summaryrefslogtreecommitdiff
path: root/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Common/I18n.qml
diff options
context:
space:
mode:
Diffstat (limited to 'raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Common/I18n.qml')
-rw-r--r--raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Common/I18n.qml138
1 files changed, 138 insertions, 0 deletions
diff --git a/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Common/I18n.qml b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Common/I18n.qml
new file mode 100644
index 0000000..aae0009
--- /dev/null
+++ b/raveos-theme/hyprland/theme-data/DankMaterialShell/quickshell/Common/I18n.qml
@@ -0,0 +1,138 @@
+pragma Singleton
+pragma ComponentBehavior: Bound
+
+import QtQuick
+import Qt.labs.folderlistmodel
+import Quickshell
+import Quickshell.Io
+
+Singleton {
+ id: root
+
+ property string _resolvedLocale: "en"
+
+ readonly property string _rawLocale: SessionData.locale === "" ? Qt.locale().name : SessionData.locale
+ 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 var _rtlLanguages: ["ar", "he", "iw", "fa", "ur", "ps", "sd", "dv", "yi", "ku"]
+ readonly property bool isRtl: _rtlLanguages.includes(_lang)
+
+ readonly property url translationsFolder: Qt.resolvedUrl("../translations/poexports")
+
+ readonly property alias folder: dir.folder
+ property var presentLocales: ({
+ "en": Qt.locale("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._loadPresentLocales();
+ 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._resolvedLocale}' (${Object.keys(root.translations).length} contexts)`);
+ } catch (e) {
+ console.warn(`I18n: Error parsing '${root._resolvedLocale}':`, e, "- falling back to English");
+ root._fallbackToEnglish();
+ }
+ }
+
+ onLoadFailed: error => {
+ console.warn(`I18n: Failed to load '${root._resolvedLocale}' (${error}), ` + "falling back to English");
+ root._fallbackToEnglish();
+ }
+ }
+
+ function locale() {
+ if (SessionData.timeLocale)
+ return Qt.locale(SessionData.timeLocale);
+ return Qt.locale();
+ }
+
+ function _loadPresentLocales() {
+ if (Object.keys(presentLocales).length > 1) {
+ return; // already loaded
+ }
+ for (let i = 0; i < dir.count; i++) {
+ const name = dir.get(i, "fileName"); // e.g. "zh_CN.json"
+ if (name && name.endsWith(".json")) {
+ const shortName = name.slice(0, -5);
+ presentLocales[shortName] = Qt.locale(shortName);
+ }
+ }
+ }
+
+ function _pickTranslation() {
+ for (let i = 0; i < _candidates.length; i++) {
+ const cand = _candidates[i];
+ if (presentLocales[cand] === undefined)
+ continue;
+ _resolvedLocale = cand;
+ useLocale(cand, cand.startsWith("en") ? "" : translationsFolder + "/" + cand + ".json");
+ return;
+ }
+
+ _resolvedLocale = "en";
+ _fallbackToEnglish();
+ }
+
+ function useLocale(localeTag, fileUrl) {
+ _resolvedLocale = localeTag || "en";
+ _selectedPath = fileUrl;
+ translationsLoaded = false;
+ translations = ({});
+ console.info(`I18n: Using locale '${localeTag}' from ${fileUrl}`);
+ }
+
+ function _fallbackToEnglish() {
+ _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;
+ }
+}