forked from Shinonome/dots-hyprland
147 lines
4.8 KiB
QML
147 lines
4.8 KiB
QML
pragma Singleton
|
|
|
|
import QtQuick
|
|
import Quickshell
|
|
import Quickshell.Io
|
|
import qs.modules.common
|
|
|
|
Singleton {
|
|
id: root
|
|
|
|
property var translations: ({})
|
|
property var generatedTranslations: ({})
|
|
property var availableLanguages: ["en_US"]
|
|
property var availableGeneratedLanguages: []
|
|
property var allAvailableLanguages: {
|
|
const combined = new Set([...root.availableLanguages, ...root.availableGeneratedLanguages]);
|
|
return Array.from(combined).sort();
|
|
}
|
|
property bool isScanning: scanLanguagesProcess.running
|
|
property bool isLoading: false
|
|
property string translationKeepSuffix: "/*keep*/"
|
|
property string translationsDir: Quickshell.shellPath("translations")
|
|
property string generatedTranslationsDir: Directories.shellConfig + "/translations"
|
|
|
|
property string languageCode: {
|
|
var configLang = Config?.options.language.ui ?? "auto";
|
|
|
|
if (configLang !== "auto")
|
|
return configLang;
|
|
|
|
return Qt.locale().name;
|
|
}
|
|
|
|
TranslationScanner {
|
|
id: scanLanguagesProcess
|
|
translationsDir: root.translationsDir
|
|
onLanguagesScanned: (languages) => {
|
|
root.availableLanguages = [...languages];
|
|
}
|
|
}
|
|
|
|
TranslationScanner {
|
|
id: scanGeneratedLanguagesProcess
|
|
translationsDir: root.generatedTranslationsDir
|
|
onLanguagesScanned: (languages) => {
|
|
root.availableGeneratedLanguages = [...languages];
|
|
}
|
|
}
|
|
|
|
onLanguageCodeChanged: {
|
|
print("[Translation] Language changed to", root.languageCode);
|
|
translationFileView.languageCode = root.languageCode;
|
|
generatedTranslationFileView.languageCode = root.languageCode;
|
|
translationFileView.reread();
|
|
generatedTranslationFileView.reread();
|
|
}
|
|
|
|
TranslationReader {
|
|
id: translationFileView
|
|
translationsDir: root.translationsDir
|
|
languageCode: root.languageCode
|
|
onContentLoaded: (data) => {
|
|
root.translations = data;
|
|
root.isLoading = false;
|
|
}
|
|
}
|
|
|
|
TranslationReader {
|
|
id: generatedTranslationFileView
|
|
translationsDir: root.generatedTranslationsDir
|
|
languageCode: root.languageCode
|
|
onContentLoaded: (data) => {
|
|
root.generatedTranslations = data;
|
|
root.isLoading = false;
|
|
}
|
|
}
|
|
|
|
function tr(text) {
|
|
// Special cases
|
|
if (!text) return "";
|
|
var key = text.toString();
|
|
if (root.isLoading || (!root?.translations?.hasOwnProperty(key) && !root?.generatedTranslations?.hasOwnProperty(key)))
|
|
return key;
|
|
|
|
// Normal cases
|
|
var translation = root.translations[key] || root.generatedTranslations[key] || key;
|
|
// print(key, "-> [", root.translations[key], root.generatedTranslations[key], key, "] ->", translation);
|
|
if (translation.endsWith(root.translationKeepSuffix)) {
|
|
translation = translation.substring(0, translation.length - root.translationKeepSuffix.length).trim();
|
|
}
|
|
return translation;
|
|
}
|
|
|
|
component TranslationScanner: Process {
|
|
id: translationScanner
|
|
required property string translationsDir
|
|
signal languagesScanned(var languages)
|
|
|
|
command: ["find", translationScanner.translationsDir, "-name", "*.json", "-exec", "basename", "{}", ".json", ";"]
|
|
running: true
|
|
|
|
stdout: StdioCollector {
|
|
id: languagesCollector
|
|
onStreamFinished: {
|
|
const output = languagesCollector.text;
|
|
const files = output.trim().split('\n').map(f => f.trim());
|
|
translationScanner.languagesScanned(files);
|
|
}
|
|
}
|
|
|
|
onExited: (exitCode, exitStatus) => {
|
|
if (exitCode !== 0) {
|
|
translationScanner.languagesScanned(["en_US"]);
|
|
}
|
|
}
|
|
}
|
|
|
|
component TranslationReader: FileView {
|
|
id: translationReader
|
|
required property string translationsDir
|
|
property string languageCode: root.languageCode
|
|
signal contentLoaded(var data)
|
|
|
|
function reread() { // Proper reload in case the file was incorrect before
|
|
translationReader.path = "";
|
|
translationReader.path = `${translationReader.translationsDir}/${translationReader.languageCode}.json`;
|
|
translationReader.reload();
|
|
}
|
|
path: ""
|
|
|
|
onLoaded: {
|
|
var textContent = "";
|
|
try {
|
|
textContent = text();
|
|
var jsonData = JSON.parse(textContent);
|
|
translationReader.contentLoaded(jsonData);
|
|
} catch (e) {
|
|
console.log("[Translation] Failed to load translations:", e);
|
|
translationReader.contentLoaded({});
|
|
}
|
|
}
|
|
onLoadFailed: error => {
|
|
translationReader.contentLoaded({});
|
|
}
|
|
}
|
|
}
|