diff --git a/Telegram/CMakeLists.txt b/Telegram/CMakeLists.txt index fab389b02f..4565022e3b 100644 --- a/Telegram/CMakeLists.txt +++ b/Telegram/CMakeLists.txt @@ -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 diff --git a/Telegram/SourceFiles/boxes/about_box.cpp b/Telegram/SourceFiles/boxes/about_box.cpp index f148f3c571..90d2e82cc0 100644 --- a/Telegram/SourceFiles/boxes/about_box.cpp +++ b/Telegram/SourceFiles/boxes/about_box.cpp @@ -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); diff --git a/Telegram/SourceFiles/boxes/language_box.cpp b/Telegram/SourceFiles/boxes/language_box.cpp index af16dba918..d852281a8f 100644 --- a/Telegram/SourceFiles/boxes/language_box.cpp +++ b/Telegram/SourceFiles/boxes/language_box.cpp @@ -196,7 +196,7 @@ std::pair 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 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(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); diff --git a/Telegram/SourceFiles/chat_helpers/emoji_keywords.cpp b/Telegram/SourceFiles/chat_helpers/emoji_keywords.cpp index 50465dd7ed..e2f1ddf4a4 100644 --- a/Telegram/SourceFiles/chat_helpers/emoji_keywords.cpp +++ b/Telegram/SourceFiles/chat_helpers/emoji_keywords.cpp @@ -569,7 +569,7 @@ std::vector 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()); diff --git a/Telegram/SourceFiles/chat_helpers/spellchecker_common.cpp b/Telegram/SourceFiles/chat_helpers/spellchecker_common.cpp index 8f2a8025af..9b04c3e65c 100644 --- a/Telegram/SourceFiles/chat_helpers/spellchecker_common.cpp +++ b/Telegram/SourceFiles/chat_helpers/spellchecker_common.cpp @@ -366,7 +366,7 @@ std::vector DefaultLanguages() { append(method->locale()); } append(QLocale(Platform::SystemLanguage())); - append(QLocale(Lang::LanguageIdOrDefault(Lang::Current().id()))); + append(QLocale(Lang::LanguageIdOrDefault(Lang::Id()))); return langs; } diff --git a/Telegram/SourceFiles/core/application.cpp b/Telegram/SourceFiles/core/application.cpp index bddaaf9792..58fe355b13 100644 --- a/Telegram/SourceFiles/core/application.cpp +++ b/Telegram/SourceFiles/core/application.cpp @@ -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" diff --git a/Telegram/SourceFiles/core/ui_integration.cpp b/Telegram/SourceFiles/core/ui_integration.cpp index 501491cdd2..e707d25894 100644 --- a/Telegram/SourceFiles/core/ui_integration.cpp +++ b/Telegram/SourceFiles/core/ui_integration.cpp @@ -58,6 +58,10 @@ void UiIntegration::startFontsBegin() { void UiIntegration::startFontsEnd() { } +QString UiIntegration::timeFormat() { + return cTimeFormat(); +} + std::shared_ptr UiIntegration::createLinkHandler( const EntityLinkData &data, const std::any &context) { diff --git a/Telegram/SourceFiles/core/ui_integration.h b/Telegram/SourceFiles/core/ui_integration.h index b119280b5f..c7367b8026 100644 --- a/Telegram/SourceFiles/core/ui_integration.h +++ b/Telegram/SourceFiles/core/ui_integration.h @@ -39,6 +39,7 @@ public: void startFontsBegin() override; void startFontsEnd() override; + QString timeFormat() override; std::shared_ptr createLinkHandler( const EntityLinkData &data, diff --git a/Telegram/SourceFiles/dialogs/dialogs_layout.cpp b/Telegram/SourceFiles/dialogs/dialogs_layout.cpp index 2ffb908855..4d44581b4b 100644 --- a/Telegram/SourceFiles/dialogs/dialogs_layout.cpp +++ b/Telegram/SourceFiles/dialogs/dialogs_layout.cpp @@ -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() diff --git a/Telegram/SourceFiles/history/history_item_components.cpp b/Telegram/SourceFiles/history/history_item_components.cpp index 70c76b2796..3a9fdb3c79 100644 --- a/Telegram/SourceFiles/history/history_item_components.cpp +++ b/Telegram/SourceFiles/history/history_item_components.cpp @@ -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)) diff --git a/Telegram/SourceFiles/history/history_widget.cpp b/Telegram/SourceFiles/history/history_widget.cpp index 423cf4a626..df648b179b 100644 --- a/Telegram/SourceFiles/history/history_widget.cpp +++ b/Telegram/SourceFiles/history/history_widget.cpp @@ -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() diff --git a/Telegram/SourceFiles/history/view/history_view_message.cpp b/Telegram/SourceFiles/history/view/history_view_message.cpp index 22c2d9d611..82f7bc1045 100644 --- a/Telegram/SourceFiles/history/view/history_view_message.cpp +++ b/Telegram/SourceFiles/history/view/history_view_message.cpp @@ -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) diff --git a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp index ea8ff143ad..7583e433f5 100644 --- a/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp +++ b/Telegram/SourceFiles/history/view/history_view_top_bar_widget.cpp @@ -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({}); }); diff --git a/Telegram/SourceFiles/intro/intro_code.cpp b/Telegram/SourceFiles/intro/intro_code.cpp index 3efe3c9a1c..710931dab5 100644 --- a/Telegram/SourceFiles/intro/intro_code.cpp +++ b/Telegram/SourceFiles/intro/intro_code.cpp @@ -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(); }); diff --git a/Telegram/SourceFiles/intro/intro_password_check.cpp b/Telegram/SourceFiles/intro/intro_password_check.cpp index 17b009c46d..bd67e4c478 100644 --- a/Telegram/SourceFiles/intro/intro_password_check.cpp +++ b/Telegram/SourceFiles/intro/intro_password_check.cpp @@ -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(); }); diff --git a/Telegram/SourceFiles/intro/intro_signup.cpp b/Telegram/SourceFiles/intro/intro_signup.cpp index df2d2c06db..a6e4068397 100644 --- a/Telegram/SourceFiles/intro/intro_signup.cpp +++ b/Telegram/SourceFiles/intro/intro_signup.cpp @@ -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 { diff --git a/Telegram/SourceFiles/intro/intro_step.cpp b/Telegram/SourceFiles/intro/intro_step.cpp index 47de864e48..92a627d13f 100644 --- a/Telegram/SourceFiles/intro/intro_step.cpp +++ b/Telegram/SourceFiles/intro/intro_step.cpp @@ -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 &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(); } diff --git a/Telegram/SourceFiles/intro/intro_widget.cpp b/Telegram/SourceFiles/intro/intro_widget.cpp index 9f83f59605..05777d2d1a 100644 --- a/Telegram/SourceFiles/intro/intro_widget.cpp +++ b/Telegram/SourceFiles/intro/intro_widget.cpp @@ -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) { diff --git a/Telegram/SourceFiles/lang/lang_file_parser.cpp b/Telegram/SourceFiles/lang/lang_file_parser.cpp index f1d0852dcd..b282613fea 100644 --- a/Telegram/SourceFiles/lang/lang_file_parser.cpp +++ b/Telegram/SourceFiles/lang/lang_file_parser.cpp @@ -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 +#include +#include namespace Lang { namespace { @@ -30,7 +35,7 @@ FileParser::FileParser(const QByteArray &content, Fn= 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; diff --git a/Telegram/SourceFiles/lang/lang_file_parser.h b/Telegram/SourceFiles/lang/lang_file_parser.h index f7fb1fb912..dfa009c82f 100644 --- a/Telegram/SourceFiles/lang/lang_file_parser.h +++ b/Telegram/SourceFiles/lang/lang_file_parser.h @@ -9,6 +9,9 @@ https://github.com/telegramdesktop/tdesktop/blob/master/LEGAL #include "lang/lang_keys.h" +#include +#include + namespace Lang { class FileParser { diff --git a/Telegram/SourceFiles/lang/lang_hardcoded.h b/Telegram/SourceFiles/lang/lang_hardcoded.h index 07b4bd9dc3..a0bb82d9cb 100644 --- a/Telegram/SourceFiles/lang/lang_hardcoded.h +++ b/Telegram/SourceFiles/lang/lang_hardcoded.h @@ -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 diff --git a/Telegram/SourceFiles/lang/lang_instance.cpp b/Telegram/SourceFiles/lang/lang_instance.cpp index 50cc404a6a..ae39789433 100644 --- a/Telegram/SourceFiles/lang/lang_instance.cpp +++ b/Telegram/SourceFiles/lang/lang_instance.cpp @@ -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 Viewer(ushort key) { +rpl::producer 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 diff --git a/Telegram/SourceFiles/lang/lang_instance.h b/Telegram/SourceFiles/lang/lang_instance.h index 10c5c69b4c..cb563b7b1f 100644 --- a/Telegram/SourceFiles/lang/lang_instance.h +++ b/Telegram/SourceFiles/lang/lang_instance.h @@ -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 ParseStrings( const MTPVector &strings); - base::Observable &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 _updated; + rpl::event_stream<> _updated; mutable QString _systemLanguage; @@ -144,7 +145,7 @@ private: namespace details { QString Current(ushort key); -rpl::producer Viewer(ushort key); +rpl::producer Value(ushort key); } // namespace details } // namespace Lang diff --git a/Telegram/SourceFiles/lang/lang_keys.cpp b/Telegram/SourceFiles/lang/lang_keys.cpp index 207ab92226..52766aa5cc 100644 --- a/Telegram/SourceFiles/lang/lang_keys.cpp +++ b/Telegram/SourceFiles/lang/lang_keys.cpp @@ -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())); } diff --git a/Telegram/SourceFiles/lang/lang_keys.h b/Telegram/SourceFiles/lang/lang_keys.h index 87ffd522c2..793971dd7e 100644 --- a/Telegram/SourceFiles/lang/lang_keys.h +++ b/Telegram/SourceFiles/lang/lang_keys.h @@ -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 diff --git a/Telegram/SourceFiles/lang/lang_pch.h b/Telegram/SourceFiles/lang/lang_pch.h new file mode 100644 index 0000000000..53a8114322 --- /dev/null +++ b/Telegram/SourceFiles/lang/lang_pch.h @@ -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 +#include + +#include + +#include "base/basic_types.h" diff --git a/Telegram/SourceFiles/lang/lang_tag.cpp b/Telegram/SourceFiles/lang/lang_tag.cpp index 9f8fadef46..0cf5475cb9 100644 --- a/Telegram/SourceFiles/lang/lang_tag.cpp +++ b/Telegram/SourceFiles/lang/lang_tag.cpp @@ -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, diff --git a/Telegram/SourceFiles/lang/lang_values.cpp b/Telegram/SourceFiles/lang/lang_values.cpp deleted file mode 100644 index b83ebd58c7..0000000000 --- a/Telegram/SourceFiles/lang/lang_values.cpp +++ /dev/null @@ -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" - diff --git a/Telegram/SourceFiles/lang/lang_values.h b/Telegram/SourceFiles/lang/lang_values.h index f5aba447ee..46bf7d016f 100644 --- a/Telegram/SourceFiles/lang/lang_values.h +++ b/Telegram/SourceFiles/lang/lang_values.h @@ -22,16 +22,22 @@ inline constexpr ushort TagValue(); template using S = std::decay_t()(QString()))>; -QString Current(ushort key); -rpl::producer Viewer(ushort key); +[[nodiscard]] QString Current(ushort key); +[[nodiscard]] rpl::producer Value(ushort key); +[[nodiscard]] bool IsNonDefaultPlural(ushort keyBase); template -Type ReplaceUnwrapTuple(Type accumulated, const Tuple &tuple) { +[[nodiscard]] Type ReplaceUnwrapTuple(Type accumulated, const Tuple &tuple) { return accumulated; } -template -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 - static Type Call(Type accumulated) { + [[nodiscard]] static Type Call(Type accumulated) { return accumulated; } }; @@ -59,7 +65,7 @@ struct ReplaceUnwrap<> { template struct ReplaceUnwrap { template - static Type Call( + [[nodiscard]] static Type Call( Type accumulated, const Value &value, const Values &...values) { @@ -75,9 +81,9 @@ struct ReplaceUnwrap { template struct Producer { template - static rpl::producer> Combine(ushort base, P p, Values &...values) { + [[nodiscard]] static rpl::producer> 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()...); @@ -85,7 +91,7 @@ struct Producer { } template - static S

Current(ushort base, P p, const Values &...values) { + [[nodiscard]] static S

Current(ushort base, P p, const Values &...values) { return ReplaceUnwrap::template Call( p(Lang::details::Current(base)), values...); @@ -95,12 +101,12 @@ struct Producer { template <> struct Producer<> { template - static rpl::producer> Combine(ushort base, P p) { - return Viewer(base) | rpl::map(std::move(p)); + [[nodiscard]] static rpl::producer> Combine(ushort base, P p) { + return Value(base) | rpl::map(std::move(p)); } template - static S

Current(ushort base, P p) { + [[nodiscard]] static S

Current(ushort base, P p) { return p(Lang::details::Current(base)); } }; @@ -108,19 +114,19 @@ struct Producer<> { template struct Producer { template - static rpl::producer> Combine( + [[nodiscard]] static rpl::producer> Combine( ushort base, P p, lngtag_count type, rpl::producer &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 { } template - static S

Current( + [[nodiscard]] static S

Current( ushort base, P p, lngtag_count type, diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp index d5743d6a8e..70894724f0 100644 --- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp +++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.cpp @@ -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() diff --git a/Telegram/SourceFiles/media/view/media_view_overlay_widget.h b/Telegram/SourceFiles/media/view/media_view_overlay_widget.h index edcfae7055..b1bbdc6977 100644 --- a/Telegram/SourceFiles/media/view/media_view_overlay_widget.h +++ b/Telegram/SourceFiles/media/view/media_view_overlay_widget.h @@ -63,7 +63,6 @@ using OverlayParent = Ui::RpWidget; class OverlayWidget final : public OverlayParent - , private base::Subscriber , public ClickHandlerHost , private PlaybackControls::Delegate { Q_OBJECT diff --git a/Telegram/SourceFiles/mtproto/mtp_instance.cpp b/Telegram/SourceFiles/mtproto/mtp_instance.cpp index 3725c4a8a3..3b2219bb87 100644 --- a/Telegram/SourceFiles/mtproto/mtp_instance.cpp +++ b/Telegram/SourceFiles/mtproto/mtp_instance.cpp @@ -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 { diff --git a/Telegram/SourceFiles/passport/passport_panel_controller.cpp b/Telegram/SourceFiles/passport/passport_panel_controller.cpp index e98bf16460..f4b5e0464c 100644 --- a/Telegram/SourceFiles/passport/passport_panel_controller.cpp +++ b/Telegram/SourceFiles/passport/passport_panel_controller.cpp @@ -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) { diff --git a/Telegram/SourceFiles/settings/settings_main.cpp b/Telegram/SourceFiles/settings/settings_main.cpp index 7c64f46c0d..c7d9579d50 100644 --- a/Telegram/SourceFiles/settings/settings_main.cpp +++ b/Telegram/SourceFiles/settings/settings_main.cpp @@ -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(button.get()); diff --git a/Telegram/SourceFiles/storage/localstorage.cpp b/Telegram/SourceFiles/storage/localstorage.cpp index 9091d2cae1..4a869fc0c1 100644 --- a/Telegram/SourceFiles/storage/localstorage.cpp +++ b/Telegram/SourceFiles/storage/localstorage.cpp @@ -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 @@ -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(); diff --git a/Telegram/SourceFiles/window/notifications_manager_default.cpp b/Telegram/SourceFiles/window/notifications_manager_default.cpp index 83d3aea6c0..ad4ddfa572 100644 --- a/Telegram/SourceFiles/window/notifications_manager_default.cpp +++ b/Telegram/SourceFiles/window/notifications_manager_default.cpp @@ -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); diff --git a/Telegram/SourceFiles/window/notifications_manager_default.h b/Telegram/SourceFiles/window/notifications_manager_default.h index 78d3046b2f..1950480f22 100644 --- a/Telegram/SourceFiles/window/notifications_manager_default.h +++ b/Telegram/SourceFiles/window/notifications_manager_default.h @@ -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, diff --git a/Telegram/SourceFiles/window/window_history_hider.cpp b/Telegram/SourceFiles/window/window_history_hider.cpp index 583541e42f..a989ef1a20 100644 --- a/Telegram/SourceFiles/window/window_history_hider.cpp +++ b/Telegram/SourceFiles/window/window_history_hider.cpp @@ -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); diff --git a/Telegram/cmake/td_lang.cmake b/Telegram/cmake/td_lang.cmake new file mode 100644 index 0000000000..7671377d5e --- /dev/null +++ b/Telegram/cmake/td_lang.cmake @@ -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 +) diff --git a/Telegram/cmake/td_ui.cmake b/Telegram/cmake/td_ui.cmake index 935fbc13ba..23d87ceb07 100644 --- a/Telegram/cmake/td_ui.cmake +++ b/Telegram/cmake/td_ui.cmake @@ -40,5 +40,6 @@ PUBLIC target_link_libraries(td_ui PUBLIC + tdesktop::td_lang desktop-app::lib_ui ) diff --git a/Telegram/lib_ui b/Telegram/lib_ui index 03ea7a05e6..e712f9b3de 160000 --- a/Telegram/lib_ui +++ b/Telegram/lib_ui @@ -1 +1 @@ -Subproject commit 03ea7a05e62332ee4e41d00606e9f80cfdd95f33 +Subproject commit e712f9b3de36ed387c5ab08b2b48e1984f682314