mirror of
https://github.com/AvengeMedia/DankMaterialShell.git
synced 2025-12-05 21:15:38 -05:00
116 lines
3.5 KiB
QML
116 lines
3.5 KiB
QML
pragma Singleton
|
|
pragma ComponentBehavior: Bound
|
|
import QtQuick
|
|
import Qt.labs.folderlistmodel
|
|
import Quickshell
|
|
import Quickshell.Io
|
|
|
|
Singleton {
|
|
id: root
|
|
|
|
readonly property string _rawLocale: Qt.locale().name
|
|
readonly property string _lang: _rawLocale.split(/[_-]/)[0]
|
|
readonly property var _candidates: {
|
|
const fullUnderscore = _rawLocale;
|
|
const fullHyphen = _rawLocale.replace("_", "-");
|
|
return [fullUnderscore, fullHyphen, _lang].filter(c => c && c !== "en");
|
|
}
|
|
|
|
readonly property url translationsFolder: Qt.resolvedUrl("../translations/poexports")
|
|
|
|
property string currentLocale: "en"
|
|
property var translations: ({})
|
|
property bool translationsLoaded: false
|
|
|
|
property url _selectedPath: ""
|
|
|
|
FolderListModel {
|
|
id: dir
|
|
folder: root.translationsFolder
|
|
nameFilters: ["*.json"]
|
|
showDirs: false
|
|
showDotAndDotDot: false
|
|
|
|
onStatusChanged: if (status === FolderListModel.Ready)
|
|
root._pickTranslation()
|
|
}
|
|
|
|
FileView {
|
|
id: translationLoader
|
|
path: root._selectedPath
|
|
|
|
onLoaded: {
|
|
try {
|
|
root.translations = JSON.parse(text());
|
|
root.translationsLoaded = true;
|
|
console.info(`I18n: Loaded translations for '${root.currentLocale}' ` + `(${Object.keys(root.translations).length} contexts)`);
|
|
} catch (e) {
|
|
console.warn(`I18n: Error parsing '${root.currentLocale}':`, e, "- falling back to English");
|
|
root._fallbackToEnglish();
|
|
}
|
|
}
|
|
|
|
onLoadFailed: error => {
|
|
console.warn(`I18n: Failed to load '${root.currentLocale}' (${error}), ` + "falling back to English");
|
|
root._fallbackToEnglish();
|
|
}
|
|
}
|
|
|
|
function _pickTranslation() {
|
|
const present = new Set();
|
|
for (let i = 0; i < dir.count; i++) {
|
|
const name = dir.get(i, "fileName"); // e.g. "zh_CN.json"
|
|
if (name && name.endsWith(".json")) {
|
|
present.add(name.slice(0, -5));
|
|
}
|
|
}
|
|
|
|
for (let i = 0; i < _candidates.length; i++) {
|
|
const cand = _candidates[i];
|
|
if (present.has(cand)) {
|
|
_useLocale(cand, dir.folder + "/" + cand + ".json");
|
|
return;
|
|
}
|
|
}
|
|
|
|
_fallbackToEnglish();
|
|
}
|
|
|
|
function _useLocale(localeTag, fileUrl) {
|
|
currentLocale = localeTag;
|
|
_selectedPath = fileUrl;
|
|
translationsLoaded = false;
|
|
translations = ({});
|
|
console.info(`I18n: Using locale '${localeTag}' from ${fileUrl}`);
|
|
}
|
|
|
|
function _fallbackToEnglish() {
|
|
currentLocale = "en";
|
|
_selectedPath = "";
|
|
translationsLoaded = false;
|
|
translations = ({});
|
|
console.warn("I18n: Falling back to built-in English strings");
|
|
}
|
|
|
|
function tr(term, context) {
|
|
if (!translationsLoaded || !translations)
|
|
return term;
|
|
const ctx = context || term;
|
|
if (translations[ctx] && translations[ctx][term])
|
|
return translations[ctx][term];
|
|
for (const c in translations) {
|
|
if (translations[c] && translations[c][term])
|
|
return translations[c][term];
|
|
}
|
|
return term;
|
|
}
|
|
|
|
function trContext(context, term) {
|
|
if (!translationsLoaded || !translations)
|
|
return term;
|
|
if (translations[context] && translations[context][term])
|
|
return translations[context][term];
|
|
return term;
|
|
}
|
|
}
|