From 63bd97e76f952d302dd3b38e3acc06fd8d648ff1 Mon Sep 17 00:00:00 2001 From: loner <2788892716@qq.com> Date: Sun, 19 Oct 2025 01:29:39 +0800 Subject: [PATCH] feat(i18n): Implement and refine language selection feature Introduces a language selection option in settings, allowing users to manually choose an application language or revert to automatic system locale detection. This includes UI updates, settings integration, and improved language detection logic. --- Assets/Translations/en.json | 3 +- Commons/I18n.qml | 55 ++++++++++++---------------- Modules/Settings/Tabs/GeneralTab.qml | 14 +++++-- 3 files changed, 36 insertions(+), 36 deletions(-) diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index 5c0b9e5d..783dc34b 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -76,7 +76,8 @@ }, "select": { "label": "Application Language", - "description": "Select the language used in the application's interface." + "description": "Select the language used in the application's interface.", + "auto-detect": "Automatic" } } }, diff --git a/Commons/I18n.qml b/Commons/I18n.qml index fe2ab0a6..4ec5e86f 100644 --- a/Commons/I18n.qml +++ b/Commons/I18n.qml @@ -7,10 +7,11 @@ import qs.Commons Singleton { id: root - property string debugForceLanguage: "" + property bool isLoaded: false property string langCode: "" + property string systemDetectedLangCode: "" property var availableLanguages: [] property var translations: ({}) property var fallbackTranslations: ({}) @@ -158,48 +159,40 @@ Singleton { return } - if (Settings.isDebug && debugForceLanguage !== "") { - Logger.d("I18n", `Debug mode: forcing language to "${debugForceLanguage}"`) - if (availableLanguages.includes(debugForceLanguage)) { - setLanguage(debugForceLanguage) - return - } else { - Logger.w("I18n", `Debug language "${debugForceLanguage}" not available in [${availableLanguages.join(', ')}]`) - } - } + var detectedLang = "" - // Check for user-defined language setting - if (Settings.data.general.language !== "" && availableLanguages.includes(Settings.data.general.language)) { - Logger.d("I18n", `User-defined language found: "${Settings.data.general.language}"`) - setLanguage(Settings.data.general.language) - return - } - - // Detect user's favorite locale - languages + // First, determine the system's preferred language for (var i = 0; i < Qt.locale().uiLanguages.length; i++) { const fullUserLang = Qt.locale().uiLanguages[i] - // Try full code match (such as zh CN, en US) if (availableLanguages.includes(fullUserLang)) { - Logger.d("I18n", `Exact match found: "${fullUserLang}"`) - setLanguage(fullUserLang) - return + detectedLang = fullUserLang + break } - // If full code match fails, try short code matching (such as zh, en) const shortUserLang = fullUserLang.substring(0, 2) if (availableLanguages.includes(shortUserLang)) { - Logger.d("I18n", `Short code match found: "${shortUserLang}" from "${fullUserLang}"`) - setLanguage(shortUserLang) - return + detectedLang = shortUserLang + break } - - Logger.d("I18n", `No match for system language: "${fullUserLang}"`) } - // Fallback to first available language (preferably "en" if available) - const fallbackLang = availableLanguages.includes("en") ? "en" : availableLanguages[0] - setLanguage(fallbackLang) + // If no system language is found among available languages, fallback + if (detectedLang === "") { + detectedLang = availableLanguages.includes("en") ? "en" : availableLanguages[0] + } + + root.systemDetectedLangCode = detectedLang + Logger.d("I18n", `System detected language: "${root.systemDetectedLangCode}"`) + + // Now, apply the language: user-defined, then system-detected + if (Settings.data.general.language !== "" && availableLanguages.includes(Settings.data.general.language)) { + Logger.d("I18n", `User-defined language found: "${Settings.data.general.language}"`) + setLanguage(Settings.data.general.language) + } else { + Logger.d("I18n", `No user-defined language, using system detected: "${root.systemDetectedLangCode}"`) + setLanguage(root.systemDetectedLangCode) + } } // ------------------------------------------- diff --git a/Modules/Settings/Tabs/GeneralTab.qml b/Modules/Settings/Tabs/GeneralTab.qml index 3bd5de54..40b5276d 100644 --- a/Modules/Settings/Tabs/GeneralTab.qml +++ b/Modules/Settings/Tabs/GeneralTab.qml @@ -204,13 +204,19 @@ ColumnLayout { Layout.fillWidth: true label: I18n.tr("settings.general.language.select.label") description: I18n.tr("settings.general.language.select.description") - model: I18n.availableLanguages.map(function(langCode) { + model: [ + { "key": "", "name": I18n.tr("settings.general.language.select.auto-detect") + " (" + I18n.systemDetectedLangCode + ")" } + ].concat(I18n.availableLanguages.map(function(langCode) { return { "key": langCode, "name": langCode } - }) - currentKey: Settings.data.general.language !== "" ? Settings.data.general.language : I18n.langCode + })) + currentKey: Settings.data.general.language onSelected: key => { Settings.data.general.language = key - I18n.setLanguage(key) + if (key === "") { + I18n.detectLanguage() // Re-detect system language if "Automatic" is selected + } else { + I18n.setLanguage(key) // Set specific language + } } } }