Move lang keys to td_lang library.

This commit is contained in:
John Preston 2020-09-30 12:11:44 +03:00
parent def1266216
commit 8634c1f7f3
41 changed files with 271 additions and 164 deletions

View File

@ -23,7 +23,6 @@ add_subdirectory(codegen)
include(CheckCXXSourceCompiles)
include(lib_ui/cmake/generate_styles.cmake)
include(cmake/generate_lang.cmake)
include(cmake/generate_numbers.cmake)
get_filename_component(src_loc SourceFiles REALPATH)
@ -35,6 +34,7 @@ include(cmake/lib_tgvoip.cmake)
include(cmake/lib_tgcalls.cmake)
include(cmake/td_export.cmake)
include(cmake/td_mtproto.cmake)
include(cmake/td_lang.cmake)
include(cmake/td_scheme.cmake)
include(cmake/td_ui.cmake)
@ -66,7 +66,6 @@ set(dependent_style_files
)
generate_styles(Telegram ${src_loc} "${style_files}" "${dependent_style_files}")
generate_lang(Telegram ${res_loc}/langs/lang.strings)
generate_numbers(Telegram ${res_loc}/numbers.txt)
set_target_properties(Telegram PROPERTIES AUTOMOC ON AUTORCC ON)
@ -78,6 +77,7 @@ PRIVATE
tdesktop::lib_tgvoip
tdesktop::td_export
tdesktop::td_mtproto
tdesktop::td_lang
tdesktop::td_scheme
tdesktop::td_ui
desktop-app::lib_webrtc
@ -720,23 +720,12 @@ PRIVATE
intro/intro_widget.h
lang/lang_cloud_manager.cpp
lang/lang_cloud_manager.h
lang/lang_file_parser.cpp
lang/lang_file_parser.h
lang/lang_hardcoded.h
lang/lang_instance.cpp
lang/lang_instance.h
lang/lang_keys.cpp
lang/lang_keys.h
lang/lang_numbers_animation.cpp
lang/lang_numbers_animation.h
lang/lang_tag.cpp
lang/lang_tag.h
lang/lang_text_entity.cpp
lang/lang_text_entity.h
lang/lang_translator.cpp
lang/lang_translator.h
lang/lang_values.cpp
lang/lang_values.h
main/main_account.cpp
main/main_account.h
main/main_app_config.cpp

View File

@ -125,7 +125,7 @@ QString telegramFaqLink() {
const auto langpacked = [&](const char *language) {
return result + '/' + language;
};
const auto current = Lang::Current().id();
const auto current = Lang::Id();
for (const auto language : { "de", "es", "it", "ko" }) {
if (current.startsWith(QLatin1String(language))) {
return langpacked(language);

View File

@ -196,7 +196,7 @@ std::pair<Languages, Languages> PrepareLists() {
const auto projId = [](const Language &language) {
return language.id;
};
const auto current = Lang::LanguageIdOrDefault(Lang::Current().id());
const auto current = Lang::LanguageIdOrDefault(Lang::Id());
auto official = Lang::CurrentCloudManager().languageList();
auto recent = Local::readRecentLanguages();
ranges::stable_partition(recent, [&](const Language &language) {
@ -207,13 +207,13 @@ std::pair<Languages, Languages> PrepareLists() {
const auto generate = [&] {
const auto name = (current == "#custom")
? "Custom lang pack"
: Lang::Current().name();
: Lang::GetInstance().name();
return Language{
current,
QString(),
QString(),
name,
Lang::Current().nativeName()
Lang::GetInstance().nativeName()
};
};
const auto i = ranges::find(official, current, projId);
@ -867,7 +867,7 @@ void Content::setupContent(
const Languages &official) {
using namespace rpl::mappers;
const auto current = Lang::LanguageIdOrDefault(Lang::Current().id());
const auto current = Lang::LanguageIdOrDefault(Lang::Id());
const auto content = Ui::CreateChild<Ui::VerticalLayout>(this);
const auto add = [&](const Languages &list, bool areOfficial) {
if (list.empty()) {
@ -1101,7 +1101,7 @@ void LanguageBox::prepare() {
// "#custom" is applied each time it's passed to switchToLanguage().
// So we check that the language really has changed.
const auto currentId = [] {
return Lang::LanguageIdOrDefault(Lang::Current().id());
return Lang::LanguageIdOrDefault(Lang::Id());
};
if (language.id != currentId()) {
Lang::CurrentCloudManager().switchToLanguage(language);

View File

@ -569,7 +569,7 @@ std::vector<QString> EmojiKeywords::languages() {
const auto yieldList = [&](const QStringList &list) {
result.insert(end(result), list.begin(), list.end());
};
yield(Lang::Current().id());
yield(Lang::Id());
yield(Lang::DefaultLanguageId());
yield(Lang::CurrentCloudManager().suggestedLanguage());
yield(Platform::SystemLanguage());

View File

@ -366,7 +366,7 @@ std::vector<int> DefaultLanguages() {
append(method->locale());
}
append(QLocale(Platform::SystemLanguage()));
append(QLocale(Lang::LanguageIdOrDefault(Lang::Current().id())));
append(QLocale(Lang::LanguageIdOrDefault(Lang::Id())));
return langs;
}

View File

@ -35,6 +35,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_translator.h"
#include "lang/lang_cloud_manager.h"
#include "lang/lang_hardcoded.h"
#include "lang/lang_instance.h"
#include "mainwidget.h"
#include "core/file_utilities.h"
#include "main/main_account.h"

View File

@ -58,6 +58,10 @@ void UiIntegration::startFontsBegin() {
void UiIntegration::startFontsEnd() {
}
QString UiIntegration::timeFormat() {
return cTimeFormat();
}
std::shared_ptr<ClickHandler> UiIntegration::createLinkHandler(
const EntityLinkData &data,
const std::any &context) {

View File

@ -39,6 +39,7 @@ public:
void startFontsBegin() override;
void startFontsEnd() override;
QString timeFormat() override;
std::shared_ptr<ClickHandler> createLinkHandler(
const EntityLinkData &data,

View File

@ -314,8 +314,7 @@ void paintRow(
const auto type = history->topPromotionType();
const auto custom = type.isEmpty()
? QString()
: Lang::Current().getNonDefaultValue(
kPsaBadgePrefix + type.toUtf8());
: Lang::GetNonDefaultValue(kPsaBadgePrefix + type.toUtf8());
const auto text = type.isEmpty()
? tr::lng_proxy_sponsor(tr::now)
: custom.isEmpty()

View File

@ -155,7 +155,7 @@ void HistoryMessageForwarded::create(const HistoryMessageVia *via) const {
if (fromChannel || !psaType.isEmpty()) {
auto custom = psaType.isEmpty()
? QString()
: Lang::Current().getNonDefaultValue(
: Lang::GetNonDefaultValue(
kPsaForwardedPrefix + psaType.toUtf8());
phrase = !custom.isEmpty()
? custom.replace("{channel}", textcmdLink(1, phrase))

View File

@ -2233,8 +2233,7 @@ void HistoryWidget::showAboutTopPromotion() {
const auto type = _history->topPromotionType();
const auto custom = type.isEmpty()
? QString()
: Lang::Current().getNonDefaultValue(
kPsaAboutPrefix + type.toUtf8());
: Lang::GetNonDefaultValue(kPsaAboutPrefix + type.toUtf8());
const auto text = type.isEmpty()
? tr::lng_proxy_sponsor_about(tr::now, Ui::Text::RichLangValue)
: custom.isEmpty()

View File

@ -1438,8 +1438,7 @@ ClickHandlerPtr Message::psaTooltipLink() const {
const auto handler = [=] {
const auto custom = type.isEmpty()
? QString()
: Lang::Current().getNonDefaultValue(
kPsaTooltipPrefix + type.toUtf8());
: Lang::GetNonDefaultValue(kPsaTooltipPrefix + type.toUtf8());
auto text = Ui::Text::RichLangValue(
(custom.isEmpty()
? tr::lng_tooltip_psa_default(tr::now)

View File

@ -67,9 +67,13 @@ TopBarWidget::TopBarWidget(
, _menuToggle(this, st::topBarMenuToggle)
, _titlePeerText(st::windowMinWidth / 3)
, _onlineUpdater([=] { updateOnlineDisplay(); }) {
subscribe(Lang::Current().updated(), [=] { refreshLang(); });
setAttribute(Qt::WA_OpaquePaintEvent);
Lang::Updated(
) | rpl::start_with_next([=] {
refreshLang();
}, lifetime());
_forward->setClickedCallback([=] { _forwardSelection.fire({}); });
_forward->setWidthChangedCallback([=] { updateControlsGeometry(); });
_sendNow->setClickedCallback([=] { _sendNowSelection.fire({}); });

View File

@ -89,7 +89,10 @@ CodeWidget::CodeWidget(
, _callTimeout(getData()->callTimeout)
, _callLabel(this, st::introDescription)
, _checkRequestTimer([=] { checkRequest(); }) {
subscribe(Lang::Current().updated(), [this] { refreshLang(); });
Lang::Updated(
) | rpl::start_with_next([=] {
refreshLang();
}, lifetime());
connect(_code, &CodeInput::changed, [=] { codeChanged(); });
_noTelegramCode->addClickHandler([=] { noTelegramCode(); });

View File

@ -40,7 +40,10 @@ PasswordCheckWidget::PasswordCheckWidget(
, _toPassword(this, tr::lng_signin_try_password(tr::now)) {
Expects(!!_request);
subscribe(Lang::Current().updated(), [=] { refreshLang(); });
Lang::Updated(
) | rpl::start_with_next([=] {
refreshLang();
}, lifetime());
_toRecover->addClickHandler([=] { toRecover(); });
_toPassword->addClickHandler([=] { toPassword(); });

View File

@ -35,7 +35,11 @@ SignupWidget::SignupWidget(
, _first(this, st::introName, tr::lng_signup_firstname())
, _last(this, st::introName, tr::lng_signup_lastname())
, _invertOrder(langFirstNameGoesSecond()) {
subscribe(Lang::Current().updated(), [this] { refreshLang(); });
Lang::Updated(
) | rpl::start_with_next([=] {
refreshLang();
}, lifetime());
if (_invertOrder) {
setTabOrder(_last, _first);
} else {

View File

@ -11,6 +11,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "storage/localstorage.h"
#include "storage/storage_account.h"
#include "lang/lang_keys.h"
#include "lang/lang_instance.h"
#include "lang/lang_cloud_manager.h"
#include "main/main_account.h"
#include "main/main_domain.h"
@ -175,11 +176,11 @@ void Step::createSession(
QImage photo,
const QVector<MTPDialogFilter> &filters) {
// Save the default language if we've suggested some other and user ignored it.
const auto currentId = Lang::Current().id();
const auto currentId = Lang::Id();
const auto defaultId = Lang::DefaultLanguageId();
const auto suggested = Lang::CurrentCloudManager().suggestedLanguage();
if (currentId.isEmpty() && !suggested.isEmpty() && suggested != defaultId) {
Lang::Current().switchToId(Lang::DefaultLanguage());
Lang::GetInstance().switchToId(Lang::DefaultLanguage());
Local::writeLangPack();
}

View File

@ -14,6 +14,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "intro/intro_signup.h"
#include "intro/intro_password_check.h"
#include "lang/lang_keys.h"
#include "lang/lang_instance.h"
#include "lang/lang_cloud_manager.h"
#include "storage/localstorage.h"
#include "main/main_account.h"
@ -126,7 +127,10 @@ Widget::Widget(
_changeLanguage->finishAnimating();
}
subscribe(Lang::Current().updated(), [this] { refreshLang(); });
Lang::Updated(
) | rpl::start_with_next([=] {
refreshLang();
}, lifetime());
show();
showControls();
@ -241,7 +245,7 @@ void Widget::createLanguageLink() {
updateControlsGeometry();
};
const auto currentId = Lang::LanguageIdOrDefault(Lang::Current().id());
const auto currentId = Lang::LanguageIdOrDefault(Lang::Id());
const auto defaultId = Lang::DefaultLanguageId();
const auto suggested = Lang::CurrentCloudManager().suggestedLanguage();
if (currentId != defaultId) {

View File

@ -8,6 +8,11 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_file_parser.h"
#include "base/parse_helper.h"
#include "ui/integration.h"
#include <QtCore/QTextStream>
#include <QtCore/QFile>
#include <QtCore/QFileInfo>
namespace Lang {
namespace {
@ -30,7 +35,7 @@ FileParser::FileParser(const QByteArray &content, Fn<void(QLatin1String key, con
void FileParser::parse() {
if (_content.isEmpty()) {
error(qsl("Got empty lang file content"));
error(u"Got empty lang file content"_q);
return;
}
@ -72,21 +77,21 @@ bool FileParser::readKeyValue(const char *&from, const char *end) {
auto key = QLatin1String(nameStart, from - nameStart);
if (from == end || *from != '"') {
return error(qsl("Expected quote after key name '%1'!").arg(key));
return error(u"Expected quote after key name '%1'!"_q.arg(key));
}
++from;
if (!skipWhitespaces(from, end)) {
return error(qsl("Unexpected end of file in key '%1'!").arg(key));
return error(u"Unexpected end of file in key '%1'!"_q.arg(key));
}
if (*from != '=') {
return error(qsl("'=' expected in key '%1'!").arg(key));
return error(u"'=' expected in key '%1'!"_q.arg(key));
}
if (!skipWhitespaces(++from, end)) {
return error(qsl("Unexpected end of file in key '%1'!").arg(key));
return error(u"Unexpected end of file in key '%1'!"_q.arg(key));
}
if (*from != '"') {
return error(qsl("Expected string after '=' in key '%1'!").arg(key));
return error(u"Expected string after '=' in key '%1'!"_q.arg(key));
}
auto skipping = false;
@ -105,11 +110,11 @@ bool FileParser::readKeyValue(const char *&from, const char *end) {
const char *start = ++from;
while (from < end && *from != '"') {
if (*from == '\n') {
return error(qsl("Unexpected end of string in key '%1'!").arg(key));
return error(u"Unexpected end of string in key '%1'!"_q.arg(key));
}
if (*from == '\\') {
if (from + 1 >= end) {
return error(qsl("Unexpected end of file in key '%1'!").arg(key));
return error(u"Unexpected end of file in key '%1'!"_q.arg(key));
}
if (*(from + 1) == '"' || *(from + 1) == '\\') {
if (from > start) appendValue(start, from - start);
@ -123,17 +128,17 @@ bool FileParser::readKeyValue(const char *&from, const char *end) {
++from;
}
if (from >= end) {
return error(qsl("Unexpected end of file in key '%1'!").arg(key));
return error(u"Unexpected end of file in key '%1'!"_q.arg(key));
}
if (from > start) {
appendValue(start, from - start);
}
if (!skipWhitespaces(++from, end)) {
return error(qsl("Unexpected end of file in key '%1'!").arg(key));
return error(u"Unexpected end of file in key '%1'!"_q.arg(key));
}
if (*from != ';') {
return error(qsl("';' expected after \"value\" in key '%1'!").arg(key));
return error(u"';' expected after \"value\" in key '%1'!"_q.arg(key));
}
skipWhitespaces(++from, end);
@ -150,18 +155,18 @@ bool FileParser::readKeyValue(const char *&from, const char *end) {
QByteArray FileParser::ReadFile(const QString &absolutePath, const QString &relativePath) {
QFile file(QFileInfo(relativePath).exists() ? relativePath : absolutePath);
if (!file.open(QIODevice::ReadOnly)) {
LOG(("Lang Error: Could not open file at '%1' ('%2')").arg(relativePath).arg(absolutePath));
Ui::Integration::Instance().writeLogEntry(u"Lang Error: Could not open file at '%1' ('%2')"_q.arg(relativePath).arg(absolutePath));
return QByteArray();
}
if (file.size() > kLangFileLimit) {
LOG(("Lang Error: File is too big: %1").arg(file.size()));
Ui::Integration::Instance().writeLogEntry(u"Lang Error: File is too big: %1"_q.arg(file.size()));
return QByteArray();
}
constexpr auto kCodecMagicSize = 3;
auto codecMagic = file.read(kCodecMagicSize);
if (codecMagic.size() < kCodecMagicSize) {
LOG(("Lang Error: Found bad file at '%1' ('%2')").arg(relativePath).arg(absolutePath));
Ui::Integration::Instance().writeLogEntry(u"Lang Error: Found bad file at '%1' ('%2')"_q.arg(relativePath).arg(absolutePath));
return QByteArray();
}
file.seek(0);
@ -172,11 +177,11 @@ QByteArray FileParser::ReadFile(const QString &absolutePath, const QString &rela
stream.setCodec("UTF-16");
auto string = stream.readAll();
if (stream.status() != QTextStream::Ok) {
LOG(("Lang Error: Could not read UTF-16 data from '%1' ('%2')").arg(relativePath).arg(absolutePath));
Ui::Integration::Instance().writeLogEntry(u"Lang Error: Could not read UTF-16 data from '%1' ('%2')"_q.arg(relativePath).arg(absolutePath));
return QByteArray();
}
if (string.isEmpty()) {
LOG(("Lang Error: Empty UTF-16 content in '%1' ('%2')").arg(relativePath).arg(absolutePath));
Ui::Integration::Instance().writeLogEntry(u"Lang Error: Empty UTF-16 content in '%1' ('%2')"_q.arg(relativePath).arg(absolutePath));
return QByteArray();
}
return string.toUtf8();
@ -192,7 +197,7 @@ QByteArray FileParser::ReadFile(const QString &absolutePath, const QString &rela
data = data.mid(3); // skip UTF-8 BOM
}
if (data.isEmpty()) {
LOG(("Lang Error: Empty UTF-8 content in '%1' ('%2')").arg(relativePath).arg(absolutePath));
Ui::Integration::Instance().writeLogEntry(u"Lang Error: Empty UTF-8 content in '%1' ('%2')"_q.arg(relativePath).arg(absolutePath));
return QByteArray();
}
return data;

View File

@ -9,6 +9,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_keys.h"
#include <set>
#include <QtCore/QMap>
namespace Lang {
class FileParser {

View File

@ -11,59 +11,59 @@ namespace Lang {
namespace Hard {
inline QString FavedSetTitle() {
return qsl("Favorite stickers");
return u"Favorite stickers"_q;
}
inline QString CallErrorIncompatible() {
return qsl("{user}'s app is using an incompatible protocol. They need to update their app before you can call them.");
return u"{user}'s app is using an incompatible protocol. They need to update their app before you can call them."_q;
}
inline QString ServerError() {
return qsl("Internal server error.");
return u"Internal server error."_q;
}
inline QString ClearPathFailed() {
return qsl("Clear failed :(");
return u"Clear failed :("_q;
}
inline QString ProxyConfigError() {
return qsl("The proxy you are using is not configured correctly and will be disabled. Please find another one.");
return u"The proxy you are using is not configured correctly and will be disabled. Please find another one."_q;
}
inline QString NoAuthorizationBot() {
return qsl("Could not get authorization bot.");
return u"Could not get authorization bot."_q;
}
inline QString SecureSaveError() {
return qsl("Error saving value.");
return u"Error saving value."_q;
}
inline QString SecureAcceptError() {
return qsl("Error acception form.");
return u"Error accepting form."_q;
}
inline QString PassportCorrupted() {
return qsl("It seems your Telegram Passport data was corrupted.\n\nYou can reset your Telegram Passport and restart this authorization.");
return u"It seems your Telegram Passport data was corrupted.\n\nYou can reset your Telegram Passport and restart this authorization."_q;
}
inline QString PassportCorruptedChange() {
return qsl("It seems your Telegram Passport data was corrupted.\n\nYou can reset your Telegram Passport and change your cloud password.");
return u"It seems your Telegram Passport data was corrupted.\n\nYou can reset your Telegram Passport and change your cloud password."_q;
}
inline QString PassportCorruptedReset() {
return qsl("Reset");
return u"Reset"_q;
}
inline QString PassportCorruptedResetSure() {
return qsl("Are you sure you want to reset your Telegram Passport data?");
return u"Are you sure you want to reset your Telegram Passport data?"_q;
}
inline QString UnknownSecureScanError() {
return qsl("Unknown scan read error.");
return u"Unknown scan read error."_q;
}
inline QString EmailConfirmationExpired() {
return qsl("This email confirmation has expired. Please setup two-step verification once again.");
return u"This email confirmation has expired. Please setup two-step verification once again."_q;
}
} // namespace Hard

View File

@ -258,7 +258,7 @@ void Instance::switchToId(const Language &data) {
value = PrepareTestValue(value, _id[5]);
}
if (!_derived) {
_updated.notify();
_updated.fire({});
}
}
updatePluralRules();
@ -278,7 +278,7 @@ void Instance::setBaseId(const QString &baseId, const QString &pluralId) {
void Instance::switchToCustomFile(const QString &filePath) {
if (loadFromCustomFile(filePath)) {
Local::writeLangPack();
_updated.notify();
_updated.fire({});
}
}
@ -667,9 +667,9 @@ void Instance::applyDifferenceToMe(
});
}
if (!_derived) {
_updated.notify();
_updated.fire({});
} else {
_derived->_updated.notify();
_derived->_updated.fire({});
}
}
@ -742,24 +742,38 @@ void Instance::resetValue(const QByteArray &key) {
}
}
Instance &Current() {
Instance &GetInstance() {
return Core::App().langpack();
}
QString Id() {
return GetInstance().id();
}
rpl::producer<> Updated() {
return GetInstance().updated();
}
QString GetNonDefaultValue(const QByteArray &key) {
return GetInstance().getNonDefaultValue(key);
}
namespace details {
QString Current(ushort key) {
return Lang::Current().getValue(key);
return GetInstance().getValue(key);
}
rpl::producer<QString> Viewer(ushort key) {
rpl::producer<QString> Value(ushort key) {
return rpl::single(
Lang::Current().getValue(key)
) | then(base::ObservableViewer(
Lang::Current().updated()
) | rpl::map([=] {
return Lang::Current().getValue(key);
}));
Current(key)
) | then(
Updated() | rpl::map([=] { return Current(key); })
);
}
bool IsNonDefaultPlural(ushort keyBase) {
return GetInstance().isNonDefaultPlural(keyBase);
}
} // namespace details

View File

@ -36,7 +36,7 @@ QString CustomLanguageId();
Language DefaultLanguage();
class Instance;
Instance &Current();
Instance &GetInstance();
enum class Pack {
None,
@ -79,8 +79,9 @@ public:
const MTPDlangPackDifference &difference);
static std::map<ushort, QString> ParseStrings(
const MTPVector<MTPLangPackString> &strings);
base::Observable<void> &updated() {
return _updated;
[[nodiscard]] rpl::producer<> updated() const {
return _updated.events();
}
QString getValue(ushort key) const {
@ -129,7 +130,7 @@ private:
QString _customFilePathRelative;
QByteArray _customFileContent;
int _version = 0;
base::Observable<void> _updated;
rpl::event_stream<> _updated;
mutable QString _systemLanguage;
@ -144,7 +145,7 @@ private:
namespace details {
QString Current(ushort key);
rpl::producer<QString> Viewer(ushort key);
rpl::producer<QString> Value(ushort key);
} // namespace details
} // namespace Lang

View File

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_keys.h"
#include "lang/lang_file_parser.h"
#include "ui/integration.h"
namespace {
@ -18,7 +19,7 @@ inline QString langDateMaybeWithYear(
WithoutYear withoutYear) {
const auto month = date.month();
if (month <= 0 || month > 12) {
return qsl("MONTH_ERR");
return u"MONTH_ERR"_q;
};
const auto year = date.year();
const auto current = QDate::currentDate();
@ -177,7 +178,7 @@ QString langMonthOfYear(int month, int year) {
MonthSmall(month)(tr::now),
lt_year,
QString::number(year))
: qsl("MONTH_ERR");
: u"MONTH_ERR"_q;
}
QString langMonth(const QDate &date) {
@ -196,7 +197,7 @@ QString langMonthOfYearFull(int month, int year) {
Month(month)(tr::now),
lt_year,
QString::number(year))
: qsl("MONTH_ERR");
: u"MONTH_ERR"_q;
}
QString langMonthFull(const QDate &date) {
@ -208,5 +209,23 @@ QString langMonthFull(const QDate &date) {
}
QString langDayOfWeek(int index) {
return (index > 0 && index <= 7) ? Weekday(index)(tr::now) : qsl("DAY_ERR");
return (index > 0 && index <= 7) ? Weekday(index)(tr::now) : u"DAY_ERR"_q;
}
QString langDateTime(const QDateTime &date) {
return tr::lng_mediaview_date_time(
tr::now,
lt_date,
langDayOfMonth(date.date()),
lt_time,
date.time().toString(Ui::Integration::Instance().timeFormat()));
}
QString langDateTimeFull(const QDateTime &date) {
return tr::lng_mediaview_date_time(
tr::now,
lt_date,
langDayOfMonthFull(date.date()),
lt_time,
date.time().toString(Ui::Integration::Instance().timeFormat()));
}

View File

@ -7,38 +7,30 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#pragma once
#include "lang/lang_instance.h"
#include "lang_auto.h"
#include "lang/lang_hardcoded.h"
#include "lang/lang_text_entity.h"
QString langDayOfMonth(const QDate &date);
QString langDayOfMonthFull(const QDate &date);
QString langMonthOfYear(int month, int year);
QString langMonth(const QDate &date);
QString langMonthOfYearFull(int month, int year);
QString langMonthFull(const QDate &date);
QString langDayOfWeek(int index);
[[nodiscard]] QString langDayOfMonth(const QDate &date);
[[nodiscard]] QString langDayOfMonthFull(const QDate &date);
[[nodiscard]] QString langMonthOfYear(int month, int year);
[[nodiscard]] QString langMonth(const QDate &date);
[[nodiscard]] QString langMonthOfYearFull(int month, int year);
[[nodiscard]] QString langMonthFull(const QDate &date);
[[nodiscard]] QString langDayOfWeek(int index);
inline QString langDayOfWeek(const QDate &date) {
[[nodiscard]] inline QString langDayOfWeek(const QDate &date) {
return langDayOfWeek(date.dayOfWeek());
}
inline QString langDateTime(const QDateTime &date) {
return tr::lng_mediaview_date_time(
tr::now,
lt_date,
langDayOfMonth(date.date()),
lt_time,
date.time().toString(cTimeFormat()));
}
[[nodiscard]] QString langDateTime(const QDateTime &date);
[[nodiscard]] QString langDateTimeFull(const QDateTime &date);
[[nodiscard]] bool langFirstNameGoesSecond();
inline QString langDateTimeFull(const QDateTime &date) {
return tr::lng_mediaview_date_time(
tr::now,
lt_date,
langDayOfMonthFull(date.date()),
lt_time,
date.time().toString(cTimeFormat()));
}
namespace Lang {
bool langFirstNameGoesSecond();
[[nodiscard]] QString Id();
[[nodiscard]] rpl::producer<> Updated();
[[nodiscard]] QString GetNonDefaultValue(const QByteArray &key);
} // namespace Lang

View File

@ -0,0 +1,13 @@
// This file is part of Desktop App Toolkit,
// a set of libraries for developing nice desktop applications.
//
// For license and copyright information please follow this link:
// https://github.com/desktop-app/legal/blob/master/LEGAL
//
#include <QtCore/QString>
#include <QtCore/QDateTime>
#include <rpl/rpl.h>
#include "base/basic_types.h"

View File

@ -8,6 +8,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "lang/lang_tag.h"
#include "lang/lang_keys.h"
#include "ui/text/text.h"
namespace Lang {
namespace {
@ -952,8 +953,8 @@ PluralResult Plural(
// Simplified.
const auto n = std::abs(shortened.number ? float64(shortened.number) : value);
const auto i = qFloor(n);
const auto integer = (qCeil(n) == i);
const auto i = int(std::floor(n));
const auto integer = (int(std::ceil(n)) == i);
const auto formatted = integer ? QString() : FormatDouble(n);
const auto dot = formatted.indexOf('.');
const auto fraction = (dot >= 0) ? formatted.mid(dot + 1) : QString();
@ -963,7 +964,7 @@ PluralResult Plural(
const auto t = f;
const auto useNonDefaultPlural = (ChoosePlural != ChoosePluralDefault)
&& Lang::Current().isNonDefaultPlural(keyBase);
&& Lang::details::IsNonDefaultPlural(keyBase);
const auto shift = (useNonDefaultPlural ? ChoosePlural : ChoosePluralDefault)(
(integer ? i : -1),
i,

View File

@ -1,9 +0,0 @@
/*
This file is part of Telegram Desktop,
the official desktop application for the Telegram messaging service.
For license and copyright information please follow this link:
https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
*/
#include "lang/lang_values.h"

View File

@ -22,16 +22,22 @@ inline constexpr ushort TagValue();
template <typename P>
using S = std::decay_t<decltype(std::declval<P>()(QString()))>;
QString Current(ushort key);
rpl::producer<QString> Viewer(ushort key);
[[nodiscard]] QString Current(ushort key);
[[nodiscard]] rpl::producer<QString> Value(ushort key);
[[nodiscard]] bool IsNonDefaultPlural(ushort keyBase);
template <int Index, typename Type, typename Tuple>
Type ReplaceUnwrapTuple(Type accumulated, const Tuple &tuple) {
[[nodiscard]] Type ReplaceUnwrapTuple(Type accumulated, const Tuple &tuple) {
return accumulated;
}
template <int Index, typename Type, typename Tuple, typename Tag, typename ...Tags>
Type ReplaceUnwrapTuple(
template <
int Index,
typename Type,
typename Tuple,
typename Tag,
typename ...Tags>
[[nodiscard]] Type ReplaceUnwrapTuple(
Type accumulated,
const Tuple &tuple,
Tag tag,
@ -51,7 +57,7 @@ struct ReplaceUnwrap;
template <>
struct ReplaceUnwrap<> {
template <typename Type>
static Type Call(Type accumulated) {
[[nodiscard]] static Type Call(Type accumulated) {
return accumulated;
}
};
@ -59,7 +65,7 @@ struct ReplaceUnwrap<> {
template <typename Tag, typename ...Tags>
struct ReplaceUnwrap<Tag, Tags...> {
template <typename Type, typename Value, typename ...Values>
static Type Call(
[[nodiscard]] static Type Call(
Type accumulated,
const Value &value,
const Values &...values) {
@ -75,9 +81,9 @@ struct ReplaceUnwrap<Tag, Tags...> {
template <typename ...Tags>
struct Producer {
template <typename P, typename ...Values>
static rpl::producer<S<P>> Combine(ushort base, P p, Values &...values) {
[[nodiscard]] static rpl::producer<S<P>> Combine(ushort base, P p, Values &...values) {
return rpl::combine(
Viewer(base),
Value(base),
std::move(values)...
) | rpl::map([p = std::move(p)](auto tuple) {
return ReplaceUnwrapTuple<1>(p(std::get<0>(tuple)), tuple, TagValue<Tags>()...);
@ -85,7 +91,7 @@ struct Producer {
}
template <typename P, typename ...Values>
static S<P> Current(ushort base, P p, const Values &...values) {
[[nodiscard]] static S<P> Current(ushort base, P p, const Values &...values) {
return ReplaceUnwrap<Tags...>::template Call(
p(Lang::details::Current(base)),
values...);
@ -95,12 +101,12 @@ struct Producer {
template <>
struct Producer<> {
template <typename P>
static rpl::producer<S<P>> Combine(ushort base, P p) {
return Viewer(base) | rpl::map(std::move(p));
[[nodiscard]] static rpl::producer<S<P>> Combine(ushort base, P p) {
return Value(base) | rpl::map(std::move(p));
}
template <typename P>
static S<P> Current(ushort base, P p) {
[[nodiscard]] static S<P> Current(ushort base, P p) {
return p(Lang::details::Current(base));
}
};
@ -108,19 +114,19 @@ struct Producer<> {
template <typename ...Tags>
struct Producer<lngtag_count, Tags...> {
template <typename P, typename ...Values>
static rpl::producer<S<P>> Combine(
[[nodiscard]] static rpl::producer<S<P>> Combine(
ushort base,
P p,
lngtag_count type,
rpl::producer<float64> &count,
Values &...values) {
return rpl::combine(
Viewer(base),
Viewer(base + 1),
Viewer(base + 2),
Viewer(base + 3),
Viewer(base + 4),
Viewer(base + 5),
Value(base),
Value(base + 1),
Value(base + 2),
Value(base + 3),
Value(base + 4),
Value(base + 5),
std::move(count),
std::move(values)...
) | rpl::map([base, type, p = std::move(p)](auto tuple) {
@ -148,7 +154,7 @@ struct Producer<lngtag_count, Tags...> {
}
template <typename P, typename ...Values>
static S<P> Current(
[[nodiscard]] static S<P> Current(
ushort base,
P p,
lngtag_count type,

View File

@ -321,7 +321,10 @@ OverlayWidget::OverlayWidget()
, _stateAnimation([=](crl::time now) { return stateAnimationCallback(now); })
, _dropdown(this, st::mediaviewDropdownMenu)
, _dropdownShowTimer(this) {
subscribe(Lang::Current().updated(), [this] { refreshLang(); });
Lang::Updated(
) | rpl::start_with_next([=] {
refreshLang();
}, lifetime());
_lastPositiveVolume = (Core::App().settings().videoVolume() > 0.)
? Core::App().settings().videoVolume()

View File

@ -63,7 +63,6 @@ using OverlayParent = Ui::RpWidget;
class OverlayWidget final
: public OverlayParent
, private base::Subscriber
, public ClickHandlerHost
, private PlaybackControls::Delegate {
Q_OBJECT

View File

@ -1661,15 +1661,15 @@ DcId Instance::mainDcId() const {
}
QString Instance::systemLangCode() const {
return Lang::Current().systemLangCode();
return Lang::GetInstance().systemLangCode();
}
QString Instance::cloudLangCode() const {
return Lang::Current().cloudLangCode(Lang::Pack::Current);
return Lang::GetInstance().cloudLangCode(Lang::Pack::Current);
}
QString Instance::langPackName() const {
return Lang::Current().langPackName();
return Lang::GetInstance().langPackName();
}
rpl::producer<> Instance::writeKeysRequests() const {

View File

@ -302,7 +302,7 @@ EditDocumentScheme GetDocumentScheme(
if (i == end(config.languagesByCountryCode)) {
return QString();
}
return Lang::Current().getNonDefaultValue(
return Lang::GetNonDefaultValue(
kLanguageNamePrefix + i->second.toUtf8());
};
result.additionalHeader = [=](const QString &countryCode) {

View File

@ -24,6 +24,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "data/data_cloud_themes.h"
#include "data/data_chat_filters.h"
#include "lang/lang_keys.h"
#include "lang/lang_instance.h"
#include "storage/localstorage.h"
#include "main/main_session.h"
#include "main/main_session_settings.h"
@ -48,10 +49,10 @@ void SetupLanguageButton(
container,
tr::lng_settings_language(),
rpl::single(
Lang::Current().id()
Lang::GetInstance().id()
) | rpl::then(
Lang::Current().idChanges()
) | rpl::map([] { return Lang::Current().nativeName(); }),
Lang::GetInstance().idChanges()
) | rpl::map([] { return Lang::GetInstance().nativeName(); }),
icon ? st::settingsSectionButton : st::settingsButton,
icon ? &st::settingsIconLanguage : nullptr);
const auto guard = Ui::CreateChild<base::binary_guard>(button.get());

View File

@ -25,6 +25,7 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
#include "main/main_account.h"
#include "main/main_session.h"
#include "window/themes/window_theme.h"
#include "lang/lang_instance.h"
#include "facades.h"
#include <QtCore/QDirIterator>
@ -1092,12 +1093,12 @@ void readLangPack() {
auto data = QByteArray();
langpack.stream >> data;
if (langpack.stream.status() == QDataStream::Ok) {
Lang::Current().fillFromSerialized(data, langpack.version);
Lang::GetInstance().fillFromSerialized(data, langpack.version);
}
}
void writeLangPack() {
auto langpack = Lang::Current().serialize();
auto langpack = Lang::GetInstance().serialize();
if (!_langPackKey) {
_langPackKey = GenerateKey(_basePath);
writeSettings();

View File

@ -416,7 +416,7 @@ Widget::Widget(
QPoint startPosition,
int shift,
Direction shiftDirection)
: TWidget(Core::App().getModalParent())
: RpWidget(Core::App().getModalParent())
, _manager(manager)
, _startPosition(startPosition)
, _direction(shiftDirection)
@ -587,7 +587,10 @@ Notification::Notification(
, _fromScheduled(fromScheduled)
, _close(this, st::notifyClose)
, _reply(this, tr::lng_notification_reply(), st::defaultBoxButton) {
subscribe(Lang::Current().updated(), [this] { refreshLang(); });
Lang::Updated(
) | rpl::start_with_next([=] {
refreshLang();
}, lifetime());
auto position = computePosition(st::notifyMinHeight);
updateGeometry(position.x(), position.y(), st::notifyWidth, st::notifyMinHeight);

View File

@ -122,7 +122,7 @@ private:
namespace internal {
class Widget : public TWidget, protected base::Subscriber {
class Widget : public Ui::RpWidget, protected base::Subscriber {
public:
enum class Direction {
Up,

View File

@ -25,7 +25,11 @@ HistoryHider::HistoryHider(
: RpWidget(parent)
, _text(text)
, _confirm(std::move(confirm)) {
subscribe(Lang::Current().updated(), [=] { refreshLang(); });
Lang::Updated(
) | rpl::start_with_next([=] {
refreshLang();
}, lifetime());
subscribe(Global::RefPeerChooseCancel(), [=] { startHide(); });
_chooseWidth = st::historyForwardChooseFont->width(_text);

View File

@ -0,0 +1,39 @@
# This file is part of Telegram Desktop,
# the official desktop application for the Telegram messaging service.
#
# For license and copyright information please follow this link:
# https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL
add_library(td_lang OBJECT)
init_target(td_lang)
add_library(tdesktop::td_lang ALIAS td_lang)
include(cmake/generate_lang.cmake)
generate_lang(td_lang ${res_loc}/langs/lang.strings)
target_precompile_headers(td_lang PRIVATE ${src_loc}/lang/lang_pch.h)
nice_target_sources(td_lang ${src_loc}
PRIVATE
lang/lang_file_parser.cpp
lang/lang_file_parser.h
lang/lang_hardcoded.h
lang/lang_keys.cpp
lang/lang_keys.h
lang/lang_pch.h
lang/lang_tag.cpp
lang/lang_tag.h
lang/lang_text_entity.cpp
lang/lang_text_entity.h
lang/lang_values.h
)
target_include_directories(td_lang
PUBLIC
${src_loc}
)
target_link_libraries(td_lang
PUBLIC
desktop-app::lib_ui
)

View File

@ -40,5 +40,6 @@ PUBLIC
target_link_libraries(td_ui
PUBLIC
tdesktop::td_lang
desktop-app::lib_ui
)

@ -1 +1 @@
Subproject commit 03ea7a05e62332ee4e41d00606e9f80cfdd95f33
Subproject commit e712f9b3de36ed387c5ab08b2b48e1984f682314