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.
This commit is contained in:
loner
2025-10-19 01:29:39 +08:00
parent 80443bb74e
commit 63bd97e76f
3 changed files with 36 additions and 36 deletions
+2 -1
View File
@@ -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"
}
}
},
+24 -31
View File
@@ -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)
}
}
// -------------------------------------------
+10 -4
View File
@@ -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
}
}
}
}