From f8acbf53eaaaa94c7682069e61f5dd507e0caf80 Mon Sep 17 00:00:00 2001 From: brvphoenix <30111323+brvphoenix@users.noreply.github.com> Date: Tue, 8 Nov 2022 09:14:56 +0800 Subject: [PATCH] Unify the way to generate the language list in WebUI and GUI --- src/base/utils/misc.cpp | 90 ++++++++++++++++++ src/base/utils/misc.h | 2 + src/gui/optionsdialog.cpp | 98 +------------------- src/webui/webapplication.cpp | 25 ++++- src/webui/www/private/views/preferences.html | 72 +++----------- 5 files changed, 133 insertions(+), 154 deletions(-) diff --git a/src/base/utils/misc.cpp b/src/base/utils/misc.cpp index 01d81e1782..e9803f36ca 100644 --- a/src/base/utils/misc.cpp +++ b/src/base/utils/misc.cpp @@ -53,6 +53,8 @@ #include #include +#include +#include #include #include #include @@ -403,6 +405,94 @@ QString Utils::Misc::getUserIDString() return uid; } +QString Utils::Misc::languageToLocalizedString(const QString &localeStr) +{ + if (localeStr.startsWith(u"eo", Qt::CaseInsensitive)) + { + // QLocale doesn't work with that locale. Esperanto isn't a "real" language. + return C_LOCALE_ESPERANTO; + } + + if (localeStr.startsWith(u"ltg", Qt::CaseInsensitive)) + { + // QLocale doesn't work with that locale. + return C_LOCALE_LATGALIAN; + } + + const QLocale locale {localeStr}; + switch (locale.language()) + { + case QLocale::Arabic: return C_LOCALE_ARABIC; + case QLocale::Armenian: return C_LOCALE_ARMENIAN; + case QLocale::Azerbaijani: return C_LOCALE_AZERBAIJANI; + case QLocale::Basque: return C_LOCALE_BASQUE; + case QLocale::Bulgarian: return C_LOCALE_BULGARIAN; + case QLocale::Byelorussian: return C_LOCALE_BYELORUSSIAN; + case QLocale::Catalan: return C_LOCALE_CATALAN; + case QLocale::Chinese: + switch (locale.country()) + { + case QLocale::China: return C_LOCALE_CHINESE_SIMPLIFIED; + case QLocale::HongKong: return C_LOCALE_CHINESE_TRADITIONAL_HK; + default: return C_LOCALE_CHINESE_TRADITIONAL_TW; + } + case QLocale::Croatian: return C_LOCALE_CROATIAN; + case QLocale::Czech: return C_LOCALE_CZECH; + case QLocale::Danish: return C_LOCALE_DANISH; + case QLocale::Dutch: return C_LOCALE_DUTCH; + case QLocale::English: + switch (locale.country()) + { + case QLocale::Australia: return C_LOCALE_ENGLISH_AUSTRALIA; + case QLocale::UnitedKingdom: return C_LOCALE_ENGLISH_UNITEDKINGDOM; + default: return C_LOCALE_ENGLISH; + } + case QLocale::Estonian: return C_LOCALE_ESTONIAN; + case QLocale::Finnish: return C_LOCALE_FINNISH; + case QLocale::French: return C_LOCALE_FRENCH; + case QLocale::Galician: return C_LOCALE_GALICIAN; + case QLocale::Georgian: return C_LOCALE_GEORGIAN; + case QLocale::German: return C_LOCALE_GERMAN; + case QLocale::Greek: return C_LOCALE_GREEK; + case QLocale::Hebrew: return C_LOCALE_HEBREW; + case QLocale::Hindi: return C_LOCALE_HINDI; + case QLocale::Hungarian: return C_LOCALE_HUNGARIAN; + case QLocale::Icelandic: return C_LOCALE_ICELANDIC; + case QLocale::Indonesian: return C_LOCALE_INDONESIAN; + case QLocale::Italian: return C_LOCALE_ITALIAN; + case QLocale::Japanese: return C_LOCALE_JAPANESE; + case QLocale::Korean: return C_LOCALE_KOREAN; + case QLocale::Latvian: return C_LOCALE_LATVIAN; + case QLocale::Lithuanian: return C_LOCALE_LITHUANIAN; + case QLocale::Malay: return C_LOCALE_MALAY; + case QLocale::Mongolian: return C_LOCALE_MONGOLIAN; + case QLocale::NorwegianBokmal: return C_LOCALE_NORWEGIAN; + case QLocale::Occitan: return C_LOCALE_OCCITAN; + case QLocale::Persian: return C_LOCALE_PERSIAN; + case QLocale::Polish: return C_LOCALE_POLISH; + case QLocale::Portuguese: + if (locale.country() == QLocale::Brazil) + return C_LOCALE_PORTUGUESE_BRAZIL; + return C_LOCALE_PORTUGUESE; + case QLocale::Romanian: return C_LOCALE_ROMANIAN; + case QLocale::Russian: return C_LOCALE_RUSSIAN; + case QLocale::Serbian: return C_LOCALE_SERBIAN; + case QLocale::Slovak: return C_LOCALE_SLOVAK; + case QLocale::Slovenian: return C_LOCALE_SLOVENIAN; + case QLocale::Spanish: return C_LOCALE_SPANISH; + case QLocale::Swedish: return C_LOCALE_SWEDISH; + case QLocale::Thai: return C_LOCALE_THAI; + case QLocale::Turkish: return C_LOCALE_TURKISH; + case QLocale::Ukrainian: return C_LOCALE_UKRAINIAN; + case QLocale::Uzbek: return C_LOCALE_UZBEK; + case QLocale::Vietnamese: return C_LOCALE_VIETNAMESE; + default: + const QString lang = QLocale::languageToString(locale.language()); + qWarning() << "Unrecognized language name: " << lang; + return lang; + } +} + QString Utils::Misc::parseHtmlLinks(const QString &rawText) { QString result = rawText; diff --git a/src/base/utils/misc.h b/src/base/utils/misc.h index 95da08afd4..fc1eac40d6 100644 --- a/src/base/utils/misc.h +++ b/src/base/utils/misc.h @@ -85,6 +85,8 @@ namespace Utils::Misc QString userFriendlyDuration(qlonglong seconds, qlonglong maxCap = -1); QString getUserIDString(); + QString languageToLocalizedString(const QString &localeStr); + #ifdef Q_OS_WIN Path windowsSystemPath(); diff --git a/src/gui/optionsdialog.cpp b/src/gui/optionsdialog.cpp index d4068e26ab..affc679e27 100644 --- a/src/gui/optionsdialog.cpp +++ b/src/gui/optionsdialog.cpp @@ -52,8 +52,8 @@ #include "base/rss/rss_session.h" #include "base/torrentfileguard.h" #include "base/torrentfileswatcher.h" -#include "base/unicodestrings.h" #include "base/utils/fs.h" +#include "base/utils/misc.h" #include "base/utils/net.h" #include "base/utils/password.h" #include "base/utils/random.h" @@ -89,81 +89,6 @@ namespace return ret; } - QString languageToLocalizedString(const QLocale &locale) - { - switch (locale.language()) - { - case QLocale::Arabic: return C_LOCALE_ARABIC; - case QLocale::Armenian: return C_LOCALE_ARMENIAN; - case QLocale::Azerbaijani: return C_LOCALE_AZERBAIJANI; - case QLocale::Basque: return C_LOCALE_BASQUE; - case QLocale::Bulgarian: return C_LOCALE_BULGARIAN; - case QLocale::Byelorussian: return C_LOCALE_BYELORUSSIAN; - case QLocale::Catalan: return C_LOCALE_CATALAN; - case QLocale::Chinese: - switch (locale.country()) - { - case QLocale::China: return C_LOCALE_CHINESE_SIMPLIFIED; - case QLocale::HongKong: return C_LOCALE_CHINESE_TRADITIONAL_HK; - default: return C_LOCALE_CHINESE_TRADITIONAL_TW; - } - case QLocale::Croatian: return C_LOCALE_CROATIAN; - case QLocale::Czech: return C_LOCALE_CZECH; - case QLocale::Danish: return C_LOCALE_DANISH; - case QLocale::Dutch: return C_LOCALE_DUTCH; - case QLocale::English: - switch (locale.country()) - { - case QLocale::Australia: return C_LOCALE_ENGLISH_AUSTRALIA; - case QLocale::UnitedKingdom: return C_LOCALE_ENGLISH_UNITEDKINGDOM; - default: return C_LOCALE_ENGLISH; - } - case QLocale::Estonian: return C_LOCALE_ESTONIAN; - case QLocale::Finnish: return C_LOCALE_FINNISH; - case QLocale::French: return C_LOCALE_FRENCH; - case QLocale::Galician: return C_LOCALE_GALICIAN; - case QLocale::Georgian: return C_LOCALE_GEORGIAN; - case QLocale::German: return C_LOCALE_GERMAN; - case QLocale::Greek: return C_LOCALE_GREEK; - case QLocale::Hebrew: return C_LOCALE_HEBREW; - case QLocale::Hindi: return C_LOCALE_HINDI; - case QLocale::Hungarian: return C_LOCALE_HUNGARIAN; - case QLocale::Icelandic: return C_LOCALE_ICELANDIC; - case QLocale::Indonesian: return C_LOCALE_INDONESIAN; - case QLocale::Italian: return C_LOCALE_ITALIAN; - case QLocale::Japanese: return C_LOCALE_JAPANESE; - case QLocale::Korean: return C_LOCALE_KOREAN; - case QLocale::Latvian: return C_LOCALE_LATVIAN; - case QLocale::Lithuanian: return C_LOCALE_LITHUANIAN; - case QLocale::Malay: return C_LOCALE_MALAY; - case QLocale::Mongolian: return C_LOCALE_MONGOLIAN; - case QLocale::NorwegianBokmal: return C_LOCALE_NORWEGIAN; - case QLocale::Occitan: return C_LOCALE_OCCITAN; - case QLocale::Persian: return C_LOCALE_PERSIAN; - case QLocale::Polish: return C_LOCALE_POLISH; - case QLocale::Portuguese: - if (locale.country() == QLocale::Brazil) - return C_LOCALE_PORTUGUESE_BRAZIL; - return C_LOCALE_PORTUGUESE; - case QLocale::Romanian: return C_LOCALE_ROMANIAN; - case QLocale::Russian: return C_LOCALE_RUSSIAN; - case QLocale::Serbian: return C_LOCALE_SERBIAN; - case QLocale::Slovak: return C_LOCALE_SLOVAK; - case QLocale::Slovenian: return C_LOCALE_SLOVENIAN; - case QLocale::Spanish: return C_LOCALE_SPANISH; - case QLocale::Swedish: return C_LOCALE_SWEDISH; - case QLocale::Thai: return C_LOCALE_THAI; - case QLocale::Turkish: return C_LOCALE_TURKISH; - case QLocale::Ukrainian: return C_LOCALE_UKRAINIAN; - case QLocale::Uzbek: return C_LOCALE_UZBEK; - case QLocale::Vietnamese: return C_LOCALE_VIETNAMESE; - default: - const QString lang = QLocale::languageToString(locale.language()); - qWarning() << "Unrecognized language name: " << lang; - return lang; - } - } - class WheelEventEater final : public QObject { public: @@ -1315,25 +1240,8 @@ void OptionsDialog::initializeLanguageCombo() const QStringList langFiles = langDir.entryList(QStringList(u"qbittorrent_*.qm"_qs), QDir::Files); for (const QString &langFile : langFiles) { - QString localeStr = langFile.mid(12); // remove "qbittorrent_" - localeStr.chop(3); // Remove ".qm" - QString languageName; - if (localeStr.startsWith(u"eo", Qt::CaseInsensitive)) - { - // QLocale doesn't work with that locale. Esperanto isn't a "real" language. - languageName = C_LOCALE_ESPERANTO; - } - else if (localeStr.startsWith(u"ltg", Qt::CaseInsensitive)) - { - // QLocale doesn't work with that locale. - languageName = C_LOCALE_LATGALIAN; - } - else - { - QLocale locale(localeStr); - languageName = languageToLocalizedString(locale); - } - m_ui->comboI18n->addItem(/*QIcon(":/icons/flags/"+country+".svg"), */ languageName, localeStr); + const QString localeStr = langFile.section(u"_"_qs, 1, -1).section(u"."_qs, 0, 0); // remove "qbittorrent_" and ".qm" + m_ui->comboI18n->addItem(/*QIcon(":/icons/flags/"+country+".svg"), */ Utils::Misc::languageToLocalizedString(localeStr), localeStr); qDebug() << "Supported locale:" << localeStr; } } diff --git a/src/webui/webapplication.cpp b/src/webui/webapplication.cpp index d35a48c878..f16e6e8122 100644 --- a/src/webui/webapplication.cpp +++ b/src/webui/webapplication.cpp @@ -32,6 +32,7 @@ #include #include +#include #include #include #include @@ -112,6 +113,22 @@ namespace return u"no-store"_qs; } + + QString createLanguagesOptionsHtml() + { + // List language files + const QDir langDir {u":/www/translations"_qs}; + const QStringList langFiles = langDir.entryList(QStringList(u"webui_*.qm"_qs), QDir::Files); + QStringList languages; + for (const QString &langFile : langFiles) + { + const QString localeStr = langFile.section(u"_"_qs, 1, -1).section(u"."_qs, 0, 0); // remove "webui_" and ".qm" + languages << u""_qs.arg(localeStr, Utils::Misc::languageToLocalizedString(localeStr)); + qDebug() << "Supported locale:" << localeStr; + } + + return languages.join(u'\n'); + } } WebApplication::WebApplication(IApplication *app, QObject *parent) @@ -472,13 +489,17 @@ void WebApplication::sendFile(const Path &path) const QMimeType mimeType = QMimeDatabase().mimeTypeForFileNameAndData(path.data(), data); const bool isTranslatable = !m_isAltUIUsed && mimeType.inherits(u"text/plain"_qs); - // Translate the file if (isTranslatable) { auto dataStr = QString::fromUtf8(data); + // Translate the file translateDocument(dataStr); - data = dataStr.toUtf8(); + // Add the language options + if (path == (m_rootFolder / Path(PRIVATE_FOLDER) / Path(u"views/preferences.html"_qs))) + dataStr.replace(u"${LANGUAGE_OPTIONS}"_qs, createLanguagesOptionsHtml()); + + data = dataStr.toUtf8(); m_translatedFiles[path] = {data, mimeType.name(), lastModified}; // caching translated file } diff --git a/src/webui/www/private/views/preferences.html b/src/webui/www/private/views/preferences.html index 78f1b42c58..22bddb687c 100644 --- a/src/webui/www/private/views/preferences.html +++ b/src/webui/www/private/views/preferences.html @@ -666,62 +666,7 @@ QBT_TR(Language)QBT_TR[CONTEXT=OptionsDialog] @@ -1408,6 +1353,7 @@ updateWebUICustomHTTPHeadersSettings: updateWebUICustomHTTPHeadersSettings, updateWebUIReverseProxySettings: updateWebUIReverseProxySettings, updateDynDnsSettings: updateDynDnsSettings, + updateWebuiLocaleSelect: updateWebuiLocaleSelect, registerDynDns: registerDynDns, applyPreferences: applyPreferences }; @@ -1737,6 +1683,18 @@ }).send(); }; + const updateWebuiLocaleSelect = (selected) => { + let languages = []; + for (let i = 0; i < $('locale_select').options.length; i++) + languages.push($('locale_select').options[i].value); + + if (!languages.includes(selected)) { + const lang = selected.slice(0, selected.indexOf('_')); + selected = languages.includes(lang) ? lang : 'en'; + } + $('locale_select').setProperty('value', selected); + }; + const loadPreferences = function() { const url = 'api/v2/app/preferences'; new Request.JSON({ @@ -2013,7 +1971,7 @@ // Web UI tab // Language - $('locale_select').setProperty('value', ((pref.locale === "en_US") ? "en" : pref.locale)); + updateWebuiLocaleSelect(pref.locale); $('performanceWarning').setProperty('checked', pref.performance_warning); // HTTP Server