From 31db1950873814564ad30d7b77e16c205d64659b Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Tue, 23 Sep 2025 22:39:38 -0400 Subject: [PATCH 01/15] First stab at i18n --- Assets/Translations/en.json | 33 ++++ Assets/Translations/fr.json | 17 ++ Commons/I18n.qml | 252 +++++++++++++++++++++++++++ Commons/Settings.qml | 2 + Modules/Settings/SettingsPanel.qml | 6 +- Modules/Settings/Tabs/BarTab.qml | 2 +- Modules/Settings/Tabs/GeneralTab.qml | 24 +-- Widgets/NText.qml | 6 +- 8 files changed, 322 insertions(+), 20 deletions(-) create mode 100644 Assets/Translations/en.json create mode 100644 Assets/Translations/fr.json create mode 100644 Commons/I18n.qml diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json new file mode 100644 index 00000000..9da205e0 --- /dev/null +++ b/Assets/Translations/en.json @@ -0,0 +1,33 @@ +{ + "settings": { + "general": { + "title": "General", + + "profile": { + "section": { + "label": "Profile", + "description": "Edit your user details and avatar." + }, + "picture": { + "label": "{user}'s Profile picture", + "description": "Your profile picture that appears throughout the interface." + } + }, + + "ui": { + "section": { + "label": "User interface", + "description": "Customize the look, feel, and behavior of the interface." + }, + "dim-desktop": { + "label": "Dim desktop", + "description": "Dim the desktop when panels or menus are open." + }, + "border-radius": { + "label": "Border radius", + "description": "Controls the corner roundness of windows, buttons, and other elements." + } + } + } + } +} diff --git a/Assets/Translations/fr.json b/Assets/Translations/fr.json new file mode 100644 index 00000000..92fa46a5 --- /dev/null +++ b/Assets/Translations/fr.json @@ -0,0 +1,17 @@ +{ + "settings": { + "general": { + "title": "General", + "profile": { + "section": { + "label": "Profile", + "description": "Modifiez vos informations d'utilisateur et votre avatar." + }, + "picture": { + "label": "Image de profile de {user}", + "description": "Votre photo de profil qui apparaît tout au long de l'interface." + } + } + } + } +} \ No newline at end of file diff --git a/Commons/I18n.qml b/Commons/I18n.qml new file mode 100644 index 00000000..8674150b --- /dev/null +++ b/Commons/I18n.qml @@ -0,0 +1,252 @@ +pragma Singleton + +import QtQuick +import Quickshell +import Quickshell.Io +import qs.Commons + +Singleton { + id: root + + property bool debug: true + property string debugForceLanguage: "" + + property bool isLoaded: false + property string langCode: "" + readonly property var availableLanguages: ["en", "fr"] + property var translations: ({}) + property var fallbackTranslations: ({}) + + // Signals for reactive updates + signal languageChanged(string newLanguage) + signal translationsLoaded + + // FileView to load translation files + property FileView translationFile: FileView { + id: fileView + watchChanges: true + onFileChanged: reload() + onLoaded: { + try { + var data = JSON.parse(text()) + root.translations = data + root.isLoaded = true + root.translationsLoaded() + Logger.log("I18n", `Loaded translations for "${root.langCode}"`) + } catch (e) { + Logger.error("I18n", `Failed to parse translation file: ${e}`) + setLanguage("en") + } + } + onLoadFailed: function (error) { + setLanguage("en") + Logger.error("I18n", `Failed to load translation file: ${error}`) + } + } + + // FileView to load translation files + property FileView fallbackTranslationFile: FileView { + id: fallbackFileView + watchChanges: true + onFileChanged: reload() + onLoaded: { + try { + var data = JSON.parse(text()) + root.fallbackTranslations = data + Logger.log("I18n", `Loaded english fallback translations`) + } catch (e) { + Logger.error("I18n", `Failed to parse fallback translation file: ${e}`) + } + } + onLoadFailed: function (error) { + Logger.error("I18n", `Failed to load fallback translation file: ${error}`) + } + } + + // ------------------------------------------- + function init() { + Logger.log("I18n", "Service started") + detectLanguage() + } + + // ------------------------------------------- + function detectLanguage() { + + if (debug && debugForceLanguage !== "") { + setLanguage(debugForceLanguage) + return + } + + // Detect user's favorite locale - languages + for (var i = 0; i < Qt.locale().uiLanguages.length; i++) { + const userLang = Qt.locale().uiLanguages[i].substring(0, 2) + if (availableLanguages.includes(userLang)) { + setLanguage(userLang) + return + } + } + + // Fallback to english + setLanguage("en") + } + + // ------------------------------------------- + function setLanguage(newLangCode) { + if (newLangCode !== langCode && availableLanguages.includes(newLangCode)) { + langCode = newLangCode + Logger.log("I18n", `Language set to "${langCode}"`) + languageChanged(langCode) + loadTranslations() + } + } + + // ------------------------------------------- + function loadTranslations() { + if (langCode === "") + return + + const filePath = `file://${Quickshell.shellDir}/Assets/Translations/${langCode}.json` + fileView.path = filePath + isLoaded = false + Logger.log("I18n", `Loading translations from: ${filePath}`) + + // Only load fallback translations if we are not using enlgish + if (langCode !== "en") { + fallbackFileView.path = `file://${Quickshell.shellDir}/Assets/Translations/en.json` + } + } + + // ------------------------------------------- + // Check if a translation exists + function hasTranslation(key) { + if (!isLoaded) + return false + + const keys = key.split(".") + var value = translations + + for (var i = 0; i < keys.length; i++) { + if (value && typeof value === "object" && keys[i] in value) { + value = value[keys[i]] + } else { + return false + } + } + + return typeof value === "string" + } + + // ------------------------------------------- + // Get all translation keys (useful for debugging) + function getAllKeys(obj, prefix) { + if (typeof obj === "undefined") + obj = translations + if (typeof prefix === "undefined") + prefix = "" + + var keys = [] + for (var key in (obj || {})) { + const value = obj[key] + const fullKey = prefix ? `${prefix}.${key}` : key + if (typeof value === "object" && value !== null) { + keys = keys.concat(getAllKeys(value, fullKey)) + } else if (typeof value === "string") { + keys.push(fullKey) + } + } + return keys + } + + // ------------------------------------------- + // Reload translations (useful for development) + function reload() { + Logger.log("I18n", "Reloading translations") + loadTranslations() + } + + // ------------------------------------------- + // Main translation function + function tr(key, interpolations) { + if (typeof interpolations === "undefined") + interpolations = {} + + if (!isLoaded) { + Logger.warn("I18n", "Translations not loaded yet") + return key + } + + // Navigate nested keys (e.g., "menu.file.open") + const keys = key.split(".") + + // Look-up translation in the active language + var value = translations + var notFound = false + for (var i = 0; i < keys.length; i++) { + if (value && typeof value === "object" && keys[i] in value) { + value = value[keys[i]] + } else { + if (debug) { + Logger.warn("I18n", `Translation key "${key}" not found`) + } + notFound = true + break + } + } + + // Fallback to english if not found + if (notFound) { + value = fallbackTranslations + for (var i = 0; i < keys.length; i++) { + if (value && typeof value === "object" && keys[i] in value) { + value = value[keys[i]] + } else { + // Indicate this key does not even exists in the english fallback + return `## ${key} ##` + } + } + + // Make untranslated string easy to spot + value = `${value}` + } + + if (typeof value !== "string") { + if (debug) { + Logger.warn("I18n", `Translation key "${key}" is not a string`) + } + return key + } + + // Handle interpolations (e.g., "Hello {name}!") + var result = value + for (var placeholder in interpolations) { + const regex = new RegExp(`\\{${placeholder}\\}`, 'g') + result = result.replace(regex, interpolations[placeholder]) + } + + return result + } + + // ------------------------------------------- + // Plural translation function + function trp(key, count, defaultSingular, defaultPlural, interpolations) { + if (typeof defaultSingular === "undefined") + defaultSingular = "" + if (typeof defaultPlural === "undefined") + defaultPlural = "" + if (typeof interpolations === "undefined") + interpolations = {} + + const pluralKey = count === 1 ? key : `${key}_plural` + const defaultValue = count === 1 ? defaultSingular : defaultPlural + + // Merge interpolations with count (QML doesn't support spread operator) + var finalInterpolations = { + "count": count + } + for (var prop in interpolations) { + finalInterpolations[prop] = interpolations[prop] + } + + return t(pluralKey, defaultValue, finalInterpolations) + } +} diff --git a/Commons/Settings.qml b/Commons/Settings.qml index 45b3018c..fd2a1ed1 100644 --- a/Commons/Settings.qml +++ b/Commons/Settings.qml @@ -494,6 +494,8 @@ Singleton { // ----------------------------------------------------- // Kickoff essential services function kickOffServices() { + I18n.init() + // Ensure our location singleton is created as soon as possible so we start fetching weather asap LocationService.init() diff --git a/Modules/Settings/SettingsPanel.qml b/Modules/Settings/SettingsPanel.qml index 418f4223..566f6a33 100644 --- a/Modules/Settings/SettingsPanel.qml +++ b/Modules/Settings/SettingsPanel.qml @@ -111,7 +111,7 @@ NPanel { function updateTabsModel() { let newTabs = [{ "id": SettingsPanel.Tab.General, - "label": "General", + "label": "settings.general.title", "icon": "settings-general", "source": generalTab }, { @@ -391,7 +391,7 @@ NPanel { // Tab label NText { - text: modelData.label + text: I18n.tr(modelData.label) color: tabTextColor font.pointSize: Style.fontSizeM * scaling font.weight: Style.fontWeightBold @@ -451,7 +451,7 @@ NPanel { // Main title NText { - text: root.tabsModel[currentTabIndex]?.label || "" + text: I18n.tr(root.tabsModel[currentTabIndex]?.label) || "" font.pointSize: Style.fontSizeXL * scaling font.weight: Style.fontWeightBold color: Color.mPrimary diff --git a/Modules/Settings/Tabs/BarTab.qml b/Modules/Settings/Tabs/BarTab.qml index 2049959c..daefde9c 100644 --- a/Modules/Settings/Tabs/BarTab.qml +++ b/Modules/Settings/Tabs/BarTab.qml @@ -41,7 +41,7 @@ ColumnLayout { } NHeader { - label: "Appearance" + label: "settings.appearance" description: "Customize the bar's appearance and position." } diff --git a/Modules/Settings/Tabs/GeneralTab.qml b/Modules/Settings/Tabs/GeneralTab.qml index 0e0d8932..a0286c38 100644 --- a/Modules/Settings/Tabs/GeneralTab.qml +++ b/Modules/Settings/Tabs/GeneralTab.qml @@ -10,8 +10,8 @@ ColumnLayout { id: root NHeader { - label: "Profile" - description: "Edit your user details and avatar." + label: I18n.tr("settings.general.profile.section.label") + description: I18n.tr("settings.general.profile.section.description") } // Profile section @@ -31,8 +31,10 @@ ColumnLayout { } NTextInputButton { - label: `${Quickshell.env("USER") || "user"}'s profile picture` - description: "Your profile picture that appears throughout the interface." + label: I18n.tr("settings.general.profile.picture.label", { + "user": Quickshell.env("USER" || "User") + }) + description: I18n.tr("settings.general.profile.picture.description") text: Settings.data.general.avatarImage placeholderText: "/home/user/.face" buttonIcon: "photo" @@ -47,7 +49,7 @@ ColumnLayout { NFilePicker { id: filePicker pickerType: "file" - title: "Select avatar image" + title: I18n.tr("settings.general.profile.select-avatar") //Select avatar image" initialPath: Settings.data.general.avatarImage.substr(0, Settings.data.general.avatarImage.lastIndexOf("/")) || Quickshell.env("HOME") nameFilters: ["Image files (*.jpg *.jpeg *.png *.gif *.pnm *.bmp *.face)", "All files (*)"] onAccepted: paths => Settings.data.general.avatarImage = paths[0] @@ -65,13 +67,13 @@ ColumnLayout { Layout.fillWidth: true NHeader { - label: "User interface" - description: "Customize the look, feel, and behavior of the interface." + label: I18n.tr("settings.general.ui.section.label") + description: I18n.tr("settings.general.ui.section.description") } NToggle { - label: "Dim desktop" - description: "Dim the desktop when panels or menus are open." + label: I18n.tr("settings.general.ui.dim-desktop.label") + description: I18n.tr("settings.general.ui.dim-desktop.description") checked: Settings.data.general.dimDesktop onToggled: checked => Settings.data.general.dimDesktop = checked } @@ -81,8 +83,8 @@ ColumnLayout { Layout.fillWidth: true NLabel { - label: "Border radius" - description: "Controls the corner roundness of windows, buttons, and other elements." + label: I18n.tr("settings.general.ui.border-radius.label") + description: I18n.tr("settings.general.ui.border-radius.description") } NValueSlider { diff --git a/Widgets/NText.qml b/Widgets/NText.qml index 82d533a5..a0434821 100644 --- a/Widgets/NText.qml +++ b/Widgets/NText.qml @@ -6,15 +6,11 @@ import qs.Widgets Text { id: root - font.family: Settings.data.ui.fontDefault font.pointSize: Style.fontSizeM * scaling font.weight: Style.fontWeightMedium - font.hintingPreference: Font.PreferNoHinting - font.kerning: true color: Color.mOnSurface - renderType: Text.QtRendering - verticalAlignment: Text.AlignVCenter elide: Text.ElideRight wrapMode: Text.NoWrap + verticalAlignment: Text.AlignVCenter } From 2285a3fb186ab3aeb44fb5dd89af13a0897c989a Mon Sep 17 00:00:00 2001 From: Ly-sec Date: Wed, 24 Sep 2025 13:20:49 +0200 Subject: [PATCH 02/15] SettingsWindow: add i18n support --- Assets/Translations/de.json | 658 ++++++++++++++++++++ Assets/Translations/en.json | 627 ++++++++++++++++++- Bin/check-i18n.sh | 62 ++ Commons/I18n.qml | 120 +++- Modules/Settings/SettingsPanel.qml | 26 +- Modules/Settings/Tabs/AboutTab.qml | 18 +- Modules/Settings/Tabs/AudioTab.qml | 81 +-- Modules/Settings/Tabs/BarTab.qml | 40 +- Modules/Settings/Tabs/ColorSchemeTab.qml | 81 +-- Modules/Settings/Tabs/DisplayTab.qml | 70 +-- Modules/Settings/Tabs/DockTab.qml | 24 +- Modules/Settings/Tabs/GeneralTab.qml | 46 +- Modules/Settings/Tabs/HooksTab.qml | 28 +- Modules/Settings/Tabs/LauncherTab.qml | 24 +- Modules/Settings/Tabs/LocationTab.qml | 32 +- Modules/Settings/Tabs/NetworkTab.qml | 6 +- Modules/Settings/Tabs/NotificationsTab.qml | 66 +- Modules/Settings/Tabs/ScreenRecorderTab.qml | 73 +-- Modules/Settings/Tabs/WallpaperTab.qml | 60 +- 19 files changed, 1760 insertions(+), 382 deletions(-) create mode 100644 Assets/Translations/de.json create mode 100755 Bin/check-i18n.sh diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json new file mode 100644 index 00000000..b8729fe0 --- /dev/null +++ b/Assets/Translations/de.json @@ -0,0 +1,658 @@ +{ + "settings": { + "general": { + "title": "Allgemein", + + "profile": { + "section": { + "label": "Profil", + "description": "Bearbeite deine Benutzerdaten und deinen Avatar." + }, + "picture": { + "label": "{user}s Profilbild", + "description": "Dein Profilbild, das überall in der Oberfläche angezeigt wird." + }, + "select-avatar": "Avatar-Bild auswählen" + }, + + "ui": { + "section": { + "label": "Benutzeroberfläche", + "description": "Passe Aussehen, Gefühl und Verhalten der Oberfläche an." + }, + "dim-desktop": { + "label": "Desktop abdunkeln", + "description": "Desktop abdunkeln, wenn Panels oder Menüs geöffnet sind." + }, + "border-radius": { + "label": "Eckenrundung", + "description": "Bestimmt die Rundung von Fenstern, Buttons und anderen Elementen." + }, + "animation-speed": { + "label": "Animationsgeschwindigkeit", + "description": "Globale Animationsgeschwindigkeit anpassen." + } + }, + "screen-corners": { + "section": { + "label": "Bildschirmecken", + "description": "Rundung und visuelle Effekte der Bildschirmecken anpassen." + }, + "show-corners": { + "label": "Bildschirmecken anzeigen", + "description": "Gerundete Ecken am Bildschirmrand anzeigen." + }, + "solid-black": { + "label": "Durchgehend schwarze Ecken", + "description": "Verwende durchgehend schwarz statt der Hintergrundfarbe der Statusleiste." + } + }, + "fonts": { + "section": { + "label": "Schriftarten", + "description": "Wähle die Schriftarten für die gesamte Oberfläche." + }, + "default": { + "label": "Standard-Schriftart", + "description": "Hauptschriftart für die gesamte Oberfläche.", + "placeholder": "Standard-Schriftart auswählen...", + "search-placeholder": "Schriftarten durchsuchen..." + }, + "monospace": { + "label": "Monospace-Schriftart", + "description": "Monospace-Schriftart für Zahlen und Statistiken.", + "placeholder": "Monospace-Schriftart auswählen...", + "search-placeholder": "Monospace-Schriftarten durchsuchen..." + }, + "accent": { + "label": "Akzent-Schriftart", + "description": "Große Schriftart für prominente Anzeigen.", + "placeholder": "Display-Schriftart auswählen...", + "search-placeholder": "Display-Schriftarten durchsuchen..." + } + } + }, + "audio": { + "title": "Audio", + "volumes": { + "section": { + "label": "Lautstärke", + "description": "Lautstärke-Einstellungen und Audiopegel anpassen." + }, + "output-volume": { + "label": "Ausgabe-Lautstärke", + "description": "Systemweite Lautstärke." + }, + "mute-output": { + "label": "Audio-Ausgabe stumm", + "description": "Haupt-Audio-Ausgabe des Systems stummschalten." + }, + "input-volume": { + "label": "Eingabe-Lautstärke", + "description": "Mikrofon-Eingangslautstärke." + }, + "mute-input": { + "label": "Audio-Eingabe stumm", + "description": "Standard-Audio-Eingang (Mikrofon) stummschalten." + }, + "step-size": { + "label": "Lautstärke-Schrittgröße", + "description": "Schrittgröße für Lautstärkeänderungen (Mausrad, Tastenkürzel)." + } + }, + "devices": { + "section": { + "label": "Audio-Geräte", + "description": "Verfügbare Audio-Ein- und Ausgabegeräte konfigurieren." + }, + "output-device": { + "label": "Ausgabegerät", + "description": "Gewünschtes Audio-Ausgabegerät auswählen." + }, + "input-device": { + "label": "Eingabegerät", + "description": "Gewünschtes Audio-Eingabegerät auswählen." + } + }, + "media": { + "section": { + "label": "Media Player", + "description": "Bevorzugte und ignorierte Media-Anwendungen festlegen." + }, + "primary-player": { + "label": "Haupt-Player", + "description": "Stichwort eingeben, um deinen Haupt-Player zu identifizieren.", + "placeholder": "z.B. spotify, vlc, mpv" + }, + "excluded-player": { + "label": "Ausgeschlossene Player", + "description": "Stichwörter für Player hinzufügen, die das System ignorieren soll. Jedes Stichwort in eine neue Zeile.", + "placeholder": "Teilstring eingeben und + drücken" + }, + "visualizer-type": { + "label": "Visualisierung", + "description": "Visualisierung für Media-Wiedergabe auswählen" + }, + "frame-rate": { + "label": "Bildrate", + "description": "Höhere Raten sind flüssiger, brauchen aber mehr Ressourcen." + } + } + }, + "display": { + "title": "Display", + "monitors": { + "section": { + "label": "Monitor-Einstellungen", + "description": "Skalierung und Helligkeit für jeden Bildschirm anpassen." + }, + "scale": "Skalierung", + "brightness": "Helligkeit", + "reset-scaling": "Skalierung zurücksetzen", + "brightness-step": { + "label": "Helligkeits-Schrittgröße", + "description": "Schrittgröße für Helligkeitsänderungen (Mausrad und Tastenkürzel)." + } + }, + "night-light": { + "section": { + "label": "Nachtlicht", + "description": "Blaues Licht reduzieren für besseren Schlaf und weniger Augenbelastung." + }, + "enable": { + "label": "Nachtlicht aktivieren", + "description": "Warmen Farbfilter anwenden, um blaues Licht zu reduzieren." + }, + "temperature": { + "label": "Farbtemperatur", + "description": "Farbwärme für Nacht- und Tageszeit einstellen.", + "night": "Nacht", + "day": "Tag" + }, + "auto-schedule": { + "label": "Automatische Zeiten", + "description": "Basiert auf Sonnenuntergang und -aufgang in {location} - empfohlen." + }, + "manual-schedule": { + "label": "Manuelle Zeiten", + "description": "Eigene Zeiten für Sonnenauf- und -untergang festlegen.", + "sunrise": "Sonnenaufgang", + "sunset": "Sonnenuntergang", + "select-start": "Startzeit auswählen", + "select-stop": "Endzeit auswählen" + }, + "force-activation": { + "label": "Sofort aktivieren", + "description": "Ignoriert den Zeitplan und wendet den Nachtfilter sofort an." + } + } + }, + "bar": { + "title": "Statusleiste", + "appearance": { + "section": { + "label": "Aussehen", + "description": "Aussehen und Position der Statusleiste anpassen." + }, + "position": { + "label": "Statusleistenposition", + "description": "Wähle, wo die Statusleiste auf dem Bildschirm platziert wird." + }, + "density": { + "label": "Statusleistendichte", + "description": "Innenabstand der Statusleiste für kompaktes oder geräumiges Aussehen anpassen." + }, + "background-opacity": { + "label": "Hintergrund-Transparenz", + "description": "Transparenz des Statusleistenhintergrunds anpassen." + }, + "show-capsule": { + "label": "Kapsel anzeigen", + "description": "Widget-Hintergründe anzeigen." + }, + "floating": { + "label": "Schwebende Statusleiste", + "description": "Statusleiste als schwebende 'Pille' anzeigen. Hinweis: Dadurch werden die Bildschirmecken an die Ränder verschoben." + }, + "margins": { + "label": "Ränder", + "description": "Ränder um die schwebende Statusleiste anpassen.", + "vertical": "Vertikal", + "horizontal": "Horizontal" + } + }, + "widgets": { + "section": { + "label": "Widget-Positionierung", + "description": "Widgets per Drag & Drop innerhalb jeder Sektion neu ordnen oder mit den Hinzufügen/Entfernen-Buttons verwalten." + } + }, + "monitors": { + "section": { + "label": "Monitor-Anzeige", + "description": "Statusleiste auf bestimmten Monitoren anzeigen. Standard ist alle, wenn keine ausgewählt." + } + } + }, + "dock": { + "title": "Dock", + "appearance": { + "section": { + "label": "Aussehen", + "description": "Verhalten und Aussehen des Docks anpassen." + }, + "auto-hide": { + "label": "Automatisch ausblenden", + "description": "Automatisch ausblenden, wenn nicht verwendet." + }, + "exclusive-zone": { + "label": "Exklusivbereich", + "description": "Fensterüberlappung verhindern." + }, + "background-opacity": { + "label": "Hintergrund-Transparenz", + "description": "Transparenz des Dock-Hintergrunds anpassen." + }, + "floating-distance": { + "label": "Schwebeabstand", + "description": "Schwebeabstand vom Bildschirmrand anpassen." + } + }, + "monitors": { + "section": { + "label": "Monitor-Anzeige", + "description": "Monitor auswählen, auf dem das Dock angezeigt wird." + } + } + }, + "launcher": { + "title": "Starter", + "settings": { + "section": { + "label": "Aussehen", + "description": "Verhalten und Aussehen des Starters anpassen." + }, + "position": { + "label": "Position", + "description": "Wähle, wo das Starter-Panel erscheint." + }, + "background-opacity": { + "label": "Hintergrund-Transparenz", + "description": "Transparenz des Starter-Hintergrunds anpassen." + }, + "clipboard-history": { + "label": "Zwischenablage-Verlauf aktivieren", + "description": "Auf zuvor kopierte Inhalte über den Starter zugreifen." + }, + "sort-by-usage": { + "label": "Nach Nutzung sortieren", + "description": "Wenn aktiviert, erscheinen häufig gestartete Apps zuerst in der Liste." + }, + "use-app2unit": { + "label": "App2Unit zum Starten verwenden", + "description": "Verwendet eine alternative Startmethode für bessere Prozessverwaltung und weniger Probleme." + } + } + }, + "notifications": { + "title": "Benachrichtigungen", + "settings": { + "section": { + "label": "Aussehen", + "description": "Aussehen und Verhalten von Benachrichtigungen konfigurieren." + }, + "do-not-disturb": { + "label": "Nicht stören", + "description": "Alle Benachrichtigungs-Popups deaktivieren, wenn aktiviert." + }, + "enable-osd": { + "label": "Bildschirmanzeige aktivieren", + "description": "Lautstärke- und Helligkeitsänderungen in Echtzeit anzeigen." + }, + "location": { + "label": "Position", + "description": "Wo Benachrichtigungen auf dem Bildschirm erscheinen." + }, + "low-urgency": { + "label": "Niedrige Priorität", + "description": "Wie lange Benachrichtigungen niedriger Priorität sichtbar bleiben." + }, + "normal-urgency": { + "label": "Normale Priorität", + "description": "Wie lange Benachrichtigungen normaler Priorität sichtbar bleiben." + }, + "critical-urgency": { + "label": "Kritische Priorität", + "description": "Wie lange kritische Benachrichtigungen sichtbar bleiben." + }, + "monitors-display": { + "label": "Monitor-Anzeige", + "description": "Benachrichtigungen auf bestimmten Monitoren anzeigen. Standard ist alle, wenn keine ausgewählt." + } + } + }, + "wallpaper": { + "title": "Hintergrundbild", + "settings": { + "section": { + "label": "Hintergrundbild-Einstellungen", + "description": "Verwaltung und Anzeige von Hintergrundbildern steuern." + }, + "enable-management": { + "label": "Hintergrundbild-Verwaltung aktivieren", + "description": "Hintergrundbilder mit Noctalia verwalten. Deaktivieren, wenn du eine andere Anwendung bevorzugst." + }, + "folder": { + "label": "Hintergrundbild-Ordner", + "description": "Pfad zu deinem Haupt-Hintergrundbild-Ordner.", + "tooltip": "Nach Hintergrundbild-Ordner suchen" + }, + "monitor-specific": { + "label": "Monitor-spezifische Verzeichnisse", + "description": "Anderen Hintergrundbild-Ordner für jeden Monitor festlegen.", + "tooltip": "Nach Monitor-Hintergrundbild-Ordner suchen" + }, + "select-folder": "Hintergrundbild-Ordner auswählen", + "select-monitor-folder": "Monitor-Hintergrundbild-Ordner auswählen" + }, + "look-feel": { + "section": { + "label": "Aussehen" + }, + "fill-mode": { + "label": "Füllmodus", + "description": "Wähle, wie das Bild an die Auflösung deines Monitors angepasst werden soll." + }, + "fill-color": { + "label": "Füllfarbe", + "description": "Wähle eine Füllfarbe, die hinter dem Hintergrundbild erscheinen kann." + }, + "transition-type": { + "label": "Übergangstyp", + "description": "Animationstyp beim Wechsel zwischen Hintergrundbildern." + }, + "transition-duration": { + "label": "Übergangsdauer", + "description": "Dauer der Übergangsanimationen in Sekunden." + }, + "edge-smoothness": { + "label": "Übergangskante weichzeichnen", + "description": "Wendet einen weichen, ausgefransten Effekt auf die Kante der Übergänge an." + } + }, + "automation": { + "section": { + "label": "Automatisierung" + }, + "random-wallpaper": { + "label": "Zufälliges Hintergrundbild", + "description": "Plane zufällige Hintergrundbild-Wechsel in regelmäßigen Abständen." + }, + "interval": { + "label": "Hintergrundbild-Intervall", + "description": "Wie oft Hintergrundbilder automatisch gewechselt werden." + }, + "custom-interval": { + "label": "Eigenes Intervall", + "description": "Zeit als HH:MM eingeben (z.B. 01:30)." + } + } + }, + "color-scheme": { + "title": "Farbschema", + "color-source": { + "section": { + "label": "Farbquelle", + "description": "Haupteinstellungen für Noctalias Farben." + }, + "dark-mode": { + "label": "Dunkler Modus", + "description": "Wechselt zu einem dunkleren Design für angenehmeres Sehen bei Nacht." + }, + "enable-matugen": { + "label": "Matugen aktivieren", + "description": "Automatisch Farben basierend auf deinem aktiven Hintergrundbild generieren." + } + }, + "predefined": { + "section": { + "label": "Vordefinierte Farbschemata", + "description": "Um diese Farbschemata zu verwenden, musst du Matugen deaktivieren. Mit aktiviertem Matugen werden Farben automatisch aus deinem Hintergrundbild generiert." + } + }, + "matugen": { + "section": { + "label": "Matugen-Vorlagen", + "description": "Farben auf externe Anwendungen anwenden." + }, + "ui": { + "label": "UI", + "description": "Desktop-Umgebung und UI-Toolkit-Theming.", + "gtk4": { + "label": "GTK 4 (libadwaita)", + "description": "Schreibt ~/.config/gtk-4.0/gtk.css" + }, + "gtk3": { + "label": "GTK 3", + "description": "Schreibt ~/.config/gtk-3.0/gtk.css" + }, + "qt6": { + "label": "Qt6ct", + "description": "Schreibt ~/.config/qt6ct/colors/noctalia.conf" + }, + "qt5": { + "label": "Qt5ct", + "description": "Schreibt ~/.config/qt5ct/colors/noctalia.conf" + } + }, + "terminal": { + "label": "Terminal", + "description": "Terminal-Emulator-Theming.", + "kitty": { + "label": "Kitty", + "description": "Schreibt ~/.config/kitty/themes/noctalia.conf und lädt neu", + "description-missing": "Erfordert installiertes kitty Terminal" + }, + "ghostty": { + "label": "Ghostty", + "description": "Schreibt ~/.config/ghostty/themes/noctalia und lädt neu", + "description-missing": "Erfordert installiertes ghostty Terminal" + }, + "foot": { + "label": "Foot", + "description": "Schreibt ~/.config/foot/themes/noctalia und lädt neu", + "description-missing": "Erfordert installiertes foot Terminal" + } + }, + "programs": { + "label": "Programme", + "description": "Anwendungsspezifisches Theming.", + "fuzzel": { + "label": "Fuzzel", + "description": "Schreibt ~/.config/fuzzel/themes/noctalia und lädt neu", + "description-missing": "Erfordert installierten fuzzel Launcher" + }, + "vesktop": { + "label": "Vesktop", + "description": "Schreibt ~/.config/vesktop/themes/noctalia.theme.css", + "description-missing": "Erfordert installierten vesktop Discord-Client" + }, + "pywalfox": { + "label": "Pywalfox (Firefox)", + "description": "Schreibt ~/.cache/wal/colors.json und führt pywalfox update aus", + "description-missing": "Erfordert installiertes pywalfox Paket" + } + }, + "misc": { + "label": "Sonstiges", + "description": "Weitere Konfigurationsoptionen.", + "user-templates": { + "label": "Benutzer-Vorlagen", + "description": "Benutzerdefinierte Matugen-Konfiguration aus ~/.config/matugen/config.toml aktivieren" + } + } + } + }, + "location": { + "title": "Standort", + "location": { + "section": { + "label": "Dein Standort", + "description": "Genaues Wetter und Nachtlicht-Zeitplan durch Festlegen deines Standorts erhalten." + }, + "search": { + "label": "Nach Standort suchen", + "description": "z.B. Berlin, DE", + "placeholder": "Ortsnamen eingeben" + } + }, + "weather": { + "section": { + "label": "Wetter", + "description": "Wähle deine bevorzugte Temperatureinheit." + }, + "fahrenheit": { + "label": "Temperatur in Fahrenheit (°F) anzeigen", + "description": "Temperatur in Fahrenheit statt Celsius anzeigen." + } + }, + "date-time": { + "section": { + "label": "Datum & Zeit", + "description": "Anpassen, wie Datum und Zeit angezeigt werden." + }, + "12hour-format": { + "label": "12-Stunden-Format auf dem Sperrbildschirm verwenden", + "description": "An für AM/PM-Format (z.B. 8:00 PM), aus für 24-Stunden-Format (z.B. 20:00)." + }, + "week-numbers": { + "label": "Wochennummern anzeigen", + "description": "Zeigt die Woche des Jahres (z.B. Woche 38) im Kalender an." + } + } + }, + "network": { + "title": "Netzwerk", + "section": { + "description": "Wi-Fi- und Bluetooth-Verbindungen verwalten." + }, + "wifi": { + "label": "Wi-Fi aktivieren" + }, + "bluetooth": { + "label": "Bluetooth aktivieren" + } + }, + "screen-recorder": { + "title": "Bildschirmaufnahme", + "general": { + "section": { + "label": "Allgemeine Einstellungen", + "description": "Ausgabe und Inhalt der Bildschirmaufnahme verwalten." + }, + "output-folder": { + "label": "Ausgabe-Ordner", + "description": "Ordner, in dem Bildschirmaufnahmen gespeichert werden.", + "tooltip": "Nach Ausgabe-Ordner suchen" + }, + "show-cursor": { + "label": "Cursor anzeigen", + "description": "Mauszeiger im Video aufnehmen." + }, + "select-output-folder": "Ausgabe-Ordner auswählen" + }, + "video": { + "section": { + "label": "Video-Einstellungen", + "description": "Video-Aufnahmeoptionen konfigurieren." + }, + "video-source": { + "label": "Video-Quelle", + "description": "Portal wird empfohlen, bei Artefakten versuche Screen." + }, + "frame-rate": { + "label": "Bildrate", + "description": "Ziel-Bildrate für Bildschirmaufnahmen." + }, + "video-quality": { + "label": "Video-Qualität", + "description": "Höhere Qualität führt zu größeren Dateien." + }, + "video-codec": { + "label": "Video-Codec", + "description": "h264 ist der gängigste Codec." + }, + "color-range": { + "label": "Farbbereich", + "description": "Begrenzt wird für bessere Kompatibilität empfohlen." + } + }, + "audio": { + "section": { + "label": "Audio-Einstellungen", + "description": "Audio-Aufnahmeoptionen konfigurieren." + }, + "audio-source": { + "label": "Audio-Quelle", + "description": "Audio-Quelle für die Aufnahme." + }, + "audio-codec": { + "label": "Audio-Codec", + "description": "Opus wird für beste Performance und kleinste Audio-Dateigröße empfohlen." + } + } + }, + "about": { + "title": "Über", + "noctalia": { + "section": { + "label": "Noctalia Shell", + "description": "Eine schlanke und minimalistische Desktop-Shell, durchdacht für Wayland entwickelt, gebaut mit Quickshell." + }, + "latest-version": "Neueste Version:", + "installed-version": "Installierte Version:", + "download-latest": "Neueste Version herunterladen" + }, + "contributors": { + "section": { + "label": "Mitwirkende", + "description": "Shoutout an unseren {count} großartigen Mitwirkenden!", + "description_plural": "Shoutout an unsere {count} großartigen Mitwirkenden!" + } + } + }, + "hooks": { + "title": "Hooks", + "system-hooks": { + "section": { + "label": "System-Hooks", + "description": "Befehle konfigurieren, die bei Systemereignissen ausgeführt werden." + }, + "enable": { + "label": "Hooks aktivieren", + "description": "Alle Hook-Befehle aktivieren oder deaktivieren." + } + }, + "wallpaper-changed": { + "label": "Hintergrundbild geändert", + "description": "Befehl, der ausgeführt wird, wenn das Hintergrundbild wechselt.", + "placeholder": "z.B. notify-send \"Hintergrundbild\" \"Geändert\"" + }, + "theme-changed": { + "label": "Design geändert", + "description": "Befehl, der ausgeführt wird, wenn zwischen dunklem und hellem Modus gewechselt wird.", + "placeholder": "z.B. notify-send \"Design\" \"Gewechselt\"" + }, + "info": { + "command-info": { + "label": "Hook-Befehl-Informationen", + "description": "• Befehle werden über Shell ausgeführt (sh -c)\n• Befehle laufen im Hintergrund (detached)\n• Test-Buttons führen mit aktuellen Werten aus" + }, + "parameters": { + "label": "Verfügbare Parameter", + "description": "• Hintergrundbild-Hook: $1 = Hintergrundbild-Pfad, $2 = Bildschirmname\n• Design-Wechsel-Hook: $1 = true/false (Dunkler-Modus-Status)" + } + } + } + } +} \ No newline at end of file diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index 9da205e0..0bb0e616 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -11,7 +11,8 @@ "picture": { "label": "{user}'s Profile picture", "description": "Your profile picture that appears throughout the interface." - } + }, + "select-avatar": "Select avatar image" }, "ui": { @@ -26,6 +27,630 @@ "border-radius": { "label": "Border radius", "description": "Controls the corner roundness of windows, buttons, and other elements." + }, + "animation-speed": { + "label": "Animation speed", + "description": "Adjust global animation speed." + } + }, + "screen-corners": { + "section": { + "label": "Screen corners", + "description": "Customize screen corner rounding and visual effects." + }, + "show-corners": { + "label": "Show screen corners", + "description": "Display rounded corners on the edge of the screen." + }, + "solid-black": { + "label": "Solid black corners", + "description": "Use solid black instead of the bar background color." + } + }, + "fonts": { + "section": { + "label": "Fonts", + "description": "Choose the fonts used throughout the interface." + }, + "default": { + "label": "Default font", + "description": "Main font used throughout the interface.", + "placeholder": "Select default font...", + "search-placeholder": "Search fonts..." + }, + "monospace": { + "label": "Monospaced font", + "description": "Monospaced font used for numbers and stats display.", + "placeholder": "Select monospace font...", + "search-placeholder": "Search monospace fonts..." + }, + "accent": { + "label": "Accent font", + "description": "Large font used for prominent displays.", + "placeholder": "Select display font...", + "search-placeholder": "Search display fonts..." + } + } + }, + "audio": { + "title": "Audio", + "volumes": { + "section": { + "label": "Volumes", + "description": "Adjust volume controls and audio levels." + }, + "output-volume": { + "label": "Output volume", + "description": "System-wide volume level." + }, + "mute-output": { + "label": "Mute audio output", + "description": "Mute the system's main audio output." + }, + "input-volume": { + "label": "Input volume", + "description": "Microphone input volume level." + }, + "mute-input": { + "label": "Mute audio input", + "description": "Mute the default audio input (microphone)." + }, + "step-size": { + "label": "Volume step size", + "description": "Adjust the step size for volume changes (scroll wheel, keyboard shortcuts)." + } + }, + "devices": { + "section": { + "label": "Audio devices", + "description": "Configure available audio input and output devices." + }, + "output-device": { + "label": "Output device", + "description": "Select the desired audio output device." + }, + "input-device": { + "label": "Input device", + "description": "Select the desired audio input device." + } + }, + "media": { + "section": { + "label": "Media players", + "description": "Set your preferred and ignored media applications." + }, + "primary-player": { + "label": "Primary player", + "description": "Enter a keyword to identify your main player.", + "placeholder": "e.g. spotify, vlc, mpv" + }, + "excluded-player": { + "label": "Excluded player", + "description": "Add keywords for players you want the system to ignore. Each keyword should be on a new line.", + "placeholder": "type substring and press +" + }, + "visualizer-type": { + "label": "Visualization type", + "description": "Choose a visualization type for media playback" + }, + "frame-rate": { + "label": "Frame rate", + "description": "Higher rates are smoother but use more resources." + } + } + }, + "display": { + "title": "Display", + "monitors": { + "section": { + "label": "Per-monitor settings", + "description": "Adjust scaling and brightness for each display." + }, + "scale": "Scale", + "brightness": "Brightness", + "reset-scaling": "Reset scaling", + "brightness-step": { + "label": "Brightness step size", + "description": "Adjust the step size for brightness changes (scroll wheel and keyboard shortcuts)." + } + }, + "night-light": { + "section": { + "label": "Night light", + "description": "Reduce blue light emission to help you sleep better and reduce eye strain." + }, + "enable": { + "label": "Enable night light", + "description": "Apply a warm color filter to reduce blue light emission." + }, + "temperature": { + "label": "Color temperature", + "description": "Set the color warmth for nighttime and daytime.", + "night": "Night", + "day": "Day" + }, + "auto-schedule": { + "label": "Automatic scheduling", + "description": "Based on the sunset and sunrise time in {location} - recommended." + }, + "manual-schedule": { + "label": "Manual scheduling", + "description": "Set custom times for sunrise and sunset.", + "sunrise": "Sunrise time", + "sunset": "Sunset time", + "select-start": "Select start time", + "select-stop": "Select stop time" + }, + "force-activation": { + "label": "Force activation", + "description": "Ignores the schedule and applies the night filter immediately." + } + } + }, + "bar": { + "title": "Bar", + "appearance": { + "section": { + "label": "Appearance", + "description": "Customize the bar's appearance and position." + }, + "position": { + "label": "Bar position", + "description": "Choose where to place the bar on the screen." + }, + "density": { + "label": "Bar density", + "description": "Adjust the bar's padding for a compact or spacious look." + }, + "background-opacity": { + "label": "Background opacity", + "description": "Adjust the background opacity of the bar." + }, + "show-capsule": { + "label": "Show capsule", + "description": "Show widget backgrounds." + }, + "floating": { + "label": "Floating bar", + "description": "Displays the bar as a floating 'pill'. Note: This will move the screen corners to the edges." + }, + "margins": { + "label": "Margins", + "description": "Adjust the margins around the floating bar.", + "vertical": "Vertical", + "horizontal": "Horizontal" + } + }, + "widgets": { + "section": { + "label": "Widgets positioning", + "description": "Drag and drop widgets to reorder them within each section, or use the add/remove buttons to manage widgets." + } + }, + "monitors": { + "section": { + "label": "Monitor display", + "description": "Show bar on specific monitors. Defaults to all if none are chosen." + } + } + }, + "dock": { + "title": "Dock", + "appearance": { + "section": { + "label": "Appearance", + "description": "Customize the dock's behavior and appearance." + }, + "auto-hide": { + "label": "Auto-hide", + "description": "Automatically hide when not in use." + }, + "exclusive-zone": { + "label": "Exclusive zone", + "description": "Prevent window overlap." + }, + "background-opacity": { + "label": "Background opacity", + "description": "Adjust the dock's background opacity." + }, + "floating-distance": { + "label": "Dock floating distance", + "description": "Adjust the floating distance from the screen edge." + } + }, + "monitors": { + "section": { + "label": "Monitor display", + "description": "Choose which monitor to display the dock on." + } + } + }, + "launcher": { + "title": "Launcher", + "settings": { + "section": { + "label": "Appearance", + "description": "Customize the launcher's behavior and appearance." + }, + "position": { + "label": "Position", + "description": "Choose where the launcher panel appears." + }, + "background-opacity": { + "label": "Background opacity", + "description": "Adjust the background opacity of the launcher." + }, + "clipboard-history": { + "label": "Enable clipboard history", + "description": "Access previously copied items from the launcher." + }, + "sort-by-usage": { + "label": "Sort by most used", + "description": "When enabled, frequently launched apps appear first in the list." + }, + "use-app2unit": { + "label": "Use App2Unit to launch applications", + "description": "Uses an alternative launch method to better manage app processes and prevent issues." + } + } + }, + "notifications": { + "title": "Notifications", + "settings": { + "section": { + "label": "Appearance", + "description": "Configure notifications appearance and behavior." + }, + "do-not-disturb": { + "label": "Do not disturb", + "description": "Disable all notification popups when enabled." + }, + "enable-osd": { + "label": "Enable on screen display", + "description": "Show volume and brightness changes in real-time." + }, + "location": { + "label": "Location", + "description": "Where notifications appear on screen." + }, + "low-urgency": { + "label": "Low urgency", + "description": "How long low priority notifications stay visible." + }, + "normal-urgency": { + "label": "Normal urgency", + "description": "How long normal priority notifications stay visible." + }, + "critical-urgency": { + "label": "Critical urgency", + "description": "How long critical priority notifications stay visible." + }, + "monitors-display": { + "label": "Monitors display", + "description": "Show notification on specific monitors. Defaults to all if none are chosen." + } + } + }, + "wallpaper": { + "title": "Wallpaper", + "settings": { + "section": { + "label": "Wallpaper settings", + "description": "Control how wallpapers are managed and displayed." + }, + "enable-management": { + "label": "Enable wallpaper management", + "description": "Manage wallpapers with Noctalia. Uncheck if you prefer using another application." + }, + "folder": { + "label": "Wallpaper folder", + "description": "Path to your main wallpaper folder.", + "tooltip": "Browse for wallpaper folder" + }, + "monitor-specific": { + "label": "Monitor-specific directories", + "description": "Set a different wallpaper folder for each monitor.", + "tooltip": "Browse for wallpaper folder" + }, + "select-folder": "Select wallpaper folder", + "select-monitor-folder": "Select monitor wallpaper folder" + }, + "look-feel": { + "section": { + "label": "Look & feel" + }, + "fill-mode": { + "label": "Fill mode", + "description": "Select how the image should scale to match your monitor's resolution." + }, + "fill-color": { + "label": "Fill color", + "description": "Choose a fill color that may appear behind the wallpaper." + }, + "transition-type": { + "label": "Transition type", + "description": "Animation type when switching between wallpapers." + }, + "transition-duration": { + "label": "Transition duration", + "description": "Duration of transition animations in seconds." + }, + "edge-smoothness": { + "label": "Soften transition edge", + "description": "Applies a soft, feathered effect to the edge of transitions." + } + }, + "automation": { + "section": { + "label": "Automation" + }, + "random-wallpaper": { + "label": "Random wallpaper", + "description": "Schedule random wallpaper changes at regular intervals." + }, + "interval": { + "label": "Wallpaper interval", + "description": "How often to change wallpapers automatically." + }, + "custom-interval": { + "label": "Custom interval", + "description": "Enter time as HH:MM (e.g., 01:30)." + } + } + }, + "color-scheme": { + "title": "Color scheme", + "color-source": { + "section": { + "label": "Color source", + "description": "Main settings for Noctalia's colors." + }, + "dark-mode": { + "label": "Dark mode", + "description": "Switches to a darker theme for easier viewing at night." + }, + "enable-matugen": { + "label": "Enable Matugen", + "description": "Automatically generate colors based on your active wallpaper." + } + }, + "predefined": { + "section": { + "label": "Predefined color schemes", + "description": "To use these color schemes, you must turn off Matugen. With Matugen enabled, colors are automatically generated from your wallpaper." + } + }, + "matugen": { + "section": { + "label": "Matugen templates", + "description": "Apply colors to external applications." + }, + "ui": { + "label": "UI", + "description": "Desktop environment and UI toolkit theming.", + "gtk4": { + "label": "GTK 4 (libadwaita)", + "description": "Write ~/.config/gtk-4.0/gtk.css" + }, + "gtk3": { + "label": "GTK 3", + "description": "Write ~/.config/gtk-3.0/gtk.css" + }, + "qt6": { + "label": "Qt6ct", + "description": "Write ~/.config/qt6ct/colors/noctalia.conf" + }, + "qt5": { + "label": "Qt5ct", + "description": "Write ~/.config/qt5ct/colors/noctalia.conf" + } + }, + "terminal": { + "label": "Terminal", + "description": "Terminal emulator theming.", + "kitty": { + "label": "Kitty", + "description": "Write ~/.config/kitty/themes/noctalia.conf and reload", + "description-missing": "Requires kitty terminal to be installed" + }, + "ghostty": { + "label": "Ghostty", + "description": "Write ~/.config/ghostty/themes/noctalia and reload", + "description-missing": "Requires ghostty terminal to be installed" + }, + "foot": { + "label": "Foot", + "description": "Write ~/.config/foot/themes/noctalia and reload", + "description-missing": "Requires foot terminal to be installed" + } + }, + "programs": { + "label": "Programs", + "description": "Application-specific theming.", + "fuzzel": { + "label": "Fuzzel", + "description": "Write ~/.config/fuzzel/themes/noctalia and reload", + "description-missing": "Requires fuzzel launcher to be installed" + }, + "vesktop": { + "label": "Vesktop", + "description": "Write ~/.config/vesktop/themes/noctalia.theme.css", + "description-missing": "Requires vesktop Discord client to be installed" + }, + "pywalfox": { + "label": "Pywalfox (Firefox)", + "description": "Write ~/.cache/wal/colors.json and run pywalfox update", + "description-missing": "Requires pywalfox package to be installed" + } + }, + "misc": { + "label": "Misc", + "description": "Additional configuration options.", + "user-templates": { + "label": "User templates", + "description": "Enable user-defined Matugen config from ~/.config/matugen/config.toml" + } + } + } + }, + "location": { + "title": "Location", + "location": { + "section": { + "label": "Your location", + "description": "Get accurate weather and night light scheduling by setting your location." + }, + "search": { + "label": "Search for a location", + "description": "e.g., Toronto, ON", + "placeholder": "Enter the location name" + } + }, + "weather": { + "section": { + "label": "Weather", + "description": "Choose your preferred temperature unit." + }, + "fahrenheit": { + "label": "Display temperature in Fahrenheit (°F)", + "description": "Display temperature in Fahrenheit instead of Celsius." + } + }, + "date-time": { + "section": { + "label": "Date & time", + "description": "Customize how date and time appear." + }, + "12hour-format": { + "label": "Use 12-hour time format on the lock screen", + "description": "On for AM/PM format (e.g., 8:00 PM), off for 24-hour format (e.g., 20:00)." + }, + "week-numbers": { + "label": "Show week numbers", + "description": "Displays the week of the year (e.g., Week 38) in the calendar." + } + } + }, + "network": { + "title": "Network", + "section": { + "description": "Manage Wi-Fi and Bluetooth connections." + }, + "wifi": { + "label": "Enable Wi-Fi" + }, + "bluetooth": { + "label": "Enable Bluetooth" + } + }, + "screen-recorder": { + "title": "Screen recorder", + "general": { + "section": { + "label": "General settings", + "description": "Manage screen recording output and content." + }, + "output-folder": { + "label": "Output folder", + "description": "Folder where screen recordings will be saved.", + "tooltip": "Browse for output folder" + }, + "show-cursor": { + "label": "Show cursor", + "description": "Record mouse cursor in the video." + }, + "select-output-folder": "Select output folder" + }, + "video": { + "section": { + "label": "Video settings", + "description": "Configure video recording options." + }, + "video-source": { + "label": "Video source", + "description": "Portal is recommended, if you get artifacts try Screen." + }, + "frame-rate": { + "label": "Frame rate", + "description": "Target frame rate for screen recordings." + }, + "video-quality": { + "label": "Video quality", + "description": "Higher quality results in larger file sizes." + }, + "video-codec": { + "label": "Video codec", + "description": "h264 is the most common codec." + }, + "color-range": { + "label": "Color range", + "description": "Limited is recommended for better compatibility." + } + }, + "audio": { + "section": { + "label": "Audio settings", + "description": "Configure audio recording options." + }, + "audio-source": { + "label": "Audio source", + "description": "Audio source to capture during recording." + }, + "audio-codec": { + "label": "Audio codec", + "description": "Opus is recommended for best performance and smallest audio size." + } + } + }, + "about": { + "title": "About", + "noctalia": { + "section": { + "label": "Noctalia shell", + "description": "A sleek and minimal desktop shell thoughtfully crafted for Wayland, built with Quickshell." + }, + "latest-version": "Latest version:", + "installed-version": "Installed version:", + "download-latest": "Download latest release" + }, + "contributors": { + "section": { + "label": "Contributors", + "description": "Shout-out to our {count} awesome contributor!", + "description_plural": "Shout-out to our {count} awesome contributors!" + } + } + }, + "hooks": { + "title": "Hooks", + "system-hooks": { + "section": { + "label": "System hooks", + "description": "Configure commands to be executed when system events occur." + }, + "enable": { + "label": "Enable hooks", + "description": "Enable or disable all hook commands." + } + }, + "wallpaper-changed": { + "label": "Wallpaper changed", + "description": "Command to be executed when wallpaper changes.", + "placeholder": "e.g., notify-send \"Wallpaper\" \"Changed\"" + }, + "theme-changed": { + "label": "Theme changed", + "description": "Command to be executed when theme toggles between dark and light mode.", + "placeholder": "e.g., notify-send \"Theme\" \"Toggled\"" + }, + "info": { + "command-info": { + "label": "Hook Command Information", + "description": "• Commands are executed via shell (sh -c)\n• Commands run in background (detached)\n• Test buttons execute with current values" + }, + "parameters": { + "label": "Available Parameters", + "description": "• Wallpaper Hook: $1 = wallpaper path, $2 = screen name\n• Theme Toggle Hook: $1 = true/false (dark mode state)" } } } diff --git a/Bin/check-i18n.sh b/Bin/check-i18n.sh new file mode 100755 index 00000000..96f5cc45 --- /dev/null +++ b/Bin/check-i18n.sh @@ -0,0 +1,62 @@ +#!/bin/bash + +# Noctalia Shell i18n Checker +# Scans for hardcoded strings that need internationalization + +# Colors +RED='\033[0;31m' +GREEN='\033[0;32m' +YELLOW='\033[1;33m' +BLUE='\033[0;34m' +CYAN='\033[0;36m' +NC='\033[0m' + +echo -e "${BLUE}Noctalia Shell i18n Checker${NC}" +echo -e "${BLUE}===========================${NC}" + +files_with_issues=0 + +# Check a single file +check_file() { + local file="$1" + local issues=$(grep -n -E '(label|text|title|description|tooltip|placeholder):\s*"[^"]{3,}"' "$file" | grep -v 'I18n.tr') + + if [[ -n "$issues" ]]; then + echo -e "${YELLOW}$file${NC}" + echo "$issues" | sed 's/^/ /' + echo "" + return 1 + fi + return 0 +} + +echo "Scanning QML files..." +echo "" + +# Find and check QML files +qml_files=$(find . -name "*.qml" -type f \ + ! -path "./Assets/*" \ + ! -path "./Bin/*" \ + ! -path "./Shaders/*" \ + ! -path "./Helpers/*" \ + ! -path "./.git/*") + +total_files=$(echo "$qml_files" | wc -l) + +for file in $qml_files; do + if ! check_file "$file"; then + ((files_with_issues++)) + fi +done + +# Summary +echo -e "${BLUE}Summary${NC}" +echo -e "${BLUE}=======${NC}" +echo -e "Files scanned: $total_files" +echo -e "Files needing i18n: $files_with_issues" + +if [[ $files_with_issues -eq 0 ]]; then + echo -e "${GREEN}All files use I18n.tr() properly!${NC}" +else + echo -e "${YELLOW}$files_with_issues files have potential hardcoded strings${NC}" +fi \ No newline at end of file diff --git a/Commons/I18n.qml b/Commons/I18n.qml index 8674150b..23457b3d 100644 --- a/Commons/I18n.qml +++ b/Commons/I18n.qml @@ -13,7 +13,7 @@ Singleton { property bool isLoaded: false property string langCode: "" - readonly property var availableLanguages: ["en", "fr"] + property var availableLanguages: [] property var translations: ({}) property var fallbackTranslations: ({}) @@ -21,6 +21,29 @@ Singleton { signal languageChanged(string newLanguage) signal translationsLoaded + // Process to list directory contents + property Process directoryScanner: Process { + id: directoryProcess + command: ["ls", `${Quickshell.shellDir}/Assets/Translations/`] + running: false + + stdout: StdioCollector { + id: stdoutCollector + } + + onExited: function (exitCode, exitStatus) { + if (exitCode === 0) { + var output = stdoutCollector.text || "" + parseDirectoryListing(output) + } else { + Logger.error("I18n", `Failed to scan translation directory`) + // Fallback to default languages + availableLanguages = ["en"] + detectLanguage() + } + } + } + // FileView to load translation files property FileView translationFile: FileView { id: fileView @@ -44,7 +67,7 @@ Singleton { } } - // FileView to load translation files + // FileView to load fallback translation files property FileView fallbackTranslationFile: FileView { id: fallbackFileView watchChanges: true @@ -66,15 +89,84 @@ Singleton { // ------------------------------------------- function init() { Logger.log("I18n", "Service started") - detectLanguage() + scanAvailableLanguages() + } + + // ------------------------------------------- + function scanAvailableLanguages() { + Logger.log("I18n", "Scanning for available translation files...") + directoryScanner.running = true + } + + // ------------------------------------------- + function parseDirectoryListing(output) { + var languages = [] + + try { + if (!output || output.trim() === "") { + Logger.warn("I18n", "Empty directory listing output") + availableLanguages = ["en"] + detectLanguage() + return + } + + const entries = output.trim().split('\n') + + for (var i = 0; i < entries.length; i++) { + const entry = entries[i].trim() + if (entry && entry.endsWith('.json')) { + // Extract language code from filename (e.g., "en.json" -> "en") + const langCode = entry.substring(0, entry.lastIndexOf('.json')) + if (langCode.length >= 2 && langCode.length <= 5) { + // Basic validation for language codes + languages.push(langCode) + } + } + } + + // Sort languages alphabetically, but ensure "en" comes first if available + languages.sort() + const enIndex = languages.indexOf("en") + if (enIndex > 0) { + languages.splice(enIndex, 1) + languages.unshift("en") + } + + if (languages.length === 0) { + Logger.warn("I18n", "No translation files found, using fallback") + languages = ["en"] // Fallback + } + + availableLanguages = languages + Logger.log("I18n", `Found ${languages.length} available languages: ${languages.join(', ')}`) + + // Detect language after scanning + detectLanguage() + } catch (e) { + Logger.error("I18n", `Failed to parse directory listing: ${e}`) + // Fallback to default languages + availableLanguages = ["en"] + detectLanguage() + } } // ------------------------------------------- function detectLanguage() { + Logger.log("I18n", `detectLanguage() called. Available languages: [${availableLanguages.join(', ')}]`) + + if (availableLanguages.length === 0) { + Logger.warn("I18n", "No available languages found") + return + } if (debug && debugForceLanguage !== "") { - setLanguage(debugForceLanguage) - return + Logger.log("I18n", `Debug mode: forcing language to "${debugForceLanguage}"`) + if (availableLanguages.includes(debugForceLanguage)) { + setLanguage(debugForceLanguage) + return + } else { + Logger.warn("I18n", `Debug language "${debugForceLanguage}" not available in [${availableLanguages.join(', ')}]`) + } } // Detect user's favorite locale - languages @@ -86,8 +178,9 @@ Singleton { } } - // Fallback to english - setLanguage("en") + // Fallback to first available language (preferably "en" if available) + const fallbackLang = availableLanguages.includes("en") ? "en" : availableLanguages[0] + setLanguage(fallbackLang) } // ------------------------------------------- @@ -97,6 +190,8 @@ Singleton { Logger.log("I18n", `Language set to "${langCode}"`) languageChanged(langCode) loadTranslations() + } else if (!availableLanguages.includes(newLangCode)) { + Logger.warn("I18n", `Language "${newLangCode}" is not available`) } } @@ -110,8 +205,8 @@ Singleton { isLoaded = false Logger.log("I18n", `Loading translations from: ${filePath}`) - // Only load fallback translations if we are not using enlgish - if (langCode !== "en") { + // Only load fallback translations if we are not using english and english is available + if (langCode !== "en" && availableLanguages.includes("en")) { fallbackFileView.path = `file://${Quickshell.shellDir}/Assets/Translations/en.json` } } @@ -194,7 +289,7 @@ Singleton { } // Fallback to english if not found - if (notFound) { + if (notFound && availableLanguages.includes("en") && langCode !== "en") { value = fallbackTranslations for (var i = 0; i < keys.length; i++) { if (value && typeof value === "object" && keys[i] in value) { @@ -207,6 +302,9 @@ Singleton { // Make untranslated string easy to spot value = `${value}` + } else if (notFound) { + // No fallback available + return `## ${key} ##` } if (typeof value !== "string") { @@ -247,6 +345,6 @@ Singleton { finalInterpolations[prop] = interpolations[prop] } - return t(pluralKey, defaultValue, finalInterpolations) + return tr(pluralKey, finalInterpolations) } } diff --git a/Modules/Settings/SettingsPanel.qml b/Modules/Settings/SettingsPanel.qml index 566f6a33..fbef5378 100644 --- a/Modules/Settings/SettingsPanel.qml +++ b/Modules/Settings/SettingsPanel.qml @@ -116,67 +116,67 @@ NPanel { "source": generalTab }, { "id": SettingsPanel.Tab.Bar, - "label": "Bar", + "label": "settings.bar.title", "icon": "settings-bar", "source": barTab }, { "id": SettingsPanel.Tab.Dock, - "label": "Dock", + "label": "settings.dock.title", "icon": "settings-dock", "source": dockTab }, { "id": SettingsPanel.Tab.Launcher, - "label": "Launcher", + "label": "settings.launcher.title", "icon": "settings-launcher", "source": launcherTab }, { "id": SettingsPanel.Tab.Audio, - "label": "Audio", + "label": "settings.audio.title", "icon": "settings-audio", "source": audioTab }, { "id": SettingsPanel.Tab.Display, - "label": "Display", + "label": "settings.display.title", "icon": "settings-display", "source": displayTab }, { "id": SettingsPanel.Tab.Notifications, - "label": "Notifications", + "label": "settings.notifications.title", "icon": "settings-notifications", "source": notificationsTab }, { "id": SettingsPanel.Tab.Network, - "label": "Network", + "label": "settings.network.title", "icon": "settings-network", "source": networkTab }, { "id": SettingsPanel.Tab.Location, - "label": "Location", + "label": "settings.location.title", "icon": "settings-location", "source": locationTab }, { "id": SettingsPanel.Tab.ColorScheme, - "label": "Color scheme", + "label": "settings.color-scheme.title", "icon": "settings-color-scheme", "source": colorSchemeTab }, { "id": SettingsPanel.Tab.Wallpaper, - "label": "Wallpaper", + "label": "settings.wallpaper.title", "icon": "settings-wallpaper", "source": wallpaperTab }, { "id": SettingsPanel.Tab.ScreenRecorder, - "label": "Screen recorder", + "label": "settings.screen-recorder.title", "icon": "settings-screen-recorder", "source": screenRecorderTab }, { "id": SettingsPanel.Tab.Hooks, - "label": "Hooks", + "label": "settings.hooks.title", "icon": "settings-hooks", "source": hooksTab }, { "id": SettingsPanel.Tab.About, - "label": "About", + "label": "settings.about.title", "icon": "settings-about", "source": aboutTab }] diff --git a/Modules/Settings/Tabs/AboutTab.qml b/Modules/Settings/Tabs/AboutTab.qml index e7336d24..1a4610d7 100644 --- a/Modules/Settings/Tabs/AboutTab.qml +++ b/Modules/Settings/Tabs/AboutTab.qml @@ -17,8 +17,8 @@ ColumnLayout { property var contributors: GitHubService.contributors NHeader { - label: "Noctalia shell" - description: "A sleek and minimal desktop shell thoughtfully crafted for Wayland, built with Quickshell." + label: I18n.tr("settings.about.noctalia.section.label") + description: I18n.tr("settings.about.noctalia.section.description") } RowLayout { @@ -31,7 +31,7 @@ ColumnLayout { columnSpacing: Style.marginS * scaling NText { - text: "Latest version:" + text: I18n.tr("settings.about.noctalia.latest-version") color: Color.mOnSurface } @@ -42,7 +42,7 @@ ColumnLayout { } NText { - text: "Installed version:" + text: I18n.tr("settings.about.noctalia.installed-version") color: Color.mOnSurface } @@ -97,7 +97,7 @@ ColumnLayout { NText { id: updateText - text: "Download latest release" + text: I18n.tr("settings.about.noctalia.download-latest") font.pointSize: Style.fontSizeL * scaling color: updateArea.containsMouse ? Color.mSurface : Color.mPrimary } @@ -123,8 +123,12 @@ ColumnLayout { } NHeader { - label: "Contributors" - description: `Shout-out to our ${root.contributors.length} awesome contributors!` + label: I18n.tr("settings.about.contributors.section.label") + description: root.contributors.length === 1 ? I18n.tr("settings.about.contributors.section.description", { + "count": root.contributors.length + }) : I18n.tr("settings.about.contributors.section.description_plural", { + "count": root.contributors.length + }) } GridView { diff --git a/Modules/Settings/Tabs/AudioTab.qml b/Modules/Settings/Tabs/AudioTab.qml index 93faa75c..d8bf87c2 100644 --- a/Modules/Settings/Tabs/AudioTab.qml +++ b/Modules/Settings/Tabs/AudioTab.qml @@ -11,8 +11,8 @@ ColumnLayout { spacing: Style.marginL * scaling NHeader { - label: "Volumes" - description: "Adjust volume controls and audio levels." + label: I18n.tr("settings.audio.volumes.section.label") + description: I18n.tr("settings.audio.volumes.section.description") } property real localVolume: AudioService.volume @@ -30,8 +30,8 @@ ColumnLayout { Layout.fillWidth: true NLabel { - label: "Output volume" - description: "System-wide volume level." + label: I18n.tr("settings.audio.volumes.output-volume.label") + description: I18n.tr("settings.audio.volumes.output-volume.description") } // Pipewire seems a bit finicky, if we spam too many volume changes it breaks easily @@ -67,8 +67,8 @@ ColumnLayout { Layout.fillWidth: true NToggle { - label: "Mute audio output" - description: "Mute the system's main audio output." + label: I18n.tr("settings.audio.volumes.mute-output.label") + description: I18n.tr("settings.audio.volumes.mute-output.description") checked: AudioService.muted onToggled: checked => { if (AudioService.sink && AudioService.sink.audio) { @@ -84,8 +84,8 @@ ColumnLayout { Layout.fillWidth: true NLabel { - label: "Input volume" - description: "Microphone input volume level." + label: I18n.tr("settings.audio.volumes.input-volume.label") + description: I18n.tr("settings.audio.volumes.input-volume.description") } NValueSlider { @@ -105,8 +105,8 @@ ColumnLayout { Layout.fillWidth: true NToggle { - label: "Mute audio input" - description: "Mute the default audio input (microphone)." + label: I18n.tr("settings.audio.volumes.mute-input.label") + description: I18n.tr("settings.audio.volumes.mute-input.description") checked: AudioService.inputMuted onToggled: checked => AudioService.setInputMuted(checked) } @@ -119,8 +119,8 @@ ColumnLayout { NSpinBox { Layout.fillWidth: true - label: "Volume step size" - description: "Adjust the step size for volume changes (scroll wheel, keyboard shortcuts)." + label: I18n.tr("settings.audio.volumes.step-size.label") + description: I18n.tr("settings.audio.volumes.step-size.description") minimum: 1 maximum: 25 value: Settings.data.audio.volumeStep @@ -141,8 +141,8 @@ ColumnLayout { spacing: Style.marginS * scaling NHeader { - label: "Audio devices" - description: "Choose your audio input and output devices." + label: I18n.tr("settings.audio.devices.section.label") + description: I18n.tr("settings.audio.devices.section.description") } // ------------------------------- @@ -157,8 +157,8 @@ ColumnLayout { Layout.bottomMargin: Style.marginL * scaling NLabel { - label: "Output device" - description: "Select the desired audio output device." + label: I18n.tr("settings.audio.devices.output-device.label") + description: I18n.tr("settings.audio.devices.output-device.description") } Repeater { @@ -184,8 +184,8 @@ ColumnLayout { Layout.fillWidth: true NLabel { - label: "Input device" - description: "Select the desired audio input device." + label: I18n.tr("settings.audio.devices.input-device.label") + description: I18n.tr("settings.audio.devices.input-device.description") } Repeater { @@ -213,15 +213,15 @@ ColumnLayout { spacing: Style.marginL * scaling NHeader { - label: "Media players" - description: "Set your preferred and ignored media applications." + label: I18n.tr("settings.audio.media.section.label") + description: I18n.tr("settings.audio.media.section.description") } // Preferred player NTextInput { - label: "Primary player" - description: "Enter a keyword to identify your main player." - placeholderText: "e.g. spotify, vlc, mpv" + label: I18n.tr("settings.audio.media.primary-player.label") + description: I18n.tr("settings.audio.media.primary-player.description") + placeholderText: I18n.tr("settings.audio.media.primary-player.placeholder") text: Settings.data.audio.preferredPlayer onTextChanged: { Settings.data.audio.preferredPlayer = text @@ -240,9 +240,9 @@ ColumnLayout { NTextInput { id: blacklistInput - label: "Excluded player" - description: "Add keywords for players you want the system to ignore. Each keyword should be on a new line." - placeholderText: "type substring and press +" + label: I18n.tr("settings.audio.media.excluded-player.label") + description: I18n.tr("settings.audio.media.excluded-player.description") + placeholderText: I18n.tr("settings.audio.media.excluded-player.placeholder") } // Button aligned to the center of the actual input field @@ -321,30 +321,11 @@ ColumnLayout { } } } - } - - // Divider - NDivider { - Layout.fillWidth: true - Layout.topMargin: Style.marginXL * scaling - Layout.bottomMargin: Style.marginXL * scaling - } - - // AudioService Visualizer Category - ColumnLayout { - spacing: Style.marginS * scaling - Layout.fillWidth: true - - NHeader { - label: "Audio visualizer" - description: "Customize visual effects that respond to audio playback." - } - // AudioService Visualizer section NComboBox { id: audioVisualizerCombo - label: "Visualization type" - description: "Choose a visualization type for media playback" + label: I18n.tr("settings.audio.media.visualizer-type.label") + description: I18n.tr("settings.audio.media.visualizer-type.description") model: ListModel { ListElement { key: "none" @@ -368,8 +349,8 @@ ColumnLayout { } NComboBox { - label: "Frame rate" - description: "Higher rates are smoother but use more resources." + label: I18n.tr("settings.audio.media.frame-rate.label") + description: I18n.tr("settings.audio.media.frame-rate.description") model: ListModel { ListElement { key: "30" @@ -404,7 +385,7 @@ ColumnLayout { onSelected: key => Settings.data.audio.cavaFrameRate = key } } - // Divider + NDivider { Layout.fillWidth: true Layout.topMargin: Style.marginXL * scaling diff --git a/Modules/Settings/Tabs/BarTab.qml b/Modules/Settings/Tabs/BarTab.qml index daefde9c..4743edab 100644 --- a/Modules/Settings/Tabs/BarTab.qml +++ b/Modules/Settings/Tabs/BarTab.qml @@ -41,14 +41,14 @@ ColumnLayout { } NHeader { - label: "settings.appearance" - description: "Customize the bar's appearance and position." + label: I18n.tr("settings.bar.appearance.section.label") + description: I18n.tr("settings.bar.appearance.section.description") } NComboBox { Layout.fillWidth: true - label: "Bar position" - description: "Choose where to place the bar on the screen." + label: I18n.tr("settings.bar.appearance.position.label") + description: I18n.tr("settings.bar.appearance.position.description") model: ListModel { ListElement { key: "top" @@ -73,8 +73,8 @@ ColumnLayout { NComboBox { Layout.fillWidth: true - label: "Bar density" - description: "Adjust the bar's padding for a compact or spacious look." + label: I18n.tr("settings.bar.appearance.density.label") + description: I18n.tr("settings.bar.appearance.density.description") model: ListModel { ListElement { key: "compact" @@ -98,8 +98,8 @@ ColumnLayout { Layout.fillWidth: true NLabel { - label: "Background opacity" - description: "Adjust the background opacity of the bar." + label: I18n.tr("settings.bar.appearance.background-opacity.label") + description: I18n.tr("settings.bar.appearance.background-opacity.description") } NValueSlider { @@ -115,16 +115,16 @@ ColumnLayout { NToggle { Layout.fillWidth: true - label: "Show capsule" - description: "Show widget backgrounds." + label: I18n.tr("settings.bar.appearance.show-capsule.label") + description: I18n.tr("settings.bar.appearance.show-capsule.description") checked: Settings.data.bar.showCapsule onToggled: checked => Settings.data.bar.showCapsule = checked } NToggle { Layout.fillWidth: true - label: "Floating bar" - description: "Displays the bar as a floating 'pill'. Note: This will move the screen corners to the edges." + label: I18n.tr("settings.bar.appearance.floating.label") + description: I18n.tr("settings.bar.appearance.floating.description") checked: Settings.data.bar.floating onToggled: checked => Settings.data.bar.floating = checked } @@ -136,8 +136,8 @@ ColumnLayout { Layout.fillWidth: true NLabel { - label: "Margins" - description: "Adjust the margins around the floating bar." + label: I18n.tr("settings.bar.appearance.margins.label") + description: I18n.tr("settings.bar.appearance.margins.description") } RowLayout { @@ -148,7 +148,7 @@ ColumnLayout { spacing: Style.marginXXS * scaling NText { - text: "Vertical" + text: I18n.tr("settings.bar.appearance.margins.vertical") font.pointSize: Style.fontSizeXS * scaling color: Color.mOnSurfaceVariant } @@ -168,7 +168,7 @@ ColumnLayout { spacing: Style.marginXXS * scaling NText { - text: "Horizontal" + text: I18n.tr("settings.bar.appearance.margins.horizontal") font.pointSize: Style.fontSizeXS * scaling color: Color.mOnSurfaceVariant } @@ -198,8 +198,8 @@ ColumnLayout { Layout.fillWidth: true NHeader { - label: "Widgets positioning" - description: "Drag and drop widgets to reorder them within each section, or use the add/remove buttons to manage widgets." + label: I18n.tr("settings.bar.widgets.section.label") + description: I18n.tr("settings.bar.widgets.section.description") } // Bar Sections @@ -268,8 +268,8 @@ ColumnLayout { Layout.fillWidth: true NHeader { - label: "Monitor display" - description: "Show bar on specific monitors. Defaults to all if none are chosen." + label: I18n.tr("settings.bar.monitors.section.label") + description: I18n.tr("settings.bar.monitors.section.description") } Repeater { diff --git a/Modules/Settings/Tabs/ColorSchemeTab.qml b/Modules/Settings/Tabs/ColorSchemeTab.qml index 09a30bb8..d7ef97ad 100644 --- a/Modules/Settings/Tabs/ColorSchemeTab.qml +++ b/Modules/Settings/Tabs/ColorSchemeTab.qml @@ -106,14 +106,14 @@ ColumnLayout { // Main Toggles - Dark Mode / Matugen NHeader { - label: "Color source" - description: "Main settings for Noctalia's colors." + label: I18n.tr("settings.color-scheme.color-source.section.label") + description: I18n.tr("settings.color-scheme.color-source.section.description") } // Dark Mode Toggle (affects both Matugen and predefined schemes that provide variants) NToggle { - label: "Dark mode" - description: "Switches to a darker theme for easier viewing at night." + label: I18n.tr("settings.color-scheme.color-source.dark-mode.label") + description: I18n.tr("settings.color-scheme.color-source.dark-mode.description") checked: Settings.data.colorSchemes.darkMode enabled: true onToggled: checked => Settings.data.colorSchemes.darkMode = checked @@ -121,8 +121,8 @@ ColumnLayout { // Use Matugen NToggle { - label: "Enable Matugen" - description: "Automatically generate colors based on your active wallpaper." + label: I18n.tr("settings.color-scheme.color-source.enable-matugen.label") + description: I18n.tr("settings.color-scheme.color-source.enable-matugen.description") checked: Settings.data.colorSchemes.useWallpaperColors onToggled: checked => { if (checked) { @@ -152,8 +152,8 @@ ColumnLayout { Layout.fillWidth: true NHeader { - label: "Predefined color schemes" - description: "To use these color schemes, you must turn off Matugen. With Matugen enabled, colors are automatically generated from your wallpaper." + label: I18n.tr("settings.color-scheme.predefined.section.label") + description: I18n.tr("settings.color-scheme.predefined.section.description") } // Color Schemes Grid @@ -324,16 +324,21 @@ ColumnLayout { visible: Settings.data.colorSchemes.useWallpaperColors spacing: Style.marginL * scaling + NHeader { + label: I18n.tr("settings.color-scheme.matugen.section.label") + description: I18n.tr("settings.color-scheme.matugen.section.description") + } + // UI Components NCollapsible { Layout.fillWidth: true - label: "UI" - description: "Desktop environment and UI toolkit theming." + label: I18n.tr("settings.color-scheme.matugen.ui.label") + description: I18n.tr("settings.color-scheme.matugen.ui.description") defaultExpanded: false NCheckbox { - label: "GTK 4 (libadwaita)" - description: "Write ~/.config/gtk-4.0/gtk.css" + label: I18n.tr("settings.color-scheme.matugen.ui.gtk4.label") + description: I18n.tr("settings.color-scheme.matugen.ui.gtk4.description") checked: Settings.data.matugen.gtk4 onToggled: checked => { Settings.data.matugen.gtk4 = checked @@ -343,8 +348,8 @@ ColumnLayout { } NCheckbox { - label: "GTK 3" - description: "Write ~/.config/gtk-3.0/gtk.css" + label: I18n.tr("settings.color-scheme.matugen.ui.gtk3.label") + description: I18n.tr("settings.color-scheme.matugen.ui.gtk3.description") checked: Settings.data.matugen.gtk3 onToggled: checked => { Settings.data.matugen.gtk3 = checked @@ -354,8 +359,8 @@ ColumnLayout { } NCheckbox { - label: "Qt6ct" - description: "Write ~/.config/qt6ct/colors/noctalia.conf" + label: I18n.tr("settings.color-scheme.matugen.ui.qt6.label") + description: I18n.tr("settings.color-scheme.matugen.ui.qt6.description") checked: Settings.data.matugen.qt6 onToggled: checked => { Settings.data.matugen.qt6 = checked @@ -365,8 +370,8 @@ ColumnLayout { } NCheckbox { - label: "Qt5ct" - description: "Write ~/.config/qt5ct/colors/noctalia.conf" + label: I18n.tr("settings.color-scheme.matugen.ui.qt5.label") + description: I18n.tr("settings.color-scheme.matugen.ui.qt5.description") checked: Settings.data.matugen.qt5 onToggled: checked => { Settings.data.matugen.qt5 = checked @@ -379,13 +384,13 @@ ColumnLayout { // Terminal Emulators NCollapsible { Layout.fillWidth: true - label: "Terminal" - description: "Terminal emulator theming." + label: I18n.tr("settings.color-scheme.matugen.terminal.label") + description: I18n.tr("settings.color-scheme.matugen.terminal.description") defaultExpanded: false NCheckbox { - label: "Kitty" - description: ProgramCheckerService.kittyAvailable ? "Write ~/.config/kitty/themes/noctalia.conf and reload" : "Requires kitty terminal to be installed" + label: I18n.tr("settings.color-scheme.matugen.terminal.kitty.label") + description: ProgramCheckerService.kittyAvailable ? I18n.tr("settings.color-scheme.matugen.terminal.kitty.description") : I18n.tr("settings.color-scheme.matugen.terminal.kitty.description-missing") checked: Settings.data.matugen.kitty enabled: ProgramCheckerService.kittyAvailable opacity: ProgramCheckerService.kittyAvailable ? 1.0 : 0.6 @@ -399,8 +404,8 @@ ColumnLayout { } NCheckbox { - label: "Ghostty" - description: ProgramCheckerService.ghosttyAvailable ? "Write ~/.config/ghostty/themes/noctalia and reload" : "Requires ghostty terminal to be installed" + label: I18n.tr("settings.color-scheme.matugen.terminal.ghostty.label") + description: ProgramCheckerService.ghosttyAvailable ? I18n.tr("settings.color-scheme.matugen.terminal.ghostty.description") : I18n.tr("settings.color-scheme.matugen.terminal.ghostty.description-missing") checked: Settings.data.matugen.ghostty enabled: ProgramCheckerService.ghosttyAvailable opacity: ProgramCheckerService.ghosttyAvailable ? 1.0 : 0.6 @@ -414,8 +419,8 @@ ColumnLayout { } NCheckbox { - label: "Foot" - description: ProgramCheckerService.footAvailable ? "Write ~/.config/foot/themes/noctalia and reload" : "Requires foot terminal to be installed" + label: I18n.tr("settings.color-scheme.matugen.terminal.foot.label") + description: ProgramCheckerService.footAvailable ? I18n.tr("settings.color-scheme.matugen.terminal.foot.description") : I18n.tr("settings.color-scheme.matugen.terminal.foot.description-missing") checked: Settings.data.matugen.foot enabled: ProgramCheckerService.footAvailable opacity: ProgramCheckerService.footAvailable ? 1.0 : 0.6 @@ -432,13 +437,13 @@ ColumnLayout { // Applications NCollapsible { Layout.fillWidth: true - label: "Programs" - description: "Application-specific theming." + label: I18n.tr("settings.color-scheme.matugen.programs.label") + description: I18n.tr("settings.color-scheme.matugen.programs.description") defaultExpanded: false NCheckbox { - label: "Fuzzel" - description: ProgramCheckerService.fuzzelAvailable ? "Write ~/.config/fuzzel/themes/noctalia and reload" : "Requires fuzzel launcher to be installed" + label: I18n.tr("settings.color-scheme.matugen.programs.fuzzel.label") + description: ProgramCheckerService.fuzzelAvailable ? I18n.tr("settings.color-scheme.matugen.programs.fuzzel.description") : I18n.tr("settings.color-scheme.matugen.programs.fuzzel.description-missing") checked: Settings.data.matugen.fuzzel enabled: ProgramCheckerService.fuzzelAvailable opacity: ProgramCheckerService.fuzzelAvailable ? 1.0 : 0.6 @@ -452,8 +457,8 @@ ColumnLayout { } NCheckbox { - label: "Vesktop" - description: ProgramCheckerService.vesktopAvailable ? "Write ~/.config/vesktop/themes/noctalia.theme.css" : "Requires vesktop Discord client to be installed" + label: I18n.tr("settings.color-scheme.matugen.programs.vesktop.label") + description: ProgramCheckerService.vesktopAvailable ? I18n.tr("settings.color-scheme.matugen.programs.vesktop.description") : I18n.tr("settings.color-scheme.matugen.programs.vesktop.description-missing") checked: Settings.data.matugen.vesktop enabled: ProgramCheckerService.vesktopAvailable opacity: ProgramCheckerService.vesktopAvailable ? 1.0 : 0.6 @@ -467,8 +472,8 @@ ColumnLayout { } NCheckbox { - label: "Pywalfox (Firefox)" - description: ProgramCheckerService.pywalfoxAvailable ? "Write ~/.cache/wal/colors.json and run pywalfox update" : "Requires pywalfox package to be installed" + label: I18n.tr("settings.color-scheme.matugen.programs.pywalfox.label") + description: ProgramCheckerService.pywalfoxAvailable ? I18n.tr("settings.color-scheme.matugen.programs.pywalfox.description") : I18n.tr("settings.color-scheme.matugen.programs.pywalfox.description-missing") checked: Settings.data.matugen.pywalfox enabled: ProgramCheckerService.pywalfoxAvailable opacity: ProgramCheckerService.pywalfoxAvailable ? 1.0 : 0.6 @@ -485,13 +490,13 @@ ColumnLayout { // Miscellaneous NCollapsible { Layout.fillWidth: true - label: "Misc" - description: "Additional configuration options." + label: I18n.tr("settings.color-scheme.matugen.misc.label") + description: I18n.tr("settings.color-scheme.matugen.misc.description") defaultExpanded: false NCheckbox { - label: "User templates" - description: "Enable user-defined Matugen config from ~/.config/matugen/config.toml" + label: I18n.tr("settings.color-scheme.matugen.misc.user-templates.label") + description: I18n.tr("settings.color-scheme.matugen.misc.user-templates.description") checked: Settings.data.matugen.enableUserTemplates onToggled: checked => { Settings.data.matugen.enableUserTemplates = checked diff --git a/Modules/Settings/Tabs/DisplayTab.qml b/Modules/Settings/Tabs/DisplayTab.qml index 79c66b2a..a8a24e66 100644 --- a/Modules/Settings/Tabs/DisplayTab.qml +++ b/Modules/Settings/Tabs/DisplayTab.qml @@ -52,8 +52,8 @@ ColumnLayout { spacing: Style.marginL * scaling NHeader { - label: "Per-monitor settings" - description: "Adjust scaling and brightness for each display." + label: I18n.tr("settings.display.monitors.section.label") + description: I18n.tr("settings.display.monitors.section.description") } ColumnLayout { @@ -103,7 +103,7 @@ ColumnLayout { Layout.fillWidth: true NText { - text: "Scale" + text: I18n.tr("settings.display.monitors.scale") Layout.preferredWidth: 80 * scaling } @@ -126,7 +126,7 @@ ColumnLayout { NIconButton { icon: "refresh" baseSize: Style.baseWidgetSize * 0.9 - tooltipText: "Reset scaling" + tooltipText: I18n.tr("settings.display.monitors.reset-scaling") onClicked: ScalingService.setScreenScale(modelData, 1.0) anchors.right: parent.right anchors.verticalCenter: parent.verticalCenter @@ -146,7 +146,7 @@ ColumnLayout { spacing: Style.marginL * scaling NText { - text: "Brightness" + text: I18n.tr("settings.display.monitors.brightness") Layout.preferredWidth: 80 * scaling } @@ -180,24 +180,6 @@ ColumnLayout { } } } - } - - NDivider { - Layout.fillWidth: true - Layout.topMargin: Style.marginXL * scaling - Layout.bottomMargin: Style.marginXL * scaling - } - - // Brightness Section - ColumnLayout { - spacing: Style.marginS * scaling - Layout.fillWidth: true - - NHeader { - label: "Brightness" - description: "Adjust brightness related settings." - } - // Brightness Step Section ColumnLayout { spacing: Style.marginS * scaling @@ -205,8 +187,8 @@ ColumnLayout { NSpinBox { Layout.fillWidth: true - label: "Brightness step size" - description: "Adjust the step size for brightness changes (scroll wheel and keyboard shortcuts)." + label: I18n.tr("settings.display.monitors.brightness-step.label") + description: I18n.tr("settings.display.monitors.brightness-step.description") minimum: 1 maximum: 50 value: Settings.data.brightness.brightnessStep @@ -229,14 +211,14 @@ ColumnLayout { Layout.fillWidth: true NHeader { - label: "Night light" - description: "Reduce blue light emission to help you sleep better and reduce eye strain." + label: I18n.tr("settings.display.night-light.section.label") + description: I18n.tr("settings.display.night-light.section.description") } } NToggle { - label: "Enable night light" - description: "Apply a warm color filter to reduce blue light emission." + label: I18n.tr("settings.display.night-light.enable.label") + description: I18n.tr("settings.display.night-light.enable.description") checked: Settings.data.nightLight.enabled onToggled: checked => { if (checked) { @@ -257,8 +239,8 @@ ColumnLayout { Layout.alignment: Qt.AlignVCenter NLabel { - label: "Color temperature" - description: "Set the color warmth for nighttime and daytime." + label: I18n.tr("settings.display.night-light.temperature.label") + description: I18n.tr("settings.display.night-light.temperature.description") } RowLayout { @@ -269,7 +251,7 @@ ColumnLayout { Layout.alignment: Qt.AlignVCenter NText { - text: "Night" + text: I18n.tr("settings.display.night-light.temperature.night") font.pointSize: Style.fontSizeM * scaling color: Color.mOnSurfaceVariant Layout.alignment: Qt.AlignVCenter @@ -291,7 +273,7 @@ ColumnLayout { } NText { - text: "Day" + text: I18n.tr("settings.display.night-light.temperature.day") font.pointSize: Style.fontSizeM * scaling color: Color.mOnSurfaceVariant Layout.alignment: Qt.AlignVCenter @@ -314,8 +296,10 @@ ColumnLayout { } NToggle { - label: "Automatic scheduling" - description: `Based on the sunset and sunrise time in ${LocationService.stableName} - recommended.` + label: I18n.tr("settings.display.night-light.auto-schedule.label") + description: I18n.tr("settings.display.night-light.auto-schedule.description", { + "location": LocationService.stableName + }) checked: Settings.data.nightLight.autoSchedule onToggled: checked => Settings.data.nightLight.autoSchedule = checked visible: Settings.data.nightLight.enabled @@ -327,8 +311,8 @@ ColumnLayout { visible: Settings.data.nightLight.enabled && !Settings.data.nightLight.autoSchedule && !Settings.data.nightLight.forced NLabel { - label: "Manual scheduling" - description: "Set custom times for sunrise and sunset." + label: I18n.tr("settings.display.night-light.manual-schedule.label") + description: I18n.tr("settings.display.night-light.manual-schedule.description") } RowLayout { @@ -336,7 +320,7 @@ ColumnLayout { spacing: Style.marginS * scaling NText { - text: "Sunrise time" + text: I18n.tr("settings.display.night-light.manual-schedule.sunrise") font.pointSize: Style.fontSizeM * scaling color: Color.mOnSurfaceVariant } @@ -344,7 +328,7 @@ ColumnLayout { NComboBox { model: timeOptions currentKey: Settings.data.nightLight.manualSunrise - placeholder: "Select start time" + placeholder: I18n.tr("settings.display.night-light.manual-schedule.select-start") onSelected: key => Settings.data.nightLight.manualSunrise = key minimumWidth: 120 * scaling } @@ -354,7 +338,7 @@ ColumnLayout { } NText { - text: "Sunset time" + text: I18n.tr("settings.display.night-light.manual-schedule.sunset") font.pointSize: Style.fontSizeM * scaling color: Color.mOnSurfaceVariant } @@ -362,7 +346,7 @@ ColumnLayout { NComboBox { model: timeOptions currentKey: Settings.data.nightLight.manualSunset - placeholder: "Select stop time" + placeholder: I18n.tr("settings.display.night-light.manual-schedule.select-stop") onSelected: key => Settings.data.nightLight.manualSunset = key minimumWidth: 120 * scaling } @@ -371,8 +355,8 @@ ColumnLayout { // Force activation toggle NToggle { - label: "Force activation" - description: "Ignores the schedule and applies the night filter immediately." + label: I18n.tr("settings.display.night-light.force-activation.label") + description: I18n.tr("settings.display.night-light.force-activation.description") checked: Settings.data.nightLight.forced onToggled: checked => { Settings.data.nightLight.forced = checked diff --git a/Modules/Settings/Tabs/DockTab.qml b/Modules/Settings/Tabs/DockTab.qml index 63068d69..edb8679a 100644 --- a/Modules/Settings/Tabs/DockTab.qml +++ b/Modules/Settings/Tabs/DockTab.qml @@ -24,20 +24,20 @@ ColumnLayout { } NHeader { - label: "Appearance" - description: "Customize the dock's behavior and appearance." + label: I18n.tr("settings.dock.appearance.section.label") + description: I18n.tr("settings.dock.appearance.section.description") } NToggle { - label: "Auto-hide" - description: "Automatically hide when not in use." + label: I18n.tr("settings.dock.appearance.auto-hide.label") + description: I18n.tr("settings.dock.appearance.auto-hide.description") checked: Settings.data.dock.autoHide onToggled: checked => Settings.data.dock.autoHide = checked } NToggle { - label: "Exclusive zone" - description: "Prevent window overlap." + label: I18n.tr("settings.dock.appearance.exclusive-zone.label") + description: I18n.tr("settings.dock.appearance.exclusive-zone.description") checked: Settings.data.dock.exclusive onToggled: checked => Settings.data.dock.exclusive = checked } @@ -46,8 +46,8 @@ ColumnLayout { spacing: Style.marginXXS * scaling Layout.fillWidth: true NLabel { - label: "Background opacity" - description: "Adjust the dock's background opacity." + label: I18n.tr("settings.dock.appearance.background-opacity.label") + description: I18n.tr("settings.dock.appearance.background-opacity.description") } NValueSlider { Layout.fillWidth: true @@ -65,8 +65,8 @@ ColumnLayout { Layout.fillWidth: true NLabel { - label: "Dock floating distance" - description: "Adjust the floating distance from the screen edge." + label: I18n.tr("settings.dock.appearance.floating-distance.label") + description: I18n.tr("settings.dock.appearance.floating-distance.description") } NValueSlider { @@ -92,8 +92,8 @@ ColumnLayout { Layout.fillWidth: true NHeader { - label: "Monitor display" - description: "Choose which monitor to display the dock on." + label: I18n.tr("settings.dock.monitors.section.label") + description: I18n.tr("settings.dock.monitors.section.description") } Repeater { diff --git a/Modules/Settings/Tabs/GeneralTab.qml b/Modules/Settings/Tabs/GeneralTab.qml index a0286c38..7079b484 100644 --- a/Modules/Settings/Tabs/GeneralTab.qml +++ b/Modules/Settings/Tabs/GeneralTab.qml @@ -49,7 +49,7 @@ ColumnLayout { NFilePicker { id: filePicker pickerType: "file" - title: I18n.tr("settings.general.profile.select-avatar") //Select avatar image" + title: I18n.tr("settings.general.profile.select-avatar") initialPath: Settings.data.general.avatarImage.substr(0, Settings.data.general.avatarImage.lastIndexOf("/")) || Quickshell.env("HOME") nameFilters: ["Image files (*.jpg *.jpeg *.png *.gif *.pnm *.bmp *.face)", "All files (*)"] onAccepted: paths => Settings.data.general.avatarImage = paths[0] @@ -104,8 +104,8 @@ ColumnLayout { Layout.fillWidth: true NLabel { - label: "Animation speed" - description: "Adjust global animation speed." + label: I18n.tr("settings.general.ui.animation-speed.label") + description: I18n.tr("settings.general.ui.animation-speed.description") } NValueSlider { @@ -132,20 +132,20 @@ ColumnLayout { Layout.fillWidth: true NHeader { - label: "Screen corners" - description: "Customize screen corner rounding and visual effects." + label: I18n.tr("settings.general.screen-corners.section.label") + description: I18n.tr("settings.general.screen-corners.section.description") } NToggle { - label: "Show screen corners" - description: "Display rounded corners on the edge of the screen." + label: I18n.tr("settings.general.screen-corners.show-corners.label") + description: I18n.tr("settings.general.screen-corners.show-corners.description") checked: Settings.data.general.showScreenCorners onToggled: checked => Settings.data.general.showScreenCorners = checked } NToggle { - label: "Solid black corners" - description: "Use solid black instead of the bar background color." + label: I18n.tr("settings.general.screen-corners.solid-black.label") + description: I18n.tr("settings.general.screen-corners.solid-black.description") checked: Settings.data.general.forceBlackScreenCorners onToggled: checked => Settings.data.general.forceBlackScreenCorners = checked } @@ -182,8 +182,8 @@ ColumnLayout { Layout.fillWidth: true NHeader { - label: "Fonts" - description: "Choose the fonts used throughout the interface." + label: I18n.tr("settings.general.fonts.section.label") + description: I18n.tr("settings.general.fonts.section.description") } // Font configuration section @@ -192,12 +192,12 @@ ColumnLayout { Layout.fillWidth: true NSearchableComboBox { - label: "Default font" - description: "Main font used throughout the interface." + label: I18n.tr("settings.general.fonts.default.label") + description: I18n.tr("settings.general.fonts.default.description") model: FontService.availableFonts currentKey: Settings.data.ui.fontDefault - placeholder: "Select default font..." - searchPlaceholder: "Search fonts..." + placeholder: I18n.tr("settings.general.fonts.default.placeholder") + searchPlaceholder: I18n.tr("settings.general.fonts.default.search-placeholder") popupHeight: 420 * scaling minimumWidth: 300 * scaling onSelected: function (key) { @@ -206,12 +206,12 @@ ColumnLayout { } NSearchableComboBox { - label: "Monospaced font" - description: "Monospaced font used for numbers and stats display." + label: I18n.tr("settings.general.fonts.monospace.label") + description: I18n.tr("settings.general.fonts.monospace.description") model: FontService.monospaceFonts currentKey: Settings.data.ui.fontFixed - placeholder: "Select monospace font..." - searchPlaceholder: "Search monospace fonts..." + placeholder: I18n.tr("settings.general.fonts.monospace.placeholder") + searchPlaceholder: I18n.tr("settings.general.fonts.monospace.search-placeholder") popupHeight: 320 * scaling minimumWidth: 300 * scaling onSelected: function (key) { @@ -220,12 +220,12 @@ ColumnLayout { } NSearchableComboBox { - label: "Accent font" - description: "Large font used for prominent displays." + label: I18n.tr("settings.general.fonts.accent.label") + description: I18n.tr("settings.general.fonts.accent.description") model: FontService.displayFonts currentKey: Settings.data.ui.fontBillboard - placeholder: "Select display font..." - searchPlaceholder: "Search display fonts..." + placeholder: I18n.tr("settings.general.fonts.accent.placeholder") + searchPlaceholder: I18n.tr("settings.general.fonts.accent.search-placeholder") popupHeight: 320 * scaling minimumWidth: 300 * scaling onSelected: function (key) { diff --git a/Modules/Settings/Tabs/HooksTab.qml b/Modules/Settings/Tabs/HooksTab.qml index ea28f8dd..ae339d1e 100644 --- a/Modules/Settings/Tabs/HooksTab.qml +++ b/Modules/Settings/Tabs/HooksTab.qml @@ -11,14 +11,14 @@ ColumnLayout { width: root.width NHeader { - label: "System hooks" - description: "Configure commands to be executed when system events occur." + label: I18n.tr("settings.hooks.system-hooks.section.label") + description: I18n.tr("settings.hooks.system-hooks.section.description") } // Enable/Disable Toggle NToggle { - label: "Enable hooks" - description: "Enable or disable all hook commands." + label: I18n.tr("settings.hooks.system-hooks.enable.label") + description: I18n.tr("settings.hooks.system-hooks.enable.description") checked: Settings.data.hooks.enabled onToggled: checked => Settings.data.hooks.enabled = checked } @@ -35,9 +35,9 @@ ColumnLayout { // Wallpaper Hook Section NInputAction { id: wallpaperHookInput - label: "Wallpaper changed" - description: "Command to be executed when wallpaper changes." - placeholderText: "e.g., notify-send \"Wallpaper\" \"Changed\"" + label: I18n.tr("settings.hooks.wallpaper-changed.label") + description: I18n.tr("settings.hooks.wallpaper-changed.description") + placeholderText: I18n.tr("settings.hooks.wallpaper-changed.placeholder") text: Settings.data.hooks.wallpaperChange onEditingFinished: { Settings.data.hooks.wallpaperChange = wallpaperHookInput.text @@ -57,9 +57,9 @@ ColumnLayout { // Dark Mode Hook Section NInputAction { id: darkModeHookInput - label: "Theme changed" - description: "Command to be executed when theme toggles between dark and light mode." - placeholderText: "e.g., notify-send \"Theme\" \"Toggled\"" + label: I18n.tr("settings.hooks.theme-changed.label") + description: I18n.tr("settings.hooks.theme-changed.description") + placeholderText: I18n.tr("settings.hooks.theme-changed.placeholder") text: Settings.data.hooks.darkModeChange onEditingFinished: { Settings.data.hooks.darkModeChange = darkModeHookInput.text @@ -82,13 +82,13 @@ ColumnLayout { Layout.fillWidth: true NLabel { - label: "Hook Command Information" - description: "• Commands are executed via shell (sh -c)\n• Commands run in background (detached)\n• Test buttons execute with current values" + label: I18n.tr("settings.hooks.info.command-info.label") + description: I18n.tr("settings.hooks.info.command-info.description") } NLabel { - label: "Available Parameters" - description: "• Wallpaper Hook: $1 = wallpaper path, $2 = screen name\n• Theme Toggle Hook: $1 = true/false (dark mode state)" + label: I18n.tr("settings.hooks.info.parameters.label") + description: I18n.tr("settings.hooks.info.parameters.description") } } } diff --git a/Modules/Settings/Tabs/LauncherTab.qml b/Modules/Settings/Tabs/LauncherTab.qml index 74b4ac54..fc456dee 100644 --- a/Modules/Settings/Tabs/LauncherTab.qml +++ b/Modules/Settings/Tabs/LauncherTab.qml @@ -10,14 +10,14 @@ ColumnLayout { spacing: Style.marginL * scaling NHeader { - label: "Appearance" - description: "Customize the launcher's behavior and appearance." + label: I18n.tr("settings.launcher.settings.section.label") + description: I18n.tr("settings.launcher.settings.section.description") } NComboBox { id: launcherPosition - label: "Position" - description: "Choose where the launcher panel appears." + label: I18n.tr("settings.launcher.settings.position.label") + description: I18n.tr("settings.launcher.settings.position.description") Layout.fillWidth: true model: ListModel { ListElement { @@ -60,14 +60,14 @@ ColumnLayout { Layout.fillWidth: true NText { - text: "Background opacity" + text: I18n.tr("settings.launcher.settings.background-opacity.label") font.pointSize: Style.fontSizeL * scaling font.weight: Style.fontWeightBold color: Color.mOnSurface } NText { - text: "Adjust the background opacity of the launcher." + text: I18n.tr("settings.launcher.settings.background-opacity.description") font.pointSize: Style.fontSizeXS * scaling color: Color.mOnSurfaceVariant wrapMode: Text.WordWrap @@ -87,22 +87,22 @@ ColumnLayout { } NToggle { - label: "Enable clipboard history" - description: "Access previously copied items from the launcher." + label: I18n.tr("settings.launcher.settings.clipboard-history.label") + description: I18n.tr("settings.launcher.settings.clipboard-history.description") checked: Settings.data.appLauncher.enableClipboardHistory onToggled: checked => Settings.data.appLauncher.enableClipboardHistory = checked } NToggle { - label: "Sort by most used" - description: "When enabled, frequently launched apps appear first in the list." + label: I18n.tr("settings.launcher.settings.sort-by-usage.label") + description: I18n.tr("settings.launcher.settings.sort-by-usage.description") checked: Settings.data.appLauncher.sortByMostUsed onToggled: checked => Settings.data.appLauncher.sortByMostUsed = checked } NToggle { - label: "Use App2Unit to launch applications" - description: "Uses an alternative launch method to better manage app processes and prevent issues." + label: I18n.tr("settings.launcher.settings.use-app2unit.label") + description: I18n.tr("settings.launcher.settings.use-app2unit.description") checked: Settings.data.appLauncher.useApp2Unit onToggled: checked => Settings.data.appLauncher.useApp2Unit = checked } diff --git a/Modules/Settings/Tabs/LocationTab.qml b/Modules/Settings/Tabs/LocationTab.qml index d0cc8d3a..2e286dc4 100644 --- a/Modules/Settings/Tabs/LocationTab.qml +++ b/Modules/Settings/Tabs/LocationTab.qml @@ -10,8 +10,8 @@ ColumnLayout { spacing: Style.marginL * scaling NHeader { - label: "Your location" - description: "Get accurate weather and night light scheduling by setting your location." + label: I18n.tr("settings.location.location.section.label") + description: I18n.tr("settings.location.location.section.description") } // Location section @@ -20,10 +20,10 @@ ColumnLayout { spacing: Style.marginL * scaling NTextInput { - label: "Search for a location" - description: "e.g., Toronto, ON" + label: I18n.tr("settings.location.location.search.label") + description: I18n.tr("settings.location.location.search.description") text: Settings.data.location.name || Settings.defaultLocation - placeholderText: "Enter the location name" + placeholderText: I18n.tr("settings.location.location.search.placeholder") onEditingFinished: { // Verify the location has really changed to avoid extra resets var newLocation = text.trim() @@ -64,13 +64,13 @@ ColumnLayout { Layout.fillWidth: true NHeader { - label: "Weather" - description: "Choose your preferred temperature unit." + label: I18n.tr("settings.location.weather.section.label") + description: I18n.tr("settings.location.weather.section.description") } NToggle { - label: "Display temperature in Fahrenheit (°F)" - description: "Display temperature in Fahrenheit instead of Celsius." + label: I18n.tr("settings.location.weather.fahrenheit.label") + description: I18n.tr("settings.location.weather.fahrenheit.description") checked: Settings.data.location.useFahrenheit onToggled: checked => Settings.data.location.useFahrenheit = checked } @@ -82,26 +82,26 @@ ColumnLayout { Layout.bottomMargin: Style.marginXL * scaling } - // Weather section + // Date & time section ColumnLayout { spacing: Style.marginM * scaling Layout.fillWidth: true NHeader { - label: "Date & time" - description: "Customize how date and time appear." + label: I18n.tr("settings.location.date-time.section.label") + description: I18n.tr("settings.location.date-time.section.description") } NToggle { - label: "Use 12-hour time format on the lock screen" - description: "On for AM/PM format (e.g., 8:00 PM), off for 24-hour format (e.g., 20:00)." + label: I18n.tr("settings.location.date-time.12hour-format.label") + description: I18n.tr("settings.location.date-time.12hour-format.description") checked: Settings.data.location.use12hourFormat onToggled: checked => Settings.data.location.use12hourFormat = checked } NToggle { - label: "Show week numbers" - description: "Displays the week of the year (e.g., Week 38) in the calendar." + label: I18n.tr("settings.location.date-time.week-numbers.label") + description: I18n.tr("settings.location.date-time.week-numbers.description") checked: Settings.data.location.showWeekNumberInCalendar onToggled: checked => Settings.data.location.showWeekNumberInCalendar = checked } diff --git a/Modules/Settings/Tabs/NetworkTab.qml b/Modules/Settings/Tabs/NetworkTab.qml index b44c9957..104ac149 100644 --- a/Modules/Settings/Tabs/NetworkTab.qml +++ b/Modules/Settings/Tabs/NetworkTab.qml @@ -12,17 +12,17 @@ ColumnLayout { spacing: Style.marginL * scaling NHeader { - label: "Manage Wi-Fi and Bluetooth connections." + description: I18n.tr("settings.network.section.description") } NToggle { - label: "Enable Wi-Fi" + label: I18n.tr("settings.network.wifi.label") checked: Settings.data.network.wifiEnabled onToggled: checked => NetworkService.setWifiEnabled(checked) } NToggle { - label: "Enable Bluetooth" + label: I18n.tr("settings.network.bluetooth.label") checked: Settings.data.network.bluetoothEnabled onToggled: checked => BluetoothService.setBluetoothEnabled(checked) } diff --git a/Modules/Settings/Tabs/NotificationsTab.qml b/Modules/Settings/Tabs/NotificationsTab.qml index 3b1b7fdb..fab5d0d6 100644 --- a/Modules/Settings/Tabs/NotificationsTab.qml +++ b/Modules/Settings/Tabs/NotificationsTab.qml @@ -28,27 +28,27 @@ ColumnLayout { Layout.fillWidth: true NHeader { - label: "Appearance" - description: "Configure notifications appearance and behavior." + label: I18n.tr("settings.notifications.settings.section.label") + description: I18n.tr("settings.notifications.settings.section.description") } NToggle { - label: "Do not disturb" - description: "Disable all notification popups when enabled." + label: I18n.tr("settings.notifications.settings.do-not-disturb.label") + description: I18n.tr("settings.notifications.settings.do-not-disturb.description") checked: Settings.data.notifications.doNotDisturb onToggled: checked => Settings.data.notifications.doNotDisturb = checked } NToggle { - label: "Enable on screen display" - description: "Show volume and brightness changes in real-time." + label: I18n.tr("settings.notifications.settings.enable-osd.label") + description: I18n.tr("settings.notifications.settings.enable-osd.description") checked: Settings.data.notifications.enableOSD onToggled: checked => Settings.data.notifications.enableOSD = checked } NComboBox { - label: "Location" - description: "Where notifications appear on screen." + label: I18n.tr("settings.notifications.settings.location.label") + description: I18n.tr("settings.notifications.settings.location.description") model: ListModel { ListElement { key: "top" @@ -78,32 +78,14 @@ ColumnLayout { currentKey: Settings.data.notifications.location || "top_right" onSelected: key => Settings.data.notifications.location = key } - } - - NDivider { - Layout.fillWidth: true - Layout.topMargin: Style.marginXL * scaling - Layout.bottomMargin: Style.marginXL * scaling - } - - // Notification Duration Settings - ColumnLayout { - spacing: Style.marginL * scaling - Layout.fillWidth: true - - NHeader { - label: "Notification duration" - description: "Configure how long notifications stay visible based on their urgency level." - } - // Low Urgency Duration ColumnLayout { spacing: Style.marginXXS * scaling Layout.fillWidth: true NLabel { - label: "Low urgency" - description: "How long low priority notifications stay visible." + label: I18n.tr("settings.notifications.settings.low-urgency.label") + description: I18n.tr("settings.notifications.settings.low-urgency.description") } NValueSlider { @@ -123,8 +105,8 @@ ColumnLayout { Layout.fillWidth: true NLabel { - label: "Normal urgency" - description: "How long normal priority notifications stay visible." + label: I18n.tr("settings.notifications.settings.normal-urgency.label") + description: I18n.tr("settings.notifications.settings.normal-urgency.description") } NValueSlider { @@ -144,8 +126,8 @@ ColumnLayout { Layout.fillWidth: true NLabel { - label: "Critical urgency" - description: "How long critical priority notifications stay visible." + label: I18n.tr("settings.notifications.settings.critical-urgency.label") + description: I18n.tr("settings.notifications.settings.critical-urgency.description") } NValueSlider { @@ -158,22 +140,10 @@ ColumnLayout { text: Settings.data.notifications.criticalUrgencyDuration + "s" } } - } - - NDivider { - Layout.fillWidth: true - Layout.topMargin: Style.marginXL * scaling - Layout.bottomMargin: Style.marginXL * scaling - } - - // Monitor Configuration - ColumnLayout { - spacing: Style.marginM * scaling - Layout.fillWidth: true - - NHeader { - label: "Monitors display" - description: "Show notification on specific monitors. Defaults to all if none are chosen." + // Monitor Configuration + NLabel { + label: I18n.tr("settings.notifications.settings.monitors-display.label") + description: I18n.tr("settings.notifications.settings.monitors-display.description") } Repeater { diff --git a/Modules/Settings/Tabs/ScreenRecorderTab.qml b/Modules/Settings/Tabs/ScreenRecorderTab.qml index f05e8dc7..ba4bbdac 100644 --- a/Modules/Settings/Tabs/ScreenRecorderTab.qml +++ b/Modules/Settings/Tabs/ScreenRecorderTab.qml @@ -12,8 +12,8 @@ ColumnLayout { spacing: Style.marginL * scaling NHeader { - label: "General settings" - description: "Manage screen recording output and content." + label: I18n.tr("settings.screen-recorder.general.section.label") + description: I18n.tr("settings.screen-recorder.general.section.description") } // Output Folder @@ -22,27 +22,22 @@ ColumnLayout { Layout.fillWidth: true NTextInputButton { - label: "Output folder" - description: "Folder where screen recordings will be saved." + label: I18n.tr("settings.screen-recorder.general.output-folder.label") + description: I18n.tr("settings.screen-recorder.general.output-folder.description") placeholderText: Quickshell.env("HOME") + "/Videos" text: Settings.data.screenRecorder.directory buttonIcon: "folder-open" - buttonTooltip: "Browse for output folder" + buttonTooltip: I18n.tr("settings.screen-recorder.general.output-folder.tooltip") onInputEditingFinished: Settings.data.screenRecorder.directory = text onButtonClicked: folderPicker.open() } - ColumnLayout { - spacing: Style.marginS * scaling - Layout.fillWidth: true - Layout.topMargin: Style.marginM * scaling - // Show Cursor - NToggle { - label: "Show cursor" - description: "Record mouse cursor in the video." - checked: Settings.data.screenRecorder.showCursor - onToggled: checked => Settings.data.screenRecorder.showCursor = checked - } + // Show Cursor + NToggle { + label: I18n.tr("settings.screen-recorder.general.show-cursor.label") + description: I18n.tr("settings.screen-recorder.general.show-cursor.description") + checked: Settings.data.screenRecorder.showCursor + onToggled: checked => Settings.data.screenRecorder.showCursor = checked } } @@ -58,13 +53,14 @@ ColumnLayout { Layout.fillWidth: true NHeader { - label: "Video settings" + label: I18n.tr("settings.screen-recorder.video.section.label") + description: I18n.tr("settings.screen-recorder.video.section.description") } // Source NComboBox { - label: "Video source" - description: "Portal is recommended, if you get artifacts try Screen." + label: I18n.tr("settings.screen-recorder.video.video-source.label") + description: I18n.tr("settings.screen-recorder.video.video-source.description") model: ListModel { ListElement { key: "portal" @@ -81,8 +77,8 @@ ColumnLayout { // Frame Rate NComboBox { - label: "Frame rate" - description: "Target frame rate for screen recordings." + label: I18n.tr("settings.screen-recorder.video.frame-rate.label") + description: I18n.tr("settings.screen-recorder.video.frame-rate.description") model: ListModel { ListElement { key: "30" @@ -119,8 +115,8 @@ ColumnLayout { // Video Quality NComboBox { - label: "Video quality" - description: "Higher quality results in larger file sizes." + label: I18n.tr("settings.screen-recorder.video.video-quality.label") + description: I18n.tr("settings.screen-recorder.video.video-quality.description") model: ListModel { ListElement { key: "medium" @@ -145,8 +141,8 @@ ColumnLayout { // Video Codec NComboBox { - label: "Video codec" - description: "h264 is the most common codec." + label: I18n.tr("settings.screen-recorder.video.video-codec.label") + description: I18n.tr("settings.screen-recorder.video.video-codec.description") model: ListModel { ListElement { key: "h264" @@ -175,8 +171,8 @@ ColumnLayout { // Color Range NComboBox { - label: "Color range" - description: "Limited is recommended for better compatibility." + label: I18n.tr("settings.screen-recorder.video.color-range.label") + description: I18n.tr("settings.screen-recorder.video.color-range.description") model: ListModel { ListElement { key: "limited" @@ -194,8 +190,8 @@ ColumnLayout { NDivider { Layout.fillWidth: true - Layout.topMargin: Style.marginL * 2 * scaling - Layout.bottomMargin: Style.marginL * scaling + Layout.topMargin: Style.marginXL * scaling + Layout.bottomMargin: Style.marginXL * scaling } // Audio Settings @@ -204,13 +200,14 @@ ColumnLayout { Layout.fillWidth: true NHeader { - label: "Audio settings" + label: I18n.tr("settings.screen-recorder.audio.section.label") + description: I18n.tr("settings.screen-recorder.audio.section.description") } // Audio Source NComboBox { - label: "Audio source" - description: "Audio source to capture during recording." + label: I18n.tr("settings.screen-recorder.audio.audio-source.label") + description: I18n.tr("settings.screen-recorder.audio.audio-source.description") model: ListModel { ListElement { key: "default_output" @@ -231,8 +228,8 @@ ColumnLayout { // Audio Codec NComboBox { - label: "Audio codec" - description: "Opus is recommended for best performance and smallest audio size." + label: I18n.tr("settings.screen-recorder.audio.audio-codec.label") + description: I18n.tr("settings.screen-recorder.audio.audio-codec.description") model: ListModel { ListElement { key: "opus" @@ -248,16 +245,10 @@ ColumnLayout { } } - NDivider { - Layout.fillWidth: true - Layout.topMargin: Style.marginXL * scaling - Layout.bottomMargin: Style.marginXL * scaling - } - NFilePicker { id: folderPicker pickerType: "folder" - title: "Select output folder" + title: I18n.tr("settings.screen-recorder.general.select-output-folder") initialPath: Settings.data.screenRecorder.directory || Quickshell.env("HOME") + "/Videos" onAccepted: paths => Settings.data.screenRecorder.directory = paths[0] } diff --git a/Modules/Settings/Tabs/WallpaperTab.qml b/Modules/Settings/Tabs/WallpaperTab.qml index 13d039cc..aff20c32 100644 --- a/Modules/Settings/Tabs/WallpaperTab.qml +++ b/Modules/Settings/Tabs/WallpaperTab.qml @@ -14,13 +14,13 @@ ColumnLayout { property string specificFolderMonitorName: "" NHeader { - label: "Wallpaper settings" - description: "Control how wallpapers are managed and displayed." + label: I18n.tr("settings.wallpaper.settings.section.label") + description: I18n.tr("settings.wallpaper.settings.section.description") } NToggle { - label: "Enable wallpaper management" - description: "Manage wallpapers with Noctalia. Uncheck if you prefer using another application." + label: I18n.tr("settings.wallpaper.settings.enable-management.label") + description: I18n.tr("settings.wallpaper.settings.enable-management.description") checked: Settings.data.wallpaper.enabled onToggled: checked => Settings.data.wallpaper.enabled = checked Layout.bottomMargin: Style.marginL * scaling @@ -33,11 +33,11 @@ ColumnLayout { NTextInputButton { id: wallpaperPathInput - label: "Wallpaper folder" - description: "Path to your main wallpaper folder." + label: I18n.tr("settings.wallpaper.settings.folder.label") + description: I18n.tr("settings.wallpaper.settings.folder.description") text: Settings.data.wallpaper.directory buttonIcon: "folder-open" - buttonTooltip: "Browse for wallpaper folder" + buttonTooltip: I18n.tr("settings.wallpaper.settings.folder.tooltip") Layout.fillWidth: true onInputEditingFinished: Settings.data.wallpaper.directory = text onButtonClicked: mainFolderPicker.open() @@ -45,8 +45,8 @@ ColumnLayout { // Monitor-specific directories NToggle { - label: "Monitor-specific directories" - description: "Set a different wallpaper folder for each monitor." + label: I18n.tr("settings.wallpaper.settings.monitor-specific.label") + description: I18n.tr("settings.wallpaper.settings.monitor-specific.description") checked: Settings.data.wallpaper.enableMultiMonitorDirectories onToggled: checked => Settings.data.wallpaper.enableMultiMonitorDirectories = checked } @@ -83,7 +83,7 @@ ColumnLayout { NTextInputButton { text: WallpaperService.getMonitorDirectory(modelData.name) buttonIcon: "folder-open" - buttonTooltip: "Browse for wallpaper folder" + buttonTooltip: I18n.tr("settings.wallpaper.settings.monitor-specific.tooltip") Layout.fillWidth: true onInputEditingFinished: WallpaperService.setMonitorDirectory(modelData.name, text) onButtonClicked: { @@ -110,13 +110,13 @@ ColumnLayout { Layout.fillWidth: true NHeader { - label: "Look & feel" + label: I18n.tr("settings.wallpaper.look-feel.section.label") } // Fill Mode NComboBox { - label: "Fill mode" - description: "Select how the image should scale to match your monitor's resolution." + label: I18n.tr("settings.wallpaper.look-feel.fill-mode.label") + description: I18n.tr("settings.wallpaper.look-feel.fill-mode.description") model: WallpaperService.fillModeModel currentKey: Settings.data.wallpaper.fillMode onSelected: key => Settings.data.wallpaper.fillMode = key @@ -124,8 +124,8 @@ ColumnLayout { RowLayout { NLabel { - label: "Fill color" - description: "Choose a fill color that may appear behind the wallpaper." + label: I18n.tr("settings.wallpaper.look-feel.fill-color.label") + description: I18n.tr("settings.wallpaper.look-feel.fill-color.description") Layout.alignment: Qt.AlignTop } @@ -137,8 +137,8 @@ ColumnLayout { // Transition Type NComboBox { - label: "Transition type" - description: "Animation type when switching between wallpapers." + label: I18n.tr("settings.wallpaper.look-feel.transition-type.label") + description: I18n.tr("settings.wallpaper.look-feel.transition-type.description") model: WallpaperService.transitionsModel currentKey: Settings.data.wallpaper.transitionType onSelected: key => Settings.data.wallpaper.transitionType = key @@ -147,8 +147,8 @@ ColumnLayout { // Transition Duration ColumnLayout { NLabel { - label: "Transition duration" - description: "Duration of transition animations in seconds." + label: I18n.tr("settings.wallpaper.look-feel.transition-duration.label") + description: I18n.tr("settings.wallpaper.look-feel.transition-duration.description") } NValueSlider { @@ -165,8 +165,8 @@ ColumnLayout { // Edge Smoothness ColumnLayout { NLabel { - label: "Soften transition edge" - description: "Applies a soft, feathered effect to the edge of transitions." + label: I18n.tr("settings.wallpaper.look-feel.edge-smoothness.label") + description: I18n.tr("settings.wallpaper.look-feel.edge-smoothness.description") } NValueSlider { @@ -193,13 +193,13 @@ ColumnLayout { Layout.fillWidth: true NHeader { - label: "Automation" + label: I18n.tr("settings.wallpaper.automation.section.label") } // Random Wallpaper NToggle { - label: "Random wallpaper" - description: "Schedule random wallpaper changes at regular intervals." + label: I18n.tr("settings.wallpaper.automation.random-wallpaper.label") + description: I18n.tr("settings.wallpaper.automation.random-wallpaper.description") checked: Settings.data.wallpaper.randomEnabled onToggled: checked => Settings.data.wallpaper.randomEnabled = checked } @@ -209,8 +209,8 @@ ColumnLayout { visible: Settings.data.wallpaper.randomEnabled RowLayout { NLabel { - label: "Wallpaper interval" - description: "How often to change wallpapers automatically." + label: I18n.tr("settings.wallpaper.automation.interval.label") + description: I18n.tr("settings.wallpaper.automation.interval.description") Layout.fillWidth: true } @@ -275,8 +275,8 @@ ColumnLayout { Layout.topMargin: Style.marginS * scaling NTextInput { - label: "Custom interval" - description: "Enter time as HH:MM (e.g., 01:30)." + label: I18n.tr("settings.wallpaper.automation.custom-interval.label") + description: I18n.tr("settings.wallpaper.automation.custom-interval.description") text: { const s = Settings.data.wallpaper.randomIntervalSec const h = Math.floor(s / 3600) @@ -341,14 +341,14 @@ ColumnLayout { NFilePicker { id: mainFolderPicker pickerType: "folder" - title: "Select wallpaper folder" + title: I18n.tr("settings.wallpaper.settings.select-folder") onAccepted: paths => Settings.data.wallpaper.directory = paths[0] } NFilePicker { id: monitorFolderPicker pickerType: "folder" - title: "Select monitor wallpaper folder" + title: I18n.tr("settings.wallpaper.settings.select-monitor-folder") onAccepted: paths => WallpaperService.setMonitorDirectory(specificFolderMonitorName, paths[0]) } } From df70f0c824abad1847bf37b761e215084b4fff56 Mon Sep 17 00:00:00 2001 From: Ly-sec Date: Wed, 24 Sep 2025 13:47:59 +0200 Subject: [PATCH 03/15] Possibly got everything transfered over to i18n --- Assets/Translations/de.json | 82 +++++ Assets/Translations/en.json | 289 ++++++++++++++++++ Bin/{check-i18n.sh => i18n-check.sh} | 0 Modules/Bar/Bluetooth/BluetoothPanel.qml | 16 +- Modules/Bar/Calendar/CalendarPanel.qml | 2 +- Modules/Bar/WiFi/WiFiPanel.qml | 36 +-- Modules/Bar/Widgets/Clock.qml | 2 +- Modules/Dock/DockMenu.qml | 8 +- Modules/LockScreen/LockScreen.qml | 12 +- .../Notification/NotificationHistoryPanel.qml | 6 +- Modules/Settings/Bar/BarSectionEditor.qml | 2 +- .../Settings/Bar/BarWidgetSettingsDialog.qml | 4 +- .../WidgetSettings/ActiveWindowSettings.qml | 2 +- .../Bar/WidgetSettings/BatterySettings.qml | 8 +- .../Bar/WidgetSettings/BrightnessSettings.qml | 4 +- .../Bar/WidgetSettings/ClockSettings.qml | 22 +- .../WidgetSettings/ControlCenterSettings.qml | 12 +- .../WidgetSettings/CustomButtonSettings.qml | 22 +- .../WidgetSettings/KeyboardLayoutSettings.qml | 4 +- .../Bar/WidgetSettings/MediaMiniSettings.qml | 6 +- .../Bar/WidgetSettings/MicrophoneSettings.qml | 4 +- .../NotificationHistorySettings.qml | 4 +- .../Bar/WidgetSettings/SpacerSettings.qml | 4 +- .../WidgetSettings/SystemMonitorSettings.qml | 12 +- .../Bar/WidgetSettings/VolumeSettings.qml | 4 +- .../Bar/WidgetSettings/WorkspaceSettings.qml | 6 +- Modules/Settings/Tabs/GeneralTab.qml | 4 +- Modules/Wallpaper/WallpaperPanel.qml | 8 +- Widgets/NColorPickerDialog.qml | 24 +- Widgets/NDateTimeTokens.qml | 79 ++--- Widgets/NIconPicker.qml | 8 +- Widgets/NTooltip.qml | 2 +- 32 files changed, 522 insertions(+), 176 deletions(-) rename Bin/{check-i18n.sh => i18n-check.sh} (100%) diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json index b8729fe0..3a42eefd 100644 --- a/Assets/Translations/de.json +++ b/Assets/Translations/de.json @@ -654,5 +654,87 @@ } } } + }, + "widgets": { + "tooltip": { + "placeholder": "Platzhalter" + }, + "datetime-tokens": { + "common": { + "12hour-time-minutes": "12-Stunden-Zeit mit Minuten", + "24hour-time-minutes": "24-Stunden-Zeit mit Minuten", + "24hour-time-seconds": "24-Stunden-Zeit mit Sekunden", + "weekday-month-day": "Wochentag, Monat und Tag", + "iso-date": "ISO-Datumsformat", + "us-date": "US-Datumsformat", + "european-date": "Europäisches Datumsformat", + "weekday-date": "Wochentag mit Datum" + }, + "hour": { + "no-leading-zero": "Stunde ohne führende Null (0-23) - 24-Stunden-Format", + "leading-zero": "Stunde mit führender Null (00-23) - 24-Stunden-Format" + }, + "minute": { + "no-leading-zero": "Minute ohne führende Null (0-59)", + "leading-zero": "Minute mit führender Null (00-59)" + }, + "second": { + "no-leading-zero": "Sekunde ohne führende Null (0-59)", + "leading-zero": "Sekunde mit führender Null (00-59)" + }, + "ampm": { + "uppercase": "AM/PM in Großbuchstaben", + "lowercase": "am/pm in Kleinbuchstaben" + }, + "timezone": { + "abbreviation": "Zeitzonenabkürzung" + }, + "year": { + "two-digit": "Jahr als zweistellige Zahl (00-99)", + "four-digit": "Jahr als vierstellige Zahl" + }, + "month": { + "number-no-zero": "Monat als Zahl ohne führende Null (1-12)", + "number-leading-zero": "Monat als Zahl mit führender Null (01-12)", + "abbreviated": "Abgekürzter Monatsname", + "full": "Vollständiger Monatsname" + }, + "day": { + "no-leading-zero": "Tag ohne führende Null (1-31)", + "leading-zero": "Tag mit führender Null (01-31)", + "abbreviated": "Abgekürzter Tagesname", + "full": "Vollständiger Tagesname" + } + }, + "icon-picker": { + "title": "Symbol-Auswahl", + "search": { + "label": "Suchen" + }, + "cancel": "Abbrechen", + "apply": "Anwenden" + }, + "color-picker": { + "title": "Farbauswahl", + "hex": { + "label": "Hex-Farbe", + "description": "Geben Sie einen hexadezimalen Farbcode ein." + }, + "rgb": { + "label": "RGB-Werte", + "description": "Passen Sie Rot-, Grün-, Blau- und Helligkeitswerte an." + }, + "brightness": "Helligkeit", + "theme-colors": { + "label": "Theme-Farben", + "description": "Schnellzugriff auf die Farbpalette Ihres Themes." + }, + "palette": { + "label": "Palette", + "description": "Wählen Sie aus einer großen Auswahl vordefinierter Farben." + }, + "cancel": "Abbrechen", + "apply": "Anwenden" + } } } \ No newline at end of file diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index 0bb0e616..3f880aee 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -45,6 +45,10 @@ "solid-black": { "label": "Solid black corners", "description": "Use solid black instead of the bar background color." + }, + "radius": { + "label": "Screen corners radius", + "description": "Adjust the rounded corners of the screen." } }, "fonts": { @@ -654,5 +658,290 @@ } } } + }, + "widgets": { + "tooltip": { + "placeholder": "Placeholder" + }, + "datetime-tokens": { + "common": { + "12hour-time-minutes": "12-hour time with minutes", + "24hour-time-minutes": "24-hour time with minutes", + "24hour-time-seconds": "24-hour time with seconds", + "weekday-month-day": "Weekday, month and day", + "iso-date": "ISO date format", + "us-date": "US date format", + "european-date": "European date format", + "weekday-date": "Weekday with date" + }, + "hour": { + "no-leading-zero": "Hour without leading zero (0-23) - 24-hour format", + "leading-zero": "Hour with leading zero (00-23) - 24-hour format" + }, + "minute": { + "no-leading-zero": "Minute without leading zero (0-59)", + "leading-zero": "Minute with leading zero (00-59)" + }, + "second": { + "no-leading-zero": "Second without leading zero (0-59)", + "leading-zero": "Second with leading zero (00-59)" + }, + "ampm": { + "uppercase": "AM/PM in uppercase", + "lowercase": "am/pm in lowercase" + }, + "timezone": { + "abbreviation": "Timezone abbreviation" + }, + "year": { + "two-digit": "Year as two-digit number (00-99)", + "four-digit": "Year as four-digit number" + }, + "month": { + "number-no-zero": "Month as number without leading zero (1-12)", + "number-leading-zero": "Month as number with leading zero (01-12)", + "abbreviated": "Abbreviated month name", + "full": "Full month name" + }, + "day": { + "no-leading-zero": "Day without leading zero (1-31)", + "leading-zero": "Day with leading zero (01-31)", + "abbreviated": "Abbreviated day name", + "full": "Full day name" + } + }, + "icon-picker": { + "title": "Icon picker", + "search": { + "label": "Search" + }, + "cancel": "Cancel", + "apply": "Apply" + }, + "color-picker": { + "title": "Color picker", + "hex": { + "label": "Hex color", + "description": "Enter a hexadecimal color code." + }, + "rgb": { + "label": "RGB values", + "description": "Adjust red, green, blue, and brightness values." + }, + "brightness": "Brightness", + "theme-colors": { + "label": "Theme colors", + "description": "Quick access to your theme's color palette." + }, + "palette": { + "label": "Palette", + "description": "Choose from a wide range of predefined colors." + }, + "cancel": "Cancel", + "apply": "Apply" + } + }, + "bar": { + "widget-settings": { + "dialog": { + "cancel": "Cancel", + "apply": "Apply" + }, + "section-editor": { + "placeholder": "Select a widget to add..." + }, + "active-window": { + "show-app-icon": "Show app icon" + }, + "system-monitor": { + "cpu-usage": "CPU usage", + "cpu-temperature": "CPU temperature", + "memory-usage": "Memory usage", + "memory-percentage": "Memory as percentage", + "network-traffic": "Network traffic", + "storage-usage": "Storage usage" + }, + "notification-history": { + "show-unread-badge": "Show unread badge", + "hide-badge-when-zero": "Hide badge when zero" + }, + "battery": { + "display-mode": { + "label": "Display mode", + "description": "Choose how you'd like this value to appear." + }, + "low-battery-threshold": { + "label": "Low battery warning threshold", + "description": "Show a warning when battery falls below this percentage." + } + }, + "control-center": { + "use-distro-logo": "Use distro logo instead of icon", + "icon": { + "label": "Icon", + "description": "Select an icon from the library or a custom file." + }, + "browse-library": "Browse Library", + "browse-file": "Browse File", + "select-custom-icon": "Select a custom icon" + }, + "keyboard-layout": { + "display-mode": { + "label": "Display mode", + "description": "Choose how you'd like this value to appear." + } + }, + "volume": { + "display-mode": { + "label": "Display mode", + "description": "Choose how you'd like this value to appear." + } + }, + "workspace": { + "label-mode": "Label Mode", + "hide-unoccupied": { + "label": "Hide unoccupied", + "description": "Don't display workspaces without windows." + } + }, + "microphone": { + "display-mode": { + "label": "Display mode", + "description": "Choose how you'd like this value to appear." + } + }, + "brightness": { + "display-mode": { + "label": "Display mode", + "description": "Choose how you'd like this value to appear." + } + }, + "spacer": { + "width": { + "label": "Width", + "description": "Spacing width in pixels" + } + }, + "custom-button": { + "icon": { + "label": "Icon", + "description": "Select an icon from the library." + }, + "browse": "Browse", + "left-click": "Left click", + "right-click": "Right click", + "middle-click": "Middle click", + "dynamic-text": "Dynamic text", + "display-command-output": { + "label": "Display Command Output", + "description": "Enter a command to run at a regular interval. The first line of its output will be displayed as text." + }, + "refresh-interval": { + "label": "Refresh interval", + "description": "Interval in milliseconds." + } + }, + "media-mini": { + "show-album-art": "Show album art", + "show-visualizer": "Show visualizer", + "visualizer-type": "Visualizer type" + }, + "clock": { + "use-primary-color": { + "label": "Use primary color", + "description": "When enabled, this applies the primary color for emphasis." + }, + "use-monospaced-font": { + "label": "Use monospaced font", + "description": "When enabled, the clock will use the monospaced font." + }, + "clock-display": { + "label": "Clock display", + "description": "Customize your clock's display by adding tokens from the list below. To use the 12-hour format, you must include the 'AP' token." + }, + "horizontal-bar": { + "label": "Horizontal bar", + "description": "Tip: Use \\n to create a line break." + }, + "vertical-bar": { + "label": "Vertical bar", + "description": "Use a space to separate each part onto a new line." + }, + "preview": "Preview" + } + } + }, + "notifications": { + "panel": { + "title": "Notifications", + "no-notifications": "No notifications", + "description": "Your notifications will show up here as they arrive." + } + }, + "wallpaper": { + "panel": { + "title": "Wallpaper selector", + "apply-all-monitors": { + "label": "Apply to all monitors", + "description": "Apply selected wallpaper to all monitors at once." + }, + "search": "Search:" + } + }, + "bluetooth": { + "panel": { + "title": "Bluetooth", + "disabled": "Bluetooth is disabled", + "enable-message": "Enable Bluetooth to see available devices.", + "connected-devices": "Connected devices", + "known-devices": "Known devices", + "available-devices": "Available devices", + "scanning": "Scanning for devices...", + "pairing-mode": "Make sure your device is in pairing mode." + } + }, + "wifi": { + "panel": { + "title": "Wi-Fi", + "disabled": "Wi-Fi is disabled", + "enable-message": "Enable Wi-Fi to see available networks.", + "searching": "Searching for nearby networks...", + "connected": "Connected", + "disconnecting": "Disconnecting...", + "forgetting": "Forgetting...", + "saved": "Saved", + "disconnect": "Disconnect", + "enter-password": "Enter password...", + "connect": "Connect", + "password": "Password", + "forget-network": "Forget this network?", + "forget": "Forget", + "no-networks": "No networks found", + "scan-again": "Scan again" + } + }, + "calendar": { + "panel": { + "week": "Week" + } + }, + "clock": { + "tooltip": "Open calendar" + }, + "dock": { + "menu": { + "focus": "Focus", + "pin": "Pin", + "unpin": "Unpin", + "close": "Close" + } + }, + "lock-screen": { + "secure-terminal": "SECURE TERMINAL", + "unlock-command": "sudo unlock-session", + "password": "Password:", + "shut-down": "Shut down", + "restart": "Restart", + "suspend": "Suspend" } } diff --git a/Bin/check-i18n.sh b/Bin/i18n-check.sh similarity index 100% rename from Bin/check-i18n.sh rename to Bin/i18n-check.sh diff --git a/Modules/Bar/Bluetooth/BluetoothPanel.qml b/Modules/Bar/Bluetooth/BluetoothPanel.qml index ce9fafc6..73706d91 100644 --- a/Modules/Bar/Bluetooth/BluetoothPanel.qml +++ b/Modules/Bar/Bluetooth/BluetoothPanel.qml @@ -35,7 +35,7 @@ NPanel { } NText { - text: "Bluetooth" + text: I18n.tr("bluetooth.panel.title") font.pointSize: Style.fontSizeL * scaling font.weight: Style.fontWeightBold color: Color.mOnSurface @@ -94,14 +94,14 @@ NPanel { } NText { - text: "Bluetooth is disabled" + text: I18n.tr("bluetooth.panel.disabled") font.pointSize: Style.fontSizeL * scaling color: Color.mOnSurfaceVariant Layout.alignment: Qt.AlignHCenter } NText { - text: "Enable Bluetooth to see available devices." + text: I18n.tr("bluetooth.panel.enable-message") font.pointSize: Style.fontSizeS * scaling color: Color.mOnSurfaceVariant Layout.alignment: Qt.AlignHCenter @@ -124,7 +124,7 @@ NPanel { // Connected devices BluetoothDevicesList { - label: "Connected devices" + label: I18n.tr("bluetooth.panel.connected-devices") property var items: { if (!BluetoothService.adapter || !Bluetooth.devices) return [] @@ -138,7 +138,7 @@ NPanel { // Known devices BluetoothDevicesList { - label: "Known devices" + label: I18n.tr("bluetooth.panel.known-devices") tooltipText: "Left click to connect. Right click to forget." property var items: { if (!BluetoothService.adapter || !Bluetooth.devices) @@ -153,7 +153,7 @@ NPanel { // Available devices BluetoothDevicesList { - label: "Available devices" + label: I18n.tr("bluetooth.panel.available-devices") property var items: { if (!BluetoothService.adapter || !Bluetooth.devices) return [] @@ -199,14 +199,14 @@ NPanel { } NText { - text: "Scanning for devices..." + text: I18n.tr("bluetooth.panel.scanning") font.pointSize: Style.fontSizeL * scaling color: Color.mOnSurface } } NText { - text: "Make sure your device is in pairing mode." + text: I18n.tr("bluetooth.panel.pairing-mode") font.pointSize: Style.fontSizeM * scaling color: Color.mOnSurfaceVariant Layout.alignment: Qt.AlignHCenter diff --git a/Modules/Bar/Calendar/CalendarPanel.qml b/Modules/Bar/Calendar/CalendarPanel.qml index 4446fa78..4789f767 100644 --- a/Modules/Bar/Calendar/CalendarPanel.qml +++ b/Modules/Bar/Calendar/CalendarPanel.qml @@ -81,7 +81,7 @@ NPanel { NText { anchors.centerIn: parent - text: "Week" + text: I18n.tr("calendar.panel.week") color: Color.mOutline font.pointSize: Style.fontSizeXS * scaling font.weight: Style.fontWeightRegular diff --git a/Modules/Bar/WiFi/WiFiPanel.qml b/Modules/Bar/WiFi/WiFiPanel.qml index 056241f5..a0ca5053 100644 --- a/Modules/Bar/WiFi/WiFiPanel.qml +++ b/Modules/Bar/WiFi/WiFiPanel.qml @@ -40,7 +40,7 @@ NPanel { } NText { - text: "Wi-Fi" + text: I18n.tr("wifi.panel.title") font.pointSize: Style.fontSizeL * scaling font.weight: Style.fontWeightBold color: Color.mOnSurface @@ -136,14 +136,14 @@ NPanel { } NText { - text: "Wi-Fi is disabled" + text: I18n.tr("wifi.panel.disabled") font.pointSize: Style.fontSizeL * scaling color: Color.mOnSurfaceVariant Layout.alignment: Qt.AlignHCenter } NText { - text: "Enable Wi-Fi to see available networks." + text: I18n.tr("wifi.panel.enable-message") font.pointSize: Style.fontSizeS * scaling color: Color.mOnSurfaceVariant Layout.alignment: Qt.AlignHCenter @@ -172,7 +172,7 @@ NPanel { } NText { - text: "Searching for nearby networks..." + text: I18n.tr("wifi.panel.searching") font.pointSize: Style.fontSizeNormal * scaling color: Color.mOnSurfaceVariant Layout.alignment: Qt.AlignHCenter @@ -295,7 +295,7 @@ NPanel { NText { id: connectedText anchors.centerIn: parent - text: "Connected" + text: I18n.tr("wifi.panel.connected") font.pointSize: Style.fontSizeXXS * scaling color: Color.mOnPrimary } @@ -311,7 +311,7 @@ NPanel { NText { id: disconnectingText anchors.centerIn: parent - text: "Disconnecting..." + text: I18n.tr("wifi.panel.disconnecting") font.pointSize: Style.fontSizeXXS * scaling color: Color.mOnPrimary } @@ -327,7 +327,7 @@ NPanel { NText { id: forgettingText anchors.centerIn: parent - text: "Forgetting..." + text: I18n.tr("wifi.panel.forgetting") font.pointSize: Style.fontSizeXXS * scaling color: Color.mOnPrimary } @@ -345,7 +345,7 @@ NPanel { NText { id: savedText anchors.centerIn: parent - text: "Saved" + text: I18n.tr("wifi.panel.saved") font.pointSize: Style.fontSizeXXS * scaling color: Color.mOnSurfaceVariant } @@ -376,10 +376,10 @@ NPanel { visible: !modelData.connected && NetworkService.connectingTo !== modelData.ssid && passwordSsid !== modelData.ssid && NetworkService.forgettingNetwork !== modelData.ssid && NetworkService.disconnectingFrom !== modelData.ssid text: { if (modelData.existing || modelData.cached) - return "Connect" + return I18n.tr("wifi.panel.connect") if (!NetworkService.isSecured(modelData.security)) - return "Connect" - return "Password" + return I18n.tr("wifi.panel.connect") + return I18n.tr("wifi.panel.password") } outlined: !hovered fontSize: Style.fontSizeXS * scaling @@ -397,7 +397,7 @@ NPanel { NButton { visible: modelData.connected && NetworkService.disconnectingFrom !== modelData.ssid - text: "Disconnect" + text: I18n.tr("wifi.panel.disconnect") outlined: !hovered fontSize: Style.fontSizeXS * scaling backgroundColor: Color.mError @@ -457,7 +457,7 @@ NPanel { Text { visible: parent.text.length === 0 anchors.verticalCenter: parent.verticalCenter - text: "Enter password..." + text: I18n.tr("wifi.panel.enter-password") color: Color.mOnSurfaceVariant font.pointSize: Style.fontSizeS * scaling } @@ -465,7 +465,7 @@ NPanel { } NButton { - text: "Connect" + text: I18n.tr("wifi.panel.connect") fontSize: Style.fontSizeXXS * scaling enabled: passwordInput.length > 0 && !NetworkService.connecting outlined: true @@ -511,7 +511,7 @@ NPanel { } NText { - text: "Forget this network?" + text: I18n.tr("wifi.panel.forget-network") font.pointSize: Style.fontSizeS * scaling color: Color.mError Layout.fillWidth: true @@ -520,7 +520,7 @@ NPanel { NButton { id: forgetButton - text: "Forget" + text: I18n.tr("wifi.panel.forget") fontSize: Style.fontSizeXXS * scaling backgroundColor: Color.mError outlined: forgetButton.hovered ? false : true @@ -561,14 +561,14 @@ NPanel { } NText { - text: "No networks found" + text: I18n.tr("wifi.panel.no-networks") font.pointSize: Style.fontSizeL * scaling color: Color.mOnSurfaceVariant Layout.alignment: Qt.AlignHCenter } NButton { - text: "Scan again" + text: I18n.tr("wifi.panel.scan-again") icon: "refresh" Layout.alignment: Qt.AlignHCenter onClicked: NetworkService.scan() diff --git a/Modules/Bar/Widgets/Clock.qml b/Modules/Bar/Widgets/Clock.qml index b2592422..4a21bb10 100644 --- a/Modules/Bar/Widgets/Clock.qml +++ b/Modules/Bar/Widgets/Clock.qml @@ -108,7 +108,7 @@ Rectangle { } NTooltip { id: tooltip - text: "Open calendar" + text: I18n.tr("clock.tooltip") target: clockContainer positionAbove: Settings.data.bar.position === "bottom" } diff --git a/Modules/Dock/DockMenu.qml b/Modules/Dock/DockMenu.qml index ff4cfa78..a2175ae5 100644 --- a/Modules/Dock/DockMenu.qml +++ b/Modules/Dock/DockMenu.qml @@ -133,7 +133,7 @@ PopupWindow { } NText { - text: "Focus" + text: I18n.tr("dock.menu.focus") font.pointSize: Style.fontSizeS * scaling color: activateMouseArea.containsMouse ? Color.mOnTertiary : Color.mOnSurfaceVariant anchors.verticalCenter: parent.verticalCenter @@ -182,8 +182,8 @@ PopupWindow { NText { text: { if (!root.toplevel) - return "Pin" - return root.isAppPinned(root.toplevel.appId) ? "Unpin" : "Pin" + return I18n.tr("dock.menu.pin") + return root.isAppPinned(root.toplevel.appId) ? I18n.tr("dock.menu.unpin") : I18n.tr("dock.menu.pin") } font.pointSize: Style.fontSizeS * scaling color: pinMouseArea.containsMouse ? Color.mOnTertiary : Color.mOnSurfaceVariant @@ -228,7 +228,7 @@ PopupWindow { } NText { - text: "Close" + text: I18n.tr("dock.menu.close") font.pointSize: Style.fontSizeS * scaling color: closeMouseArea.containsMouse ? Color.mOnTertiary : Color.mOnSurfaceVariant anchors.verticalCenter: parent.verticalCenter diff --git a/Modules/LockScreen/LockScreen.qml b/Modules/LockScreen/LockScreen.qml index 16219f92..89611629 100644 --- a/Modules/LockScreen/LockScreen.qml +++ b/Modules/LockScreen/LockScreen.qml @@ -383,7 +383,7 @@ Loader { spacing: Style.marginL * scaling NText { - text: "SECURE TERMINAL" + text: I18n.tr("lock-screen.secure-terminal") color: Color.mOnSurface font.family: Settings.data.ui.fontFixed font.pointSize: Style.fontSizeL * scaling @@ -486,7 +486,7 @@ Loader { } NText { - text: "sudo unlock-session" + text: I18n.tr("lock-screen.unlock-command") color: Color.mOnSurface font.family: Settings.data.ui.fontFixed font.pointSize: Style.fontSizeL * scaling @@ -498,7 +498,7 @@ Loader { spacing: Style.marginM * scaling NText { - text: "Password:" + text: I18n.tr("lock-screen.password") color: Color.mPrimary font.family: Settings.data.ui.fontFixed font.pointSize: Style.fontSizeL * scaling @@ -902,7 +902,7 @@ Loader { id: shutdownTooltipText anchors.margins: Style.marginM * scaling anchors.fill: parent - text: "Shut down" + text: I18n.tr("lock-screen.shut-down") font.pointSize: Style.fontSizeM * scaling horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter @@ -953,7 +953,7 @@ Loader { id: restartTooltipText anchors.margins: Style.marginM * scaling anchors.fill: parent - text: "Restart" + text: I18n.tr("lock-screen.restart") font.pointSize: Style.fontSizeM * scaling horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter @@ -1005,7 +1005,7 @@ Loader { id: suspendTooltipText anchors.margins: Style.marginM * scaling anchors.fill: parent - text: "Suspend" + text: I18n.tr("lock-screen.suspend") font.pointSize: Style.fontSizeM * scaling horizontalAlignment: Text.AlignHCenter verticalAlignment: Text.AlignVCenter diff --git a/Modules/Notification/NotificationHistoryPanel.qml b/Modules/Notification/NotificationHistoryPanel.qml index 35f92d0a..220b26f4 100644 --- a/Modules/Notification/NotificationHistoryPanel.qml +++ b/Modules/Notification/NotificationHistoryPanel.qml @@ -37,7 +37,7 @@ NPanel { } NText { - text: "Notifications" + text: I18n.tr("notifications.panel.title") font.pointSize: Style.fontSizeL * scaling font.weight: Style.fontWeightBold color: Color.mOnSurface @@ -94,14 +94,14 @@ NPanel { } NText { - text: "No notifications" + text: I18n.tr("notifications.panel.no-notifications") font.pointSize: Style.fontSizeL * scaling color: Color.mOnSurfaceVariant Layout.alignment: Qt.AlignHCenter } NText { - text: "Your notifications will show up here as they arrive." + text: I18n.tr("notifications.panel.description") font.pointSize: Style.fontSizeS * scaling color: Color.mOnSurfaceVariant Layout.alignment: Qt.AlignHCenter diff --git a/Modules/Settings/Bar/BarSectionEditor.qml b/Modules/Settings/Bar/BarSectionEditor.qml index 39dc62e3..1e6d1d46 100644 --- a/Modules/Settings/Bar/BarSectionEditor.qml +++ b/Modules/Settings/Bar/BarSectionEditor.qml @@ -84,7 +84,7 @@ NBox { model: availableWidgets label: "" description: "" - placeholder: "Select a widget to add..." + placeholder: I18n.tr("bar.widget-settings.section-editor.placeholder") onSelected: key => comboBox.currentKey = key popupHeight: 340 * scaling diff --git a/Modules/Settings/Bar/BarWidgetSettingsDialog.qml b/Modules/Settings/Bar/BarWidgetSettingsDialog.qml index 86344997..72981f85 100644 --- a/Modules/Settings/Bar/BarWidgetSettingsDialog.qml +++ b/Modules/Settings/Bar/BarWidgetSettingsDialog.qml @@ -101,13 +101,13 @@ Popup { } NButton { - text: "Cancel" + text: I18n.tr("bar.widget-settings.dialog.cancel") outlined: true onClicked: widgetSettings.close() } NButton { - text: "Apply" + text: I18n.tr("bar.widget-settings.dialog.apply") icon: "check" onClicked: { if (settingsLoader.item && settingsLoader.item.saveSettings) { diff --git a/Modules/Settings/Bar/WidgetSettings/ActiveWindowSettings.qml b/Modules/Settings/Bar/WidgetSettings/ActiveWindowSettings.qml index eabf5876..72366ffd 100644 --- a/Modules/Settings/Bar/WidgetSettings/ActiveWindowSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/ActiveWindowSettings.qml @@ -25,7 +25,7 @@ ColumnLayout { NToggle { id: showIcon Layout.fillWidth: true - label: "Show app icon" + label: I18n.tr("bar.widget-settings.active-window.show-app-icon") checked: root.valueShowIcon onToggled: checked => root.valueShowIcon = checked } diff --git a/Modules/Settings/Bar/WidgetSettings/BatterySettings.qml b/Modules/Settings/Bar/WidgetSettings/BatterySettings.qml index 24094fce..977e49e5 100644 --- a/Modules/Settings/Bar/WidgetSettings/BatterySettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/BatterySettings.qml @@ -25,8 +25,8 @@ ColumnLayout { } NComboBox { - label: "Display mode" - description: "Choose how you'd like this value to appear." + label: I18n.tr("bar.widget-settings.battery.display-mode.label") + description: I18n.tr("bar.widget-settings.battery.display-mode.description") minimumWidth: 134 * scaling model: ListModel { ListElement { @@ -47,8 +47,8 @@ ColumnLayout { } NSpinBox { - label: "Low battery warning threshold" - description: "Show a warning when battery falls below this percentage." + label: I18n.tr("bar.widget-settings.battery.low-battery-threshold.label") + description: I18n.tr("bar.widget-settings.battery.low-battery-threshold.description") value: valueWarningThreshold suffix: "%" minimum: 5 diff --git a/Modules/Settings/Bar/WidgetSettings/BrightnessSettings.qml b/Modules/Settings/Bar/WidgetSettings/BrightnessSettings.qml index e8e0465d..c54ca3ac 100644 --- a/Modules/Settings/Bar/WidgetSettings/BrightnessSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/BrightnessSettings.qml @@ -23,8 +23,8 @@ ColumnLayout { } NComboBox { - label: "Display mode" - description: "Choose how you'd like this value to appear." + label: I18n.tr("bar.widget-settings.brightness.display-mode.label") + description: I18n.tr("bar.widget-settings.brightness.display-mode.description") minimumWidth: 134 * scaling model: ListModel { ListElement { diff --git a/Modules/Settings/Bar/WidgetSettings/ClockSettings.qml b/Modules/Settings/Bar/WidgetSettings/ClockSettings.qml index 60e2794c..ca6c300d 100644 --- a/Modules/Settings/Bar/WidgetSettings/ClockSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/ClockSettings.qml @@ -64,16 +64,16 @@ ColumnLayout { NToggle { Layout.fillWidth: true - label: "Use primary color" - description: "When enabled, this applies the primary color for emphasis." + label: I18n.tr("bar.widget-settings.clock.use-primary-color.label") + description: I18n.tr("bar.widget-settings.clock.use-primary-color.description") checked: valueUsePrimaryColor onToggled: checked => valueUsePrimaryColor = checked } NToggle { Layout.fillWidth: true - label: "Use monospaced font" - description: "When enabled, the clock will use the monospaced font." + label: I18n.tr("bar.widget-settings.clock.use-monospaced-font.label") + description: I18n.tr("bar.widget-settings.clock.use-monospaced-font.description") checked: valueUseMonospacedFont onToggled: checked => valueUseMonospacedFont = checked } @@ -83,8 +83,8 @@ ColumnLayout { } NHeader { - label: "Clock display" - description: "Customize your clock's display by adding tokens from the list below. To use the 12-hour format, you must include the 'AP' token." + label: I18n.tr("bar.widget-settings.clock.clock-display.label") + description: I18n.tr("bar.widget-settings.clock.clock-display.description") } RowLayout { @@ -104,8 +104,8 @@ ColumnLayout { NTextInput { id: inputHoriz Layout.fillWidth: true - label: "Horizontal bar" - description: "Tip: Use \\n to create a line break." + label: I18n.tr("bar.widget-settings.clock.horizontal-bar.label") + description: I18n.tr("bar.widget-settings.clock.horizontal-bar.description") placeholderText: "HH:mm ddd, MMM dd" text: valueFormatHorizontal onTextChanged: valueFormatHorizontal = text @@ -127,8 +127,8 @@ ColumnLayout { NTextInput { id: inputVert Layout.fillWidth: true - label: "Vertical bar" - description: "Use a space to separate each part onto a new line." + label: I18n.tr("bar.widget-settings.clock.vertical-bar.label") + description: I18n.tr("bar.widget-settings.clock.vertical-bar.description") placeholderText: "HH mm dd MM" text: valueFormatVertical onTextChanged: valueFormatVertical = text @@ -151,7 +151,7 @@ ColumnLayout { Layout.fillWidth: false NLabel { - label: "Preview" + label: I18n.tr("bar.widget-settings.clock.preview") Layout.alignment: Qt.AlignHCenter | Qt.AlignTop } diff --git a/Modules/Settings/Bar/WidgetSettings/ControlCenterSettings.qml b/Modules/Settings/Bar/WidgetSettings/ControlCenterSettings.qml index 9c6ab6a9..c3dcabfc 100644 --- a/Modules/Settings/Bar/WidgetSettings/ControlCenterSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/ControlCenterSettings.qml @@ -27,7 +27,7 @@ ColumnLayout { } NToggle { - label: "Use distro logo instead of icon" + label: I18n.tr("bar.widget-settings.control-center.use-distro-logo") checked: valueUseDistroLogo onToggled: { valueUseDistroLogo = checked @@ -42,8 +42,8 @@ ColumnLayout { spacing: Style.marginM * scaling NLabel { - label: "Icon" - description: "Select an icon from the library or a custom file." + label: I18n.tr("bar.widget-settings.control-center.icon.label") + description: I18n.tr("bar.widget-settings.control-center.icon.description") } NImageCircled { @@ -66,13 +66,13 @@ ColumnLayout { spacing: Style.marginM * scaling NButton { enabled: !valueUseDistroLogo - text: "Browse Library" + text: I18n.tr("bar.widget-settings.control-center.browse-library") onClicked: iconPicker.open() } NButton { enabled: !valueUseDistroLogo - text: "Browse File" + text: I18n.tr("bar.widget-settings.control-center.browse-file") onClicked: filePicker.open() } } @@ -88,7 +88,7 @@ ColumnLayout { NFilePicker { id: filePicker - title: "Select a custom icon" + title: I18n.tr("bar.widget-settings.control-center.select-custom-icon") onAccepted: paths => valueCustomIconPath = paths[0] } } diff --git a/Modules/Settings/Bar/WidgetSettings/CustomButtonSettings.qml b/Modules/Settings/Bar/WidgetSettings/CustomButtonSettings.qml index 7586f280..34964e44 100644 --- a/Modules/Settings/Bar/WidgetSettings/CustomButtonSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/CustomButtonSettings.qml @@ -30,8 +30,8 @@ ColumnLayout { spacing: Style.marginM * scaling NLabel { - label: "Icon" - description: "Select an icon from the library." + label: I18n.tr("bar.widget-settings.custom-button.icon.label") + description: I18n.tr("bar.widget-settings.custom-button.icon.description") } NIcon { @@ -42,7 +42,7 @@ ColumnLayout { } NButton { - text: "Browse" + text: I18n.tr("bar.widget-settings.custom-button.browse") onClicked: iconPicker.open() } } @@ -58,7 +58,7 @@ ColumnLayout { NTextInput { id: leftClickExecInput Layout.fillWidth: true - label: "Left click" + label: I18n.tr("bar.widget-settings.custom-button.left-click") placeholderText: "Enter command to execute (app or custom script)" text: widgetData?.leftClickExec || widgetMetadata.leftClickExec } @@ -66,7 +66,7 @@ ColumnLayout { NTextInput { id: rightClickExecInput Layout.fillWidth: true - label: "Right click" + label: I18n.tr("bar.widget-settings.custom-button.right-click") placeholderText: "Enter command to execute (app or custom script)" text: widgetData?.rightClickExec || widgetMetadata.rightClickExec } @@ -74,7 +74,7 @@ ColumnLayout { NTextInput { id: middleClickExecInput Layout.fillWidth: true - label: "Middle click" + label: I18n.tr("bar.widget-settings.custom-button.middle-click") placeholderText: "Enter command to execute (app or custom script)" text: widgetData.middleClickExec || widgetMetadata.middleClickExec } @@ -84,14 +84,14 @@ ColumnLayout { } NHeader { - label: "Dynamic text" + label: I18n.tr("bar.widget-settings.custom-button.dynamic-text") } NTextInput { id: textCommandInput Layout.fillWidth: true - label: "Display Command Output" - description: "Enter a command to run at a regular interval. The first line of its output will be displayed as text." + label: I18n.tr("bar.widget-settings.custom-button.display-command-output.label") + description: I18n.tr("bar.widget-settings.custom-button.display-command-output.description") placeholderText: "echo \"Hello World\"" text: widgetData?.textCommand || widgetMetadata.textCommand } @@ -99,8 +99,8 @@ ColumnLayout { NTextInput { id: textIntervalInput Layout.fillWidth: true - label: "Refresh interval" - description: "Interval in milliseconds." + label: I18n.tr("bar.widget-settings.custom-button.refresh-interval.label") + description: I18n.tr("bar.widget-settings.custom-button.refresh-interval.description") placeholderText: String(widgetMetadata.textIntervalMs || 3000) text: widgetData && widgetData.textIntervalMs !== undefined ? String(widgetData.textIntervalMs) : "" } diff --git a/Modules/Settings/Bar/WidgetSettings/KeyboardLayoutSettings.qml b/Modules/Settings/Bar/WidgetSettings/KeyboardLayoutSettings.qml index 875fffa9..36ad8042 100644 --- a/Modules/Settings/Bar/WidgetSettings/KeyboardLayoutSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/KeyboardLayoutSettings.qml @@ -23,8 +23,8 @@ ColumnLayout { } NComboBox { - label: "Display mode" - description: "Choose how you'd like this value to appear." + label: I18n.tr("bar.widget-settings.keyboard-layout.display-mode.label") + description: I18n.tr("bar.widget-settings.keyboard-layout.display-mode.description") minimumWidth: 134 * scaling model: ListModel { ListElement { diff --git a/Modules/Settings/Bar/WidgetSettings/MediaMiniSettings.qml b/Modules/Settings/Bar/WidgetSettings/MediaMiniSettings.qml index fb70f9da..a82187c1 100644 --- a/Modules/Settings/Bar/WidgetSettings/MediaMiniSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/MediaMiniSettings.qml @@ -27,20 +27,20 @@ ColumnLayout { } NToggle { - label: "Show album art" + label: I18n.tr("bar.widget-settings.media-mini.show-album-art") checked: valueShowAlbumArt onToggled: checked => valueShowAlbumArt = checked } NToggle { - label: "Show visualizer" + label: I18n.tr("bar.widget-settings.media-mini.show-visualizer") checked: valueShowVisualizer onToggled: checked => valueShowVisualizer = checked } NComboBox { visible: valueShowVisualizer - label: "Visualizer type" + label: I18n.tr("bar.widget-settings.media-mini.visualizer-type") model: ListModel { ListElement { key: "linear" diff --git a/Modules/Settings/Bar/WidgetSettings/MicrophoneSettings.qml b/Modules/Settings/Bar/WidgetSettings/MicrophoneSettings.qml index e8e0465d..d832b0d6 100644 --- a/Modules/Settings/Bar/WidgetSettings/MicrophoneSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/MicrophoneSettings.qml @@ -23,8 +23,8 @@ ColumnLayout { } NComboBox { - label: "Display mode" - description: "Choose how you'd like this value to appear." + label: I18n.tr("bar.widget-settings.microphone.display-mode.label") + description: I18n.tr("bar.widget-settings.microphone.display-mode.description") minimumWidth: 134 * scaling model: ListModel { ListElement { diff --git a/Modules/Settings/Bar/WidgetSettings/NotificationHistorySettings.qml b/Modules/Settings/Bar/WidgetSettings/NotificationHistorySettings.qml index 751a832a..206c2797 100644 --- a/Modules/Settings/Bar/WidgetSettings/NotificationHistorySettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/NotificationHistorySettings.qml @@ -25,13 +25,13 @@ ColumnLayout { } NToggle { - label: "Show unread badge" + label: I18n.tr("bar.widget-settings.notification-history.show-unread-badge") checked: valueShowUnreadBadge onToggled: checked => valueShowUnreadBadge = checked } NToggle { - label: "Hide badge when zero" + label: I18n.tr("bar.widget-settings.notification-history.hide-badge-when-zero") checked: valueHideWhenZero onToggled: checked => valueHideWhenZero = checked } diff --git a/Modules/Settings/Bar/WidgetSettings/SpacerSettings.qml b/Modules/Settings/Bar/WidgetSettings/SpacerSettings.qml index 8de5f6ee..1ecd2740 100644 --- a/Modules/Settings/Bar/WidgetSettings/SpacerSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/SpacerSettings.qml @@ -22,8 +22,8 @@ ColumnLayout { NTextInput { id: widthInput Layout.fillWidth: true - label: "Width" - description: "Spacing width in pixels" + label: I18n.tr("bar.widget-settings.spacer.width.label") + description: I18n.tr("bar.widget-settings.spacer.width.description") text: widgetData.width || widgetMetadata.width placeholderText: "Enter width in pixels" } diff --git a/Modules/Settings/Bar/WidgetSettings/SystemMonitorSettings.qml b/Modules/Settings/Bar/WidgetSettings/SystemMonitorSettings.qml index d2cee141..b7524c86 100644 --- a/Modules/Settings/Bar/WidgetSettings/SystemMonitorSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/SystemMonitorSettings.qml @@ -35,7 +35,7 @@ ColumnLayout { NToggle { id: showCpuUsage Layout.fillWidth: true - label: "CPU usage" + label: I18n.tr("bar.widget-settings.system-monitor.cpu-usage") checked: valueShowCpuUsage onToggled: checked => valueShowCpuUsage = checked } @@ -43,7 +43,7 @@ ColumnLayout { NToggle { id: showCpuTemp Layout.fillWidth: true - label: "CPU temperature" + label: I18n.tr("bar.widget-settings.system-monitor.cpu-temperature") checked: valueShowCpuTemp onToggled: checked => valueShowCpuTemp = checked } @@ -51,7 +51,7 @@ ColumnLayout { NToggle { id: showMemoryUsage Layout.fillWidth: true - label: "Memory usage" + label: I18n.tr("bar.widget-settings.system-monitor.memory-usage") checked: valueShowMemoryUsage onToggled: checked => valueShowMemoryUsage = checked } @@ -59,7 +59,7 @@ ColumnLayout { NToggle { id: showMemoryAsPercent Layout.fillWidth: true - label: "Memory as percentage" + label: I18n.tr("bar.widget-settings.system-monitor.memory-percentage") checked: valueShowMemoryAsPercent onToggled: checked => valueShowMemoryAsPercent = checked } @@ -67,7 +67,7 @@ ColumnLayout { NToggle { id: showNetworkStats Layout.fillWidth: true - label: "Network traffic" + label: I18n.tr("bar.widget-settings.system-monitor.network-traffic") checked: valueShowNetworkStats onToggled: checked => valueShowNetworkStats = checked } @@ -75,7 +75,7 @@ ColumnLayout { NToggle { id: showDiskUsage Layout.fillWidth: true - label: "Storage usage" + label: I18n.tr("bar.widget-settings.system-monitor.storage-usage") checked: valueShowDiskUsage onToggled: checked => valueShowDiskUsage = checked } diff --git a/Modules/Settings/Bar/WidgetSettings/VolumeSettings.qml b/Modules/Settings/Bar/WidgetSettings/VolumeSettings.qml index e8e0465d..00d63083 100644 --- a/Modules/Settings/Bar/WidgetSettings/VolumeSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/VolumeSettings.qml @@ -23,8 +23,8 @@ ColumnLayout { } NComboBox { - label: "Display mode" - description: "Choose how you'd like this value to appear." + label: I18n.tr("bar.widget-settings.volume.display-mode.label") + description: I18n.tr("bar.widget-settings.volume.display-mode.description") minimumWidth: 134 * scaling model: ListModel { ListElement { diff --git a/Modules/Settings/Bar/WidgetSettings/WorkspaceSettings.qml b/Modules/Settings/Bar/WidgetSettings/WorkspaceSettings.qml index a72c91cf..47854470 100644 --- a/Modules/Settings/Bar/WidgetSettings/WorkspaceSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/WorkspaceSettings.qml @@ -23,7 +23,7 @@ ColumnLayout { NComboBox { id: labelModeCombo - label: "Label Mode" + label: I18n.tr("bar.widget-settings.workspace.label-mode") model: ListModel { ListElement { key: "none" @@ -45,8 +45,8 @@ ColumnLayout { NToggle { id: hideUnoccupiedToggle - label: "Hide unoccupied" - description: "Don't display workspaces without windows." + label: I18n.tr("bar.widget-settings.workspace.hide-unoccupied.label") + description: I18n.tr("bar.widget-settings.workspace.hide-unoccupied.description") checked: widgetData.hideUnoccupied onToggled: checked => hideUnoccupiedToggle.checked = checked } diff --git a/Modules/Settings/Tabs/GeneralTab.qml b/Modules/Settings/Tabs/GeneralTab.qml index 7079b484..0d748a97 100644 --- a/Modules/Settings/Tabs/GeneralTab.qml +++ b/Modules/Settings/Tabs/GeneralTab.qml @@ -155,8 +155,8 @@ ColumnLayout { Layout.fillWidth: true NLabel { - label: "Screen corners radius" - description: "Adjust the rounded corners of the screen." + label: I18n.tr("settings.general.screen-corners.radius.label") + description: I18n.tr("settings.general.screen-corners.radius.description") } NValueSlider { diff --git a/Modules/Wallpaper/WallpaperPanel.qml b/Modules/Wallpaper/WallpaperPanel.qml index 7c0bad58..2b6b8fb6 100644 --- a/Modules/Wallpaper/WallpaperPanel.qml +++ b/Modules/Wallpaper/WallpaperPanel.qml @@ -56,7 +56,7 @@ NPanel { } NText { - text: "Wallpaper selector" + text: I18n.tr("wallpaper.panel.title") font.pointSize: Style.fontSizeL * scaling font.weight: Style.fontWeightBold color: Color.mOnSurface @@ -83,8 +83,8 @@ NPanel { } NToggle { - label: "Apply to all monitors" - description: "Apply selected wallpaper to all monitors at once." + label: I18n.tr("wallpaper.panel.apply-all-monitors.label") + description: I18n.tr("wallpaper.panel.apply-all-monitors.description") checked: Settings.data.wallpaper.setWallpaperOnAllMonitors onToggled: checked => Settings.data.wallpaper.setWallpaperOnAllMonitors = checked Layout.fillWidth: true @@ -175,7 +175,7 @@ NPanel { spacing: Style.marginM * scaling NText { - text: "Search:" + text: I18n.tr("wallpaper.panel.search") color: Color.mOnSurface font.pointSize: Style.fontSizeM * scaling Layout.preferredWidth: implicitWidth diff --git a/Widgets/NColorPickerDialog.qml b/Widgets/NColorPickerDialog.qml index 836fb4ab..7c823444 100644 --- a/Widgets/NColorPickerDialog.qml +++ b/Widgets/NColorPickerDialog.qml @@ -143,7 +143,7 @@ Popup { } NText { - text: "Color picker" + text: I18n.tr("widgets.color-picker.title") font.pointSize: Style.fontSizeXL * scaling font.weight: Style.fontWeightBold color: Color.mPrimary @@ -206,8 +206,8 @@ Popup { spacing: Style.marginM * scaling NLabel { - label: "Hex color" - description: "Enter a hexadecimal color code." + label: I18n.tr("widgets.color-picker.hex.label") + description: I18n.tr("widgets.color-picker.hex.description") Layout.fillWidth: true } @@ -235,8 +235,8 @@ Popup { spacing: Style.marginM * scaling NLabel { - label: "RGB values" - description: "Adjust red, green, blue, and brightness values." + label: I18n.tr("widgets.color-picker.rgb.label") + description: I18n.tr("widgets.color-picker.rgb.description") Layout.fillWidth: true } @@ -325,7 +325,7 @@ Popup { spacing: Style.marginM * scaling NText { - text: "Brightness" + text: I18n.tr("widgets.color-picker.brightness") font.weight: Font.Bold Layout.preferredWidth: 80 * scaling } @@ -371,8 +371,8 @@ Popup { spacing: Style.marginS * scaling NLabel { - label: "Theme colors" - description: "Quick access to your theme's color palette." + label: I18n.tr("widgets.color-picker.theme-colors.label") + description: I18n.tr("widgets.color-picker.theme-colors.description") Layout.fillWidth: true } @@ -419,8 +419,8 @@ Popup { spacing: Style.marginS * scaling NLabel { - label: "Palette" - description: "Choose from a wide range of predefined colors." + label: I18n.tr("widgets.color-picker.palette.label") + description: I18n.tr("widgets.color-picker.palette.description") Layout.fillWidth: true } @@ -469,7 +469,7 @@ Popup { NButton { id: cancelButton - text: "Cancel" + text: I18n.tr("widgets.color-picker.cancel") outlined: cancelButton.hovered ? false : true onClicked: { root.close() @@ -477,7 +477,7 @@ Popup { } NButton { - text: "Apply" + text: I18n.tr("widgets.color-picker.apply") icon: "check" onClicked: { root.colorSelected(root.selectedColor) diff --git a/Widgets/NDateTimeTokens.qml b/Widgets/NDateTimeTokens.qml index 904f3c29..8f5aac16 100644 --- a/Widgets/NDateTimeTokens.qml +++ b/Widgets/NDateTimeTokens.qml @@ -31,87 +31,62 @@ Rectangle { ListElement { category: "Common" token: "h:mm AP" - description: "12-hour time with minutes" + description: I18n.tr("widgets.datetime-tokens.common.12hour-time-minutes") example: "2:30 PM" } ListElement { category: "Common" token: "HH:mm" - description: "24-hour time with minutes" + description: I18n.tr("widgets.datetime-tokens.common.24hour-time-minutes") example: "14:30" } ListElement { category: "Common" token: "HH:mm:ss" - description: "24-hour time with seconds" + description: I18n.tr("widgets.datetime-tokens.common.24hour-time-seconds") example: "14:30:45" } ListElement { category: "Common" token: "ddd MMM d" - description: "Weekday, month and day" + description: I18n.tr("widgets.datetime-tokens.common.weekday-month-day") example: "Mon Dec 25" } ListElement { category: "Common" token: "yyyy-MM-dd" - description: "ISO date format" + description: I18n.tr("widgets.datetime-tokens.common.iso-date") example: "2023-12-25" } ListElement { category: "Common" token: "MM/dd/yyyy" - description: "US date format" + description: I18n.tr("widgets.datetime-tokens.common.us-date") example: "12/25/2023" } ListElement { category: "Common" token: "dd.MM.yyyy" - description: "European date format" + description: I18n.tr("widgets.datetime-tokens.common.european-date") example: "25.12.2023" } ListElement { category: "Common" token: "ddd, MMM dd" - description: "Weekday with date" + description: I18n.tr("widgets.datetime-tokens.common.weekday-date") example: "Fri, Dec 12" } - // Hour tokens - // ListElement { - // category: "Hour" - // token: "h" - // description: "Hour without leading zero (12-hour when used with AP/ap, otherwise 24-hour)" - // example: "2 (needs AP/ap for 12hr)" - // } - // ListElement { - // category: "Hour" - // token: "hh" - // description: "Hour with leading zero (12-hour when used with AP/ap, otherwise 24-hour)" - // example: "02 (needs AP/ap for 12hr)" - // } - // ListElement { - // category: "Hour" - // token: "h AP" - // description: "12-hour format with AM/PM" - // example: "2 PM" - // } - // ListElement { - // category: "Hour" - // token: "hh AP" - // description: "12-hour format with leading zero and AM/PM" - // example: "02 PM" - // } ListElement { category: "Hour" token: "H" - description: "Hour without leading zero (0-23) - 24-hour format" + description: I18n.tr("widgets.datetime-tokens.hour.no-leading-zero") example: "14" } ListElement { category: "Hour" token: "HH" - description: "Hour with leading zero (00-23) - 24-hour format" + description: I18n.tr("widgets.datetime-tokens.hour.leading-zero") example: "14" } @@ -119,13 +94,13 @@ Rectangle { ListElement { category: "Minute" token: "m" - description: "Minute without leading zero (0-59)" + description: I18n.tr("widgets.datetime-tokens.minute.no-leading-zero") example: "30" } ListElement { category: "Minute" token: "mm" - description: "Minute with leading zero (00-59)" + description: I18n.tr("widgets.datetime-tokens.minute.leading-zero") example: "30" } @@ -133,13 +108,13 @@ Rectangle { ListElement { category: "Second" token: "s" - description: "Second without leading zero (0-59)" + description: I18n.tr("widgets.datetime-tokens.second.no-leading-zero") example: "45" } ListElement { category: "Second" token: "ss" - description: "Second with leading zero (00-59)" + description: I18n.tr("widgets.datetime-tokens.second.leading-zero") example: "45" } @@ -147,13 +122,13 @@ Rectangle { ListElement { category: "AM/PM" token: "AP" - description: "AM/PM in uppercase" + description: I18n.tr("widgets.datetime-tokens.ampm.uppercase") example: "PM" } ListElement { category: "AM/PM" token: "ap" - description: "am/pm in lowercase" + description: I18n.tr("widgets.datetime-tokens.ampm.lowercase") example: "pm" } @@ -161,7 +136,7 @@ Rectangle { ListElement { category: "Timezone" token: "t" - description: "Timezone abbreviation" + description: I18n.tr("widgets.datetime-tokens.timezone.abbreviation") example: "UTC" } @@ -169,13 +144,13 @@ Rectangle { ListElement { category: "Year" token: "yy" - description: "Year as two-digit number (00-99)" + description: I18n.tr("widgets.datetime-tokens.year.two-digit") example: "23" } ListElement { category: "Year" token: "yyyy" - description: "Year as four-digit number" + description: I18n.tr("widgets.datetime-tokens.year.four-digit") example: "2023" } @@ -183,25 +158,25 @@ Rectangle { ListElement { category: "Month" token: "M" - description: "Month as number without leading zero (1-12)" + description: I18n.tr("widgets.datetime-tokens.month.number-no-zero") example: "12" } ListElement { category: "Month" token: "MM" - description: "Month as number with leading zero (01-12)" + description: I18n.tr("widgets.datetime-tokens.month.number-leading-zero") example: "12" } ListElement { category: "Month" token: "MMM" - description: "Abbreviated month name" + description: I18n.tr("widgets.datetime-tokens.month.abbreviated") example: "Dec" } ListElement { category: "Month" token: "MMMM" - description: "Full month name" + description: I18n.tr("widgets.datetime-tokens.month.full") example: "December" } @@ -209,25 +184,25 @@ Rectangle { ListElement { category: "Day" token: "d" - description: "Day without leading zero (1-31)" + description: I18n.tr("widgets.datetime-tokens.day.no-leading-zero") example: "25" } ListElement { category: "Day" token: "dd" - description: "Day with leading zero (01-31)" + description: I18n.tr("widgets.datetime-tokens.day.leading-zero") example: "25" } ListElement { category: "Day" token: "ddd" - description: "Abbreviated day name" + description: I18n.tr("widgets.datetime-tokens.day.abbreviated") example: "Mon" } ListElement { category: "Day" token: "dddd" - description: "Full day name" + description: I18n.tr("widgets.datetime-tokens.day.full") example: "Monday" } } diff --git a/Widgets/NIconPicker.qml b/Widgets/NIconPicker.qml index c0ffaa49..4aecf9cb 100644 --- a/Widgets/NIconPicker.qml +++ b/Widgets/NIconPicker.qml @@ -63,7 +63,7 @@ Popup { RowLayout { Layout.fillWidth: true NText { - text: "Icon picker" + text: I18n.tr("widgets.icon-picker.title") font.pointSize: Style.fontSizeL * scaling font.weight: Style.fontWeightBold color: Color.mPrimary @@ -85,7 +85,7 @@ Popup { NTextInput { id: searchInput Layout.fillWidth: true - label: "Search" + label: I18n.tr("widgets.icon-picker.search.label") placeholderText: "e.g., noctalia, niri, battery, cloud" text: root.query onTextChanged: root.query = text.trim().toLowerCase() @@ -166,12 +166,12 @@ Popup { Layout.fillWidth: true } NButton { - text: "Cancel" + text: I18n.tr("widgets.icon-picker.cancel") outlined: true onClicked: root.close() } NButton { - text: "Apply" + text: I18n.tr("widgets.icon-picker.apply") icon: "check" enabled: root.selectedIcon !== "" onClicked: { diff --git a/Widgets/NTooltip.qml b/Widgets/NTooltip.qml index eb8afd19..67cf6169 100644 --- a/Widgets/NTooltip.qml +++ b/Widgets/NTooltip.qml @@ -6,7 +6,7 @@ Window { id: root property bool isVisible: false - property string text: "Placeholder" + property string text: I18n.tr("widgets.tooltip.placeholder") property Item target: null property int delay: Style.tooltipDelay property bool positionAbove: false From 2a23b6afddad2bdb3ebdd0a89ae63182656af70b Mon Sep 17 00:00:00 2001 From: Ly-sec Date: Wed, 24 Sep 2025 14:12:12 +0200 Subject: [PATCH 04/15] i18n: WAY more i18n conversion --- Assets/Translations/en.json | 123 ++++++++++++++++++ Modules/Bar/Bluetooth/BluetoothPanel.qml | 6 +- Modules/Bar/Calendar/CalendarPanel.qml | 4 +- Modules/Bar/WiFi/WiFiPanel.qml | 6 +- Modules/Bar/Widgets/Bluetooth.qml | 2 +- Modules/Bar/Widgets/ControlCenter.qml | 2 +- Modules/Bar/Widgets/DarkMode.qml | 2 +- Modules/Bar/Widgets/KeepAwake.qml | 2 +- Modules/Bar/Widgets/Microphone.qml | 2 +- Modules/Bar/Widgets/NightLight.qml | 2 +- Modules/Bar/Widgets/NotificationHistory.qml | 2 +- Modules/Bar/Widgets/ScreenRecorder.qml | 2 +- Modules/Bar/Widgets/SessionMenu.qml | 2 +- Modules/Bar/Widgets/Volume.qml | 2 +- Modules/Bar/Widgets/WallpaperSelector.qml | 2 +- Modules/Bar/Widgets/WiFi.qml | 2 +- Modules/ControlCenter/Cards/MediaCard.qml | 6 +- .../ControlCenter/Cards/PowerProfilesCard.qml | 6 +- Modules/ControlCenter/Cards/ProfileCard.qml | 6 +- Modules/ControlCenter/Cards/UtilitiesCard.qml | 6 +- Modules/Launcher/Launcher.qml | 2 +- .../Launcher/Plugins/ApplicationsPlugin.qml | 2 +- Modules/Launcher/Plugins/CalculatorPlugin.qml | 2 +- Modules/Launcher/Plugins/ClipboardPlugin.qml | 2 +- Modules/Notification/Notification.qml | 2 +- .../Notification/NotificationHistoryPanel.qml | 8 +- Modules/SessionMenu/SessionMenu.qml | 2 +- Modules/Settings/Bar/BarSectionEditor.qml | 6 +- .../Bar/WidgetSettings/BatterySettings.qml | 26 ++-- .../Bar/WidgetSettings/BrightnessSettings.qml | 26 ++-- .../Bar/WidgetSettings/ClockSettings.qml | 4 +- .../WidgetSettings/CustomButtonSettings.qml | 8 +- .../WidgetSettings/KeyboardLayoutSettings.qml | 26 ++-- .../Bar/WidgetSettings/MediaMiniSettings.qml | 26 ++-- .../Bar/WidgetSettings/MicrophoneSettings.qml | 26 ++-- .../Bar/WidgetSettings/SpacerSettings.qml | 2 +- .../Bar/WidgetSettings/VolumeSettings.qml | 26 ++-- .../Bar/WidgetSettings/WorkspaceSettings.qml | 26 ++-- Modules/Settings/SettingsPanel.qml | 2 +- Modules/Settings/Tabs/AudioTab.qml | 92 ++++++------- Modules/Settings/Tabs/GeneralTab.qml | 2 +- Modules/Settings/Tabs/ScreenRecorderTab.qml | 18 +-- Modules/Wallpaper/WallpaperPanel.qml | 6 +- Widgets/NIconPicker.qml | 2 +- 44 files changed, 327 insertions(+), 204 deletions(-) diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index 3f880aee..004d5278 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -925,6 +925,53 @@ "week": "Week" } }, + "tooltips": { + "refresh": "Refresh", + "close": "Close", + "refresh-wallpaper-list": "Refresh wallpaper list", + "refresh-devices": "Refresh devices", + "forget-network": "Forget network", + "clear-history": "Clear history", + "delete-notification": "Delete notification", + "previous-month": "Previous month", + "next-month": "Next month", + "add-widget": "Add widget", + "widget-settings": "Widget settings", + "remove-widget": "Remove widget", + "open-settings": "Open settings", + "session-menu": "Session Menu", + "close-side-panel": "Close side panel", + "cancel-timer": "Cancel timer", + "start-screen-recording": "Start screen recording", + "stop-screen-recording": "Stop screen recording", + "screen-recorder-not-installed": "Screen recorder is not installed", + "enable-keep-awake": "Enable keep awake", + "disable-keep-awake": "Disable keep awake", + "wallpaper-selector": "Left click: Open wallpaper selector.\nRight click: Set random wallpaper.", + "do-not-disturb-enabled": "'Do not disturb' enabled", + "do-not-disturb-disabled": "'Do not disturb' disabled", + "connect-disconnect-devices": "Left click to connect. Right click to forget.", + "set-power-profile": "Set \"{profile}\" power profile", + "switch-to-light-mode": "Switch to light mode", + "switch-to-dark-mode": "Switch to dark mode", + "night-light-disabled": "Night light is disabled.\nLeft click to cycle mode.\nRight click to access settings.", + "night-light-enabled": "Night light is enabled.\nLeft click to cycle mode.\nRight click to access settings.", + "night-light-forced": "Night light is forced.\nLeft click to cycle mode.\nRight click to access settings.", + "click-to-start-recording": "Click to start recording", + "click-to-stop-recording": "Click to stop recording", + "open-side-panel": "Open side panel", + "volume-at": "Volume at {volume}%\nLeft click to toggle mute. Right click for settings.\nScroll to modify volume.", + "microphone-volume-at": "Microphone volume at {volume}%\nLeft click to toggle mute. Right click for settings.\nScroll to modify volume.", + "manage-wifi": "Manage Wi-Fi", + "bluetooth-devices": "Bluetooth devices", + "open-notification-history-enable-dnd": "Open notification history\nRight-click to enable \"Do not disturb\".", + "open-notification-history-disable-dnd": "Open notification history\nRight-click to disable \"Do not disturb\".", + "open-wallpaper-selector": "Open wallpaper selector", + "previous-media": "Previous media", + "pause": "Pause", + "play": "Play", + "next-media": "Next media" + }, "clock": { "tooltip": "Open calendar" }, @@ -936,6 +983,82 @@ "close": "Close" } }, + "placeholders": { + "search-icons": "e.g., noctalia, niri, battery, cloud", + "profile-picture-path": "/home/user/.face", + "enter-width-pixels": "Enter width in pixels", + "enter-command": "Enter command to execute (app or custom script)", + "command-example": "echo \"Hello World\"", + "clock-horizontal": "HH:mm ddd, MMM dd", + "clock-vertical": "HH mm dd MM", + "search-wallpapers": "Type to filter wallpapers...", + "search-launcher": "Search entries... or use > for commands" + }, + "options": { + "display-mode": { + "on-hover": "On hover", + "always-show": "Always show", + "always-hide": "Always hide", + "force-open": "Force Open" + }, + "workspace-labels": { + "none": "None", + "index": "Index", + "name": "Name" + }, + "visualizer-types": { + "none": "None", + "linear": "Linear", + "mirrored": "Mirrored", + "wave": "Wave" + }, + "frame-rates": { + "30-fps": "30 FPS", + "60-fps": "60 FPS", + "100-fps": "100 FPS", + "120-fps": "120 FPS", + "144-fps": "144 FPS", + "165-fps": "165 FPS", + "240-fps": "240 FPS" + }, + "screen-recording": { + "sources": { + "portal": "Portal", + "screen": "Screen" + }, + "quality": { + "medium": "Medium", + "high": "High", + "very-high": "Very high", + "ultra": "Ultra" + }, + "codecs": { + "h264": "H264", + "hevc": "HEVC", + "av1": "AV1", + "vp8": "VP8", + "vp9": "VP9" + }, + "color-range": { + "limited": "Limited", + "full": "Full" + }, + "audio-sources": { + "system-output": "System output", + "microphone-input": "Microphone input", + "both": "System output + microphone input" + }, + "audio-codecs": { + "opus": "Opus", + "aac": "AAC" + } + } + }, + "plugins": { + "applications": "Applications", + "clipboard": "Clipboard history", + "calculator": "Calculator" + }, "lock-screen": { "secure-terminal": "SECURE TERMINAL", "unlock-command": "sudo unlock-session", diff --git a/Modules/Bar/Bluetooth/BluetoothPanel.qml b/Modules/Bar/Bluetooth/BluetoothPanel.qml index 73706d91..3f4773ab 100644 --- a/Modules/Bar/Bluetooth/BluetoothPanel.qml +++ b/Modules/Bar/Bluetooth/BluetoothPanel.qml @@ -52,7 +52,7 @@ NPanel { NIconButton { enabled: Settings.data.network.bluetoothEnabled icon: BluetoothService.adapter && BluetoothService.adapter.discovering ? "stop" : "refresh" - tooltipText: "Refresh devices" + tooltipText: I18n.tr("tooltips.refresh-devices") baseSize: Style.baseWidgetSize * 0.8 onClicked: { if (BluetoothService.adapter) { @@ -63,7 +63,7 @@ NPanel { NIconButton { icon: "close" - tooltipText: "Close" + tooltipText: I18n.tr("tooltips.close") baseSize: Style.baseWidgetSize * 0.8 onClicked: { root.close() @@ -139,7 +139,7 @@ NPanel { // Known devices BluetoothDevicesList { label: I18n.tr("bluetooth.panel.known-devices") - tooltipText: "Left click to connect. Right click to forget." + tooltipText: I18n.tr("tooltips.connect-disconnect-devices") property var items: { if (!BluetoothService.adapter || !Bluetooth.devices) return [] diff --git a/Modules/Bar/Calendar/CalendarPanel.qml b/Modules/Bar/Calendar/CalendarPanel.qml index 4789f767..6fc5f136 100644 --- a/Modules/Bar/Calendar/CalendarPanel.qml +++ b/Modules/Bar/Calendar/CalendarPanel.qml @@ -31,7 +31,7 @@ NPanel { NIconButton { icon: "chevron-left" - tooltipText: "Previous month" + tooltipText: I18n.tr("tooltips.previous-month") onClicked: { let newDate = new Date(grid.year, grid.month - 1, 1) grid.year = newDate.getFullYear() @@ -50,7 +50,7 @@ NPanel { NIconButton { icon: "chevron-right" - tooltipText: "Next month" + tooltipText: I18n.tr("tooltips.next-month") onClicked: { let newDate = new Date(grid.year, grid.month + 1, 1) grid.year = newDate.getFullYear() diff --git a/Modules/Bar/WiFi/WiFiPanel.qml b/Modules/Bar/WiFi/WiFiPanel.qml index a0ca5053..0590c795 100644 --- a/Modules/Bar/WiFi/WiFiPanel.qml +++ b/Modules/Bar/WiFi/WiFiPanel.qml @@ -56,7 +56,7 @@ NPanel { NIconButton { icon: "refresh" - tooltipText: "Refresh" + tooltipText: I18n.tr("tooltips.refresh") baseSize: Style.baseWidgetSize * 0.8 enabled: Settings.data.network.wifiEnabled && !NetworkService.scanning onClicked: NetworkService.scan() @@ -64,7 +64,7 @@ NPanel { NIconButton { icon: "close" - tooltipText: "Close" + tooltipText: I18n.tr("tooltips.close") baseSize: Style.baseWidgetSize * 0.8 onClicked: root.close() } @@ -367,7 +367,7 @@ NPanel { NIconButton { visible: (modelData.existing || modelData.cached) && !modelData.connected && NetworkService.connectingTo !== modelData.ssid && NetworkService.forgettingNetwork !== modelData.ssid && NetworkService.disconnectingFrom !== modelData.ssid icon: "trash" - tooltipText: "Forget network" + tooltipText: I18n.tr("tooltips.forget-network") baseSize: Style.baseWidgetSize * 0.8 onClicked: expandedSsid = expandedSsid === modelData.ssid ? "" : modelData.ssid } diff --git a/Modules/Bar/Widgets/Bluetooth.qml b/Modules/Bar/Widgets/Bluetooth.qml index a5a0d1c7..04f2757d 100644 --- a/Modules/Bar/Widgets/Bluetooth.qml +++ b/Modules/Bar/Widgets/Bluetooth.qml @@ -21,7 +21,7 @@ NIconButton { colorBorderHover: Color.transparent icon: Settings.data.network.bluetoothEnabled ? "bluetooth" : "bluetooth-off" - tooltipText: "Bluetooth devices" + tooltipText: I18n.tr("tooltips.bluetooth-devices") onClicked: PanelService.getPanel("bluetoothPanel")?.toggle(this) onRightClicked: PanelService.getPanel("bluetoothPanel")?.toggle(this) } diff --git a/Modules/Bar/Widgets/ControlCenter.qml b/Modules/Bar/Widgets/ControlCenter.qml index c1d348f7..51492b98 100644 --- a/Modules/Bar/Widgets/ControlCenter.qml +++ b/Modules/Bar/Widgets/ControlCenter.qml @@ -35,7 +35,7 @@ NIconButton { // If we have a custom path or distro logo, don't use the theme icon. icon: (customIconPath === "" && !useDistroLogo) ? customIcon : "" - tooltipText: "Open side panel" + tooltipText: I18n.tr("tooltips.open-side-panel") baseSize: Style.capsuleHeight compact: (Settings.data.bar.density === "compact") colorBg: (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent) diff --git a/Modules/Bar/Widgets/DarkMode.qml b/Modules/Bar/Widgets/DarkMode.qml index f9c4e4aa..1043b225 100644 --- a/Modules/Bar/Widgets/DarkMode.qml +++ b/Modules/Bar/Widgets/DarkMode.qml @@ -10,7 +10,7 @@ NIconButton { property real scaling: 1.0 icon: "dark-mode" - tooltipText: `Switch to ${Settings.data.colorSchemes.darkMode ? "light" : "dark"} mode` + tooltipText: Settings.data.colorSchemes.darkMode ? I18n.tr("tooltips.switch-to-light-mode") : I18n.tr("tooltips.switch-to-dark-mode") compact: (Settings.data.bar.density === "compact") baseSize: Style.capsuleHeight colorBg: Settings.data.colorSchemes.darkMode ? (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent) : Color.mPrimary diff --git a/Modules/Bar/Widgets/KeepAwake.qml b/Modules/Bar/Widgets/KeepAwake.qml index a6d2b0f7..91ca6af2 100644 --- a/Modules/Bar/Widgets/KeepAwake.qml +++ b/Modules/Bar/Widgets/KeepAwake.qml @@ -14,7 +14,7 @@ NIconButton { baseSize: Style.capsuleHeight compact: (Settings.data.bar.density === "compact") icon: IdleInhibitorService.isInhibited ? "keep-awake-on" : "keep-awake-off" - tooltipText: IdleInhibitorService.isInhibited ? "Disable keep awake" : "Enable keep awake" + tooltipText: IdleInhibitorService.isInhibited ? I18n.tr("tooltips.disable-keep-awake") : I18n.tr("tooltips.enable-keep-awake") colorBg: IdleInhibitorService.isInhibited ? Color.mPrimary : (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent) colorFg: IdleInhibitorService.isInhibited ? Color.mOnPrimary : Color.mOnSurface colorBorder: Color.transparent diff --git a/Modules/Bar/Widgets/Microphone.qml b/Modules/Bar/Widgets/Microphone.qml index 41e5dbff..71b756d6 100644 --- a/Modules/Bar/Widgets/Microphone.qml +++ b/Modules/Bar/Widgets/Microphone.qml @@ -97,7 +97,7 @@ Item { suffix: "%" forceOpen: displayMode === "alwaysShow" forceClose: displayMode === "alwaysHide" - tooltipText: "Microphone volume at " + Math.round(AudioService.inputVolume * 100) + "%\nLeft click to toggle mute. Right click for settings.\nScroll to modify volume." + tooltipText: I18n.tr("tooltips.microphone-volume-at", {"volume": Math.round(AudioService.inputVolume * 100)}) onWheel: function (delta) { wheelAccumulator += delta diff --git a/Modules/Bar/Widgets/NightLight.qml b/Modules/Bar/Widgets/NightLight.qml index b1801dd5..3be8cf53 100644 --- a/Modules/Bar/Widgets/NightLight.qml +++ b/Modules/Bar/Widgets/NightLight.qml @@ -22,7 +22,7 @@ NIconButton { colorBorderHover: Color.transparent icon: Settings.data.nightLight.enabled ? (Settings.data.nightLight.forced ? "nightlight-forced" : "nightlight-on") : "nightlight-off" - tooltipText: `Night light is ${Settings.data.nightLight.enabled ? (Settings.data.nightLight.forced ? "forced." : "enabled.") : "disabled."}\nLeft click to cycle mode.\nRight click to access settings.` + tooltipText: Settings.data.nightLight.enabled ? (Settings.data.nightLight.forced ? I18n.tr("tooltips.night-light-forced") : I18n.tr("tooltips.night-light-enabled")) : I18n.tr("tooltips.night-light-disabled") onClicked: { if (!Settings.data.nightLight.enabled) { Settings.data.nightLight.enabled = true diff --git a/Modules/Bar/Widgets/NotificationHistory.qml b/Modules/Bar/Widgets/NotificationHistory.qml index 6b2d69f2..d33f3116 100644 --- a/Modules/Bar/Widgets/NotificationHistory.qml +++ b/Modules/Bar/Widgets/NotificationHistory.qml @@ -52,7 +52,7 @@ NIconButton { baseSize: Style.capsuleHeight compact: (Settings.data.bar.density === "compact") icon: Settings.data.notifications.doNotDisturb ? "bell-off" : "bell" - tooltipText: `Open notification history\nRight-click to ${Settings.data.notifications.doNotDisturb ? "disable" : "enable"} "Do not disturb".` + tooltipText: Settings.data.notifications.doNotDisturb ? I18n.tr("tooltips.open-notification-history-disable-dnd") : I18n.tr("tooltips.open-notification-history-enable-dnd") colorBg: (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent) colorFg: Color.mOnSurface colorBorder: Color.transparent diff --git a/Modules/Bar/Widgets/ScreenRecorder.qml b/Modules/Bar/Widgets/ScreenRecorder.qml index e0b09256..28b5e7c2 100644 --- a/Modules/Bar/Widgets/ScreenRecorder.qml +++ b/Modules/Bar/Widgets/ScreenRecorder.qml @@ -11,7 +11,7 @@ NIconButton { property real scaling: 1.0 icon: "camera-video" - tooltipText: ScreenRecorderService.isRecording ? "Click to stop recording" : "Click to start recording" + tooltipText: ScreenRecorderService.isRecording ? I18n.tr("tooltips.click-to-stop-recording") : I18n.tr("tooltips.click-to-start-recording") compact: (Settings.data.bar.density === "compact") baseSize: Style.capsuleHeight colorBg: ScreenRecorderService.isRecording ? Color.mPrimary : (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent) diff --git a/Modules/Bar/Widgets/SessionMenu.qml b/Modules/Bar/Widgets/SessionMenu.qml index 38ee93dd..8aea7785 100644 --- a/Modules/Bar/Widgets/SessionMenu.qml +++ b/Modules/Bar/Widgets/SessionMenu.qml @@ -14,7 +14,7 @@ NIconButton { compact: (Settings.data.bar.density === "compact") baseSize: Style.capsuleHeight icon: "power" - tooltipText: "Session menu" + tooltipText: I18n.tr("tooltips.session-menu") colorBg: (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent) colorFg: Color.mError colorBorder: Color.transparent diff --git a/Modules/Bar/Widgets/Volume.qml b/Modules/Bar/Widgets/Volume.qml index 03ac13c9..0d65b4b2 100644 --- a/Modules/Bar/Widgets/Volume.qml +++ b/Modules/Bar/Widgets/Volume.qml @@ -83,7 +83,7 @@ Item { suffix: "%" forceOpen: displayMode === "alwaysShow" forceClose: displayMode === "alwaysHide" - tooltipText: "Volume at " + Math.round(AudioService.volume * 100) + "%\nLeft click to toggle mute. Right click for settings.\nScroll to modify volume." + tooltipText: I18n.tr("tooltips.volume-at", {"volume": Math.round(AudioService.volume * 100)}) onWheel: function (delta) { wheelAccumulator += delta diff --git a/Modules/Bar/Widgets/WallpaperSelector.qml b/Modules/Bar/Widgets/WallpaperSelector.qml index 05163d2f..341df6df 100644 --- a/Modules/Bar/Widgets/WallpaperSelector.qml +++ b/Modules/Bar/Widgets/WallpaperSelector.qml @@ -14,7 +14,7 @@ NIconButton { baseSize: Style.capsuleHeight compact: (Settings.data.bar.density === "compact") icon: "wallpaper-selector" - tooltipText: "Open wallpaper selector" + tooltipText: I18n.tr("tooltips.open-wallpaper-selector") colorBg: (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent) colorFg: Color.mOnSurface colorBorder: Color.transparent diff --git a/Modules/Bar/Widgets/WiFi.qml b/Modules/Bar/Widgets/WiFi.qml index 0991e33b..0e8d3f9b 100644 --- a/Modules/Bar/Widgets/WiFi.qml +++ b/Modules/Bar/Widgets/WiFi.qml @@ -40,7 +40,7 @@ NIconButton { return "signal_wifi_bad" } } - tooltipText: "Manage Wi-Fi" + tooltipText: I18n.tr("tooltips.manage-wifi") onClicked: PanelService.getPanel("wifiPanel")?.toggle(this) onRightClicked: PanelService.getPanel("wifiPanel")?.toggle(this) } diff --git a/Modules/ControlCenter/Cards/MediaCard.qml b/Modules/ControlCenter/Cards/MediaCard.qml index 5e4ad4f8..bed4ce83 100644 --- a/Modules/ControlCenter/Cards/MediaCard.qml +++ b/Modules/ControlCenter/Cards/MediaCard.qml @@ -280,7 +280,7 @@ NBox { // Previous button NIconButton { icon: "media-prev" - tooltipText: "Previous media" + tooltipText: I18n.tr("tooltips.previous-media") visible: MediaService.canGoPrevious onClicked: MediaService.canGoPrevious ? MediaService.previous() : {} } @@ -288,7 +288,7 @@ NBox { // Play/Pause button NIconButton { icon: MediaService.isPlaying ? "media-pause" : "media-play" - tooltipText: MediaService.isPlaying ? "Pause" : "Play" + tooltipText: MediaService.isPlaying ? I18n.tr("tooltips.pause") : I18n.tr("tooltips.play") visible: (MediaService.canPlay || MediaService.canPause) onClicked: (MediaService.canPlay || MediaService.canPause) ? MediaService.playPause() : {} } @@ -296,7 +296,7 @@ NBox { // Next button NIconButton { icon: "media-next" - tooltipText: "Next media" + tooltipText: I18n.tr("tooltips.next-media") visible: MediaService.canGoNext onClicked: MediaService.canGoNext ? MediaService.next() : {} } diff --git a/Modules/ControlCenter/Cards/PowerProfilesCard.qml b/Modules/ControlCenter/Cards/PowerProfilesCard.qml index 5ab7f7df..09cfe286 100644 --- a/Modules/ControlCenter/Cards/PowerProfilesCard.qml +++ b/Modules/ControlCenter/Cards/PowerProfilesCard.qml @@ -26,7 +26,7 @@ NBox { // Performance NIconButton { icon: PowerProfileService.getIcon(PowerProfile.Performance) - tooltipText: `Set "${PowerProfileService.getName(PowerProfile.Performance)}" power profile` + tooltipText: I18n.tr("tooltips.set-power-profile", {"profile": PowerProfileService.getName(PowerProfile.Performance)}) enabled: hasPP opacity: enabled ? Style.opacityFull : Style.opacityMedium colorBg: (enabled && PowerProfileService.profile === PowerProfile.Performance) ? Color.mPrimary : Color.mSurfaceVariant @@ -36,7 +36,7 @@ NBox { // Balanced NIconButton { icon: PowerProfileService.getIcon(PowerProfile.Balanced) - tooltipText: `Set "${PowerProfileService.getName(PowerProfile.Balanced)}" power profile` + tooltipText: I18n.tr("tooltips.set-power-profile", {"profile": PowerProfileService.getName(PowerProfile.Balanced)}) enabled: hasPP opacity: enabled ? Style.opacityFull : Style.opacityMedium colorBg: (enabled && PowerProfileService.profile === PowerProfile.Balanced) ? Color.mPrimary : Color.mSurfaceVariant @@ -46,7 +46,7 @@ NBox { // Eco NIconButton { icon: PowerProfileService.getIcon(PowerProfile.PowerSaver) - tooltipText: `Set "${PowerProfileService.getName(PowerProfile.PowerSaver)}" power profile` + tooltipText: I18n.tr("tooltips.set-power-profile", {"profile": PowerProfileService.getName(PowerProfile.PowerSaver)}) enabled: hasPP opacity: enabled ? Style.opacityFull : Style.opacityMedium colorBg: (enabled && PowerProfileService.profile === PowerProfile.PowerSaver) ? Color.mPrimary : Color.mSurfaceVariant diff --git a/Modules/ControlCenter/Cards/ProfileCard.qml b/Modules/ControlCenter/Cards/ProfileCard.qml index d7aa4a4e..1d3e35d0 100644 --- a/Modules/ControlCenter/Cards/ProfileCard.qml +++ b/Modules/ControlCenter/Cards/ProfileCard.qml @@ -56,7 +56,7 @@ NBox { } NIconButton { icon: "settings" - tooltipText: "Open settings" + tooltipText: I18n.tr("tooltips.open-settings") onClicked: { settingsPanel.requestedTab = SettingsPanel.Tab.General settingsPanel.open() @@ -66,7 +66,7 @@ NBox { NIconButton { id: powerButton icon: "power" - tooltipText: "Session Menu" + tooltipText: I18n.tr("tooltips.session-menu") onClicked: { sessionMenuPanel.open() controlCenterPanel.close() @@ -76,7 +76,7 @@ NBox { NIconButton { id: closeButton icon: "close" - tooltipText: "Close side panel" + tooltipText: I18n.tr("tooltips.close-side-panel") onClicked: { controlCenterPanel.close() } diff --git a/Modules/ControlCenter/Cards/UtilitiesCard.qml b/Modules/ControlCenter/Cards/UtilitiesCard.qml index 9bfae591..decd9659 100644 --- a/Modules/ControlCenter/Cards/UtilitiesCard.qml +++ b/Modules/ControlCenter/Cards/UtilitiesCard.qml @@ -24,7 +24,7 @@ NBox { NIconButton { icon: "camera-video" enabled: ScreenRecorderService.isAvailable - tooltipText: ScreenRecorderService.isAvailable ? (ScreenRecorderService.isRecording ? "Stop screen recording" : "Start screen recording") : "Screen recorder is not installed" + tooltipText: ScreenRecorderService.isAvailable ? (ScreenRecorderService.isRecording ? I18n.tr("tooltips.stop-screen-recording") : I18n.tr("tooltips.start-screen-recording")) : I18n.tr("tooltips.screen-recorder-not-installed") colorBg: ScreenRecorderService.isRecording ? Color.mPrimary : Color.mSurfaceVariant colorFg: ScreenRecorderService.isRecording ? Color.mOnPrimary : Color.mPrimary onClicked: { @@ -42,7 +42,7 @@ NBox { // Idle Inhibitor NIconButton { icon: IdleInhibitorService.isInhibited ? "keep-awake-on" : "keep-awake-off" - tooltipText: `${IdleInhibitorService.isInhibited ? "Disable" : "Enable"} keep awake` + tooltipText: IdleInhibitorService.isInhibited ? I18n.tr("tooltips.disable-keep-awake") : I18n.tr("tooltips.enable-keep-awake") colorBg: IdleInhibitorService.isInhibited ? Color.mPrimary : Color.mSurfaceVariant colorFg: IdleInhibitorService.isInhibited ? Color.mOnPrimary : Color.mPrimary onClicked: { @@ -54,7 +54,7 @@ NBox { NIconButton { visible: Settings.data.wallpaper.enabled icon: "wallpaper-selector" - tooltipText: "Left click: Open wallpaper selector.\nRight click: Set random wallpaper." + tooltipText: I18n.tr("tooltips.wallpaper-selector") onClicked: PanelService.getPanel("wallpaperPanel")?.toggle(this) onRightClicked: WallpaperService.setRandomWallpaper() } diff --git a/Modules/Launcher/Launcher.qml b/Modules/Launcher/Launcher.qml index ba1855e3..0714530f 100644 --- a/Modules/Launcher/Launcher.qml +++ b/Modules/Launcher/Launcher.qml @@ -245,7 +245,7 @@ NPanel { fontWeight: Style.fontWeightSemiBold text: searchText - placeholderText: "Search entries... or use > for commands" + placeholderText: I18n.tr("placeholders.search-launcher") onTextChanged: searchText = text diff --git a/Modules/Launcher/Plugins/ApplicationsPlugin.qml b/Modules/Launcher/Plugins/ApplicationsPlugin.qml index 0754bd66..46d83094 100644 --- a/Modules/Launcher/Plugins/ApplicationsPlugin.qml +++ b/Modules/Launcher/Plugins/ApplicationsPlugin.qml @@ -7,7 +7,7 @@ import "../../../Helpers/FuzzySort.js" as Fuzzysort Item { property var launcher: null - property string name: "Applications" + property string name: I18n.tr("plugins.applications") property bool handleSearch: true property var entries: [] diff --git a/Modules/Launcher/Plugins/CalculatorPlugin.qml b/Modules/Launcher/Plugins/CalculatorPlugin.qml index 20298703..3f0b1a03 100644 --- a/Modules/Launcher/Plugins/CalculatorPlugin.qml +++ b/Modules/Launcher/Plugins/CalculatorPlugin.qml @@ -4,7 +4,7 @@ import "../../../Helpers/AdvancedMath.js" as AdvancedMath Item { property var launcher: null - property string name: "Calculator" + property string name: I18n.tr("plugins.calculator") function handleCommand(query) { // Handle >calc command or direct math expressions after > diff --git a/Modules/Launcher/Plugins/ClipboardPlugin.qml b/Modules/Launcher/Plugins/ClipboardPlugin.qml index 9de69903..271f7823 100644 --- a/Modules/Launcher/Plugins/ClipboardPlugin.qml +++ b/Modules/Launcher/Plugins/ClipboardPlugin.qml @@ -7,7 +7,7 @@ Item { id: root // Plugin metadata - property string name: "Clipboard history" + property string name: I18n.tr("plugins.clipboard") property var launcher: null // Plugin capabilities diff --git a/Modules/Notification/Notification.qml b/Modules/Notification/Notification.qml index 48bfe37a..12405c96 100644 --- a/Modules/Notification/Notification.qml +++ b/Modules/Notification/Notification.qml @@ -374,7 +374,7 @@ Variants { // Close button positioned absolutely NIconButton { icon: "close" - tooltipText: "Close" + tooltipText: I18n.tr("tooltips.close") baseSize: Style.baseWidgetSize * 0.6 anchors.top: parent.top anchors.topMargin: Style.marginM * scaling diff --git a/Modules/Notification/NotificationHistoryPanel.qml b/Modules/Notification/NotificationHistoryPanel.qml index 220b26f4..cdc1bcfa 100644 --- a/Modules/Notification/NotificationHistoryPanel.qml +++ b/Modules/Notification/NotificationHistoryPanel.qml @@ -46,14 +46,14 @@ NPanel { NIconButton { icon: Settings.data.notifications.doNotDisturb ? "bell-off" : "bell" - tooltipText: `'Do not disturb' ${Settings.data.notifications.doNotDisturb ? "enabled" : "disabled"}` + tooltipText: Settings.data.notifications.doNotDisturb ? I18n.tr("tooltips.do-not-disturb-enabled") : I18n.tr("tooltips.do-not-disturb-disabled") baseSize: Style.baseWidgetSize * 0.8 onClicked: Settings.data.notifications.doNotDisturb = !Settings.data.notifications.doNotDisturb } NIconButton { icon: "trash" - tooltipText: "Clear history" + tooltipText: I18n.tr("tooltips.clear-history") baseSize: Style.baseWidgetSize * 0.8 onClicked: { NotificationService.clearHistory() @@ -64,7 +64,7 @@ NPanel { NIconButton { icon: "close" - tooltipText: "Close" + tooltipText: I18n.tr("tooltips.close") baseSize: Style.baseWidgetSize * 0.8 onClicked: root.close() } @@ -244,7 +244,7 @@ NPanel { // Delete button NIconButton { icon: "trash" - tooltipText: "Delete notification" + tooltipText: I18n.tr("tooltips.delete-notification") baseSize: Style.baseWidgetSize * 0.7 Layout.alignment: Qt.AlignTop diff --git a/Modules/SessionMenu/SessionMenu.qml b/Modules/SessionMenu/SessionMenu.qml index c3de9a59..b3a1b1a2 100644 --- a/Modules/SessionMenu/SessionMenu.qml +++ b/Modules/SessionMenu/SessionMenu.qml @@ -277,7 +277,7 @@ NPanel { NIconButton { icon: timerActive ? "stop" : "close" - tooltipText: timerActive ? "Cancel timer" : "Close" + tooltipText: timerActive ? I18n.tr("tooltips.cancel-timer") : I18n.tr("tooltips.close") Layout.alignment: Qt.AlignVCenter colorBg: timerActive ? Qt.alpha(Color.mError, 0.08) : Color.transparent colorFg: timerActive ? Color.mError : Color.mOnSurface diff --git a/Modules/Settings/Bar/BarSectionEditor.qml b/Modules/Settings/Bar/BarSectionEditor.qml index 1e6d1d46..86b5e72f 100644 --- a/Modules/Settings/Bar/BarSectionEditor.qml +++ b/Modules/Settings/Bar/BarSectionEditor.qml @@ -99,7 +99,7 @@ NBox { colorBgHover: Color.mSecondary colorFgHover: Color.mOnSecondary enabled: comboBox.currentKey !== "" - tooltipText: "Add widget" + tooltipText: I18n.tr("tooltips.add-widget") Layout.alignment: Qt.AlignVCenter Layout.leftMargin: Style.marginS * scaling onClicked: { @@ -227,7 +227,7 @@ NBox { active: BarWidgetRegistry.widgetHasUserSettings(modelData.id) sourceComponent: NIconButton { icon: "settings" - tooltipText: "Widget settings" + tooltipText: I18n.tr("tooltips.widget-settings") baseSize: miniButtonSize colorBorder: Qt.alpha(Color.mOutline, Style.opacityLight) colorBg: Color.mOnSurface @@ -268,7 +268,7 @@ NBox { NIconButton { icon: "close" - tooltipText: "Remove widget" + tooltipText: I18n.tr("tooltips.remove-widget") baseSize: miniButtonSize colorBorder: Qt.alpha(Color.mOutline, Style.opacityLight) colorBg: Color.mOnSurface diff --git a/Modules/Settings/Bar/WidgetSettings/BatterySettings.qml b/Modules/Settings/Bar/WidgetSettings/BatterySettings.qml index 977e49e5..acb14169 100644 --- a/Modules/Settings/Bar/WidgetSettings/BatterySettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/BatterySettings.qml @@ -28,20 +28,20 @@ ColumnLayout { label: I18n.tr("bar.widget-settings.battery.display-mode.label") description: I18n.tr("bar.widget-settings.battery.display-mode.description") minimumWidth: 134 * scaling - model: ListModel { - ListElement { - key: "onhover" - name: "On hover" + model: [ + { + key: "onhover", + name: I18n.tr("options.display-mode.on-hover") + }, + { + key: "alwaysShow", + name: I18n.tr("options.display-mode.always-show") + }, + { + key: "alwaysHide", + name: I18n.tr("options.display-mode.always-hide") } - ListElement { - key: "alwaysShow" - name: "Always show" - } - ListElement { - key: "alwaysHide" - name: "Always hide" - } - } + ] currentKey: root.valueDisplayMode onSelected: key => root.valueDisplayMode = key } diff --git a/Modules/Settings/Bar/WidgetSettings/BrightnessSettings.qml b/Modules/Settings/Bar/WidgetSettings/BrightnessSettings.qml index c54ca3ac..9d5070e3 100644 --- a/Modules/Settings/Bar/WidgetSettings/BrightnessSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/BrightnessSettings.qml @@ -26,20 +26,20 @@ ColumnLayout { label: I18n.tr("bar.widget-settings.brightness.display-mode.label") description: I18n.tr("bar.widget-settings.brightness.display-mode.description") minimumWidth: 134 * scaling - model: ListModel { - ListElement { - key: "onhover" - name: "On hover" + model: [ + { + key: "onhover", + name: I18n.tr("options.display-mode.on-hover") + }, + { + key: "alwaysShow", + name: I18n.tr("options.display-mode.always-show") + }, + { + key: "alwaysHide", + name: I18n.tr("options.display-mode.always-hide") } - ListElement { - key: "alwaysShow" - name: "Always show" - } - ListElement { - key: "alwaysHide" - name: "Always hide" - } - } + ] currentKey: valueDisplayMode onSelected: key => valueDisplayMode = key } diff --git a/Modules/Settings/Bar/WidgetSettings/ClockSettings.qml b/Modules/Settings/Bar/WidgetSettings/ClockSettings.qml index ca6c300d..099c5ff1 100644 --- a/Modules/Settings/Bar/WidgetSettings/ClockSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/ClockSettings.qml @@ -106,7 +106,7 @@ ColumnLayout { Layout.fillWidth: true label: I18n.tr("bar.widget-settings.clock.horizontal-bar.label") description: I18n.tr("bar.widget-settings.clock.horizontal-bar.description") - placeholderText: "HH:mm ddd, MMM dd" + placeholderText: I18n.tr("placeholders.clock-horizontal") text: valueFormatHorizontal onTextChanged: valueFormatHorizontal = text Component.onCompleted: { @@ -129,7 +129,7 @@ ColumnLayout { Layout.fillWidth: true label: I18n.tr("bar.widget-settings.clock.vertical-bar.label") description: I18n.tr("bar.widget-settings.clock.vertical-bar.description") - placeholderText: "HH mm dd MM" + placeholderText: I18n.tr("placeholders.clock-vertical") text: valueFormatVertical onTextChanged: valueFormatVertical = text Component.onCompleted: { diff --git a/Modules/Settings/Bar/WidgetSettings/CustomButtonSettings.qml b/Modules/Settings/Bar/WidgetSettings/CustomButtonSettings.qml index 34964e44..0733091a 100644 --- a/Modules/Settings/Bar/WidgetSettings/CustomButtonSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/CustomButtonSettings.qml @@ -59,7 +59,7 @@ ColumnLayout { id: leftClickExecInput Layout.fillWidth: true label: I18n.tr("bar.widget-settings.custom-button.left-click") - placeholderText: "Enter command to execute (app or custom script)" + placeholderText: I18n.tr("placeholders.enter-command") text: widgetData?.leftClickExec || widgetMetadata.leftClickExec } @@ -67,7 +67,7 @@ ColumnLayout { id: rightClickExecInput Layout.fillWidth: true label: I18n.tr("bar.widget-settings.custom-button.right-click") - placeholderText: "Enter command to execute (app or custom script)" + placeholderText: I18n.tr("placeholders.enter-command") text: widgetData?.rightClickExec || widgetMetadata.rightClickExec } @@ -75,7 +75,7 @@ ColumnLayout { id: middleClickExecInput Layout.fillWidth: true label: I18n.tr("bar.widget-settings.custom-button.middle-click") - placeholderText: "Enter command to execute (app or custom script)" + placeholderText: I18n.tr("placeholders.enter-command") text: widgetData.middleClickExec || widgetMetadata.middleClickExec } @@ -92,7 +92,7 @@ ColumnLayout { Layout.fillWidth: true label: I18n.tr("bar.widget-settings.custom-button.display-command-output.label") description: I18n.tr("bar.widget-settings.custom-button.display-command-output.description") - placeholderText: "echo \"Hello World\"" + placeholderText: I18n.tr("placeholders.command-example") text: widgetData?.textCommand || widgetMetadata.textCommand } diff --git a/Modules/Settings/Bar/WidgetSettings/KeyboardLayoutSettings.qml b/Modules/Settings/Bar/WidgetSettings/KeyboardLayoutSettings.qml index 36ad8042..9350e9b7 100644 --- a/Modules/Settings/Bar/WidgetSettings/KeyboardLayoutSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/KeyboardLayoutSettings.qml @@ -26,20 +26,20 @@ ColumnLayout { label: I18n.tr("bar.widget-settings.keyboard-layout.display-mode.label") description: I18n.tr("bar.widget-settings.keyboard-layout.display-mode.description") minimumWidth: 134 * scaling - model: ListModel { - ListElement { - key: "onhover" - name: "On hover" + model: [ + { + key: "onhover", + name: I18n.tr("options.display-mode.on-hover") + }, + { + key: "forceOpen", + name: I18n.tr("options.display-mode.force-open") + }, + { + key: "alwaysHide", + name: I18n.tr("options.display-mode.always-hide") } - ListElement { - key: "forceOpen" - name: "Force Open" - } - ListElement { - key: "alwaysHide" - name: "Always hide" - } - } + ] currentKey: valueDisplayMode onSelected: key => valueDisplayMode = key } diff --git a/Modules/Settings/Bar/WidgetSettings/MediaMiniSettings.qml b/Modules/Settings/Bar/WidgetSettings/MediaMiniSettings.qml index a82187c1..daeaf5a6 100644 --- a/Modules/Settings/Bar/WidgetSettings/MediaMiniSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/MediaMiniSettings.qml @@ -41,20 +41,20 @@ ColumnLayout { NComboBox { visible: valueShowVisualizer label: I18n.tr("bar.widget-settings.media-mini.visualizer-type") - model: ListModel { - ListElement { - key: "linear" - name: "Linear" + model: [ + { + key: "linear", + name: I18n.tr("options.visualizer-types.linear") + }, + { + key: "mirrored", + name: I18n.tr("options.visualizer-types.mirrored") + }, + { + key: "wave", + name: I18n.tr("options.visualizer-types.wave") } - ListElement { - key: "mirrored" - name: "Mirrored" - } - ListElement { - key: "wave" - name: "Wave" - } - } + ] currentKey: valueVisualizerType onSelected: key => valueVisualizerType = key minimumWidth: 200 * scaling diff --git a/Modules/Settings/Bar/WidgetSettings/MicrophoneSettings.qml b/Modules/Settings/Bar/WidgetSettings/MicrophoneSettings.qml index d832b0d6..d7071022 100644 --- a/Modules/Settings/Bar/WidgetSettings/MicrophoneSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/MicrophoneSettings.qml @@ -26,20 +26,20 @@ ColumnLayout { label: I18n.tr("bar.widget-settings.microphone.display-mode.label") description: I18n.tr("bar.widget-settings.microphone.display-mode.description") minimumWidth: 134 * scaling - model: ListModel { - ListElement { - key: "onhover" - name: "On hover" + model: [ + { + key: "onhover", + name: I18n.tr("options.display-mode.on-hover") + }, + { + key: "alwaysShow", + name: I18n.tr("options.display-mode.always-show") + }, + { + key: "alwaysHide", + name: I18n.tr("options.display-mode.always-hide") } - ListElement { - key: "alwaysShow" - name: "Always show" - } - ListElement { - key: "alwaysHide" - name: "Always hide" - } - } + ] currentKey: valueDisplayMode onSelected: key => valueDisplayMode = key } diff --git a/Modules/Settings/Bar/WidgetSettings/SpacerSettings.qml b/Modules/Settings/Bar/WidgetSettings/SpacerSettings.qml index 1ecd2740..7c6b8b17 100644 --- a/Modules/Settings/Bar/WidgetSettings/SpacerSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/SpacerSettings.qml @@ -25,6 +25,6 @@ ColumnLayout { label: I18n.tr("bar.widget-settings.spacer.width.label") description: I18n.tr("bar.widget-settings.spacer.width.description") text: widgetData.width || widgetMetadata.width - placeholderText: "Enter width in pixels" + placeholderText: I18n.tr("placeholders.enter-width-pixels") } } diff --git a/Modules/Settings/Bar/WidgetSettings/VolumeSettings.qml b/Modules/Settings/Bar/WidgetSettings/VolumeSettings.qml index 00d63083..987bedbb 100644 --- a/Modules/Settings/Bar/WidgetSettings/VolumeSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/VolumeSettings.qml @@ -26,20 +26,20 @@ ColumnLayout { label: I18n.tr("bar.widget-settings.volume.display-mode.label") description: I18n.tr("bar.widget-settings.volume.display-mode.description") minimumWidth: 134 * scaling - model: ListModel { - ListElement { - key: "onhover" - name: "On hover" + model: [ + { + key: "onhover", + name: I18n.tr("options.display-mode.on-hover") + }, + { + key: "alwaysShow", + name: I18n.tr("options.display-mode.always-show") + }, + { + key: "alwaysHide", + name: I18n.tr("options.display-mode.always-hide") } - ListElement { - key: "alwaysShow" - name: "Always show" - } - ListElement { - key: "alwaysHide" - name: "Always hide" - } - } + ] currentKey: valueDisplayMode onSelected: key => valueDisplayMode = key } diff --git a/Modules/Settings/Bar/WidgetSettings/WorkspaceSettings.qml b/Modules/Settings/Bar/WidgetSettings/WorkspaceSettings.qml index 47854470..3c8ce794 100644 --- a/Modules/Settings/Bar/WidgetSettings/WorkspaceSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/WorkspaceSettings.qml @@ -24,20 +24,20 @@ ColumnLayout { id: labelModeCombo label: I18n.tr("bar.widget-settings.workspace.label-mode") - model: ListModel { - ListElement { - key: "none" - name: "None" + model: [ + { + key: "none", + name: I18n.tr("options.workspace-labels.none") + }, + { + key: "index", + name: I18n.tr("options.workspace-labels.index") + }, + { + key: "name", + name: I18n.tr("options.workspace-labels.name") } - ListElement { - key: "index" - name: "Index" - } - ListElement { - key: "name" - name: "Name" - } - } + ] currentKey: widgetData.labelMode || widgetMetadata.labelMode onSelected: key => labelModeCombo.currentKey = key minimumWidth: 200 * scaling diff --git a/Modules/Settings/SettingsPanel.qml b/Modules/Settings/SettingsPanel.qml index fbef5378..0513033f 100644 --- a/Modules/Settings/SettingsPanel.qml +++ b/Modules/Settings/SettingsPanel.qml @@ -462,7 +462,7 @@ NPanel { // Close button NIconButton { icon: "close" - tooltipText: "Close" + tooltipText: I18n.tr("tooltips.close") Layout.alignment: Qt.AlignVCenter onClicked: root.close() } diff --git a/Modules/Settings/Tabs/AudioTab.qml b/Modules/Settings/Tabs/AudioTab.qml index d8bf87c2..bd02fbd2 100644 --- a/Modules/Settings/Tabs/AudioTab.qml +++ b/Modules/Settings/Tabs/AudioTab.qml @@ -326,24 +326,24 @@ ColumnLayout { id: audioVisualizerCombo label: I18n.tr("settings.audio.media.visualizer-type.label") description: I18n.tr("settings.audio.media.visualizer-type.description") - model: ListModel { - ListElement { - key: "none" - name: "None" + model: [ + { + key: "none", + name: I18n.tr("options.visualizer-types.none") + }, + { + key: "linear", + name: I18n.tr("options.visualizer-types.linear") + }, + { + key: "mirrored", + name: I18n.tr("options.visualizer-types.mirrored") + }, + { + key: "wave", + name: I18n.tr("options.visualizer-types.wave") } - ListElement { - key: "linear" - name: "Linear" - } - ListElement { - key: "mirrored" - name: "Mirrored" - } - ListElement { - key: "wave" - name: "Wave" - } - } + ] currentKey: Settings.data.audio.visualizerType onSelected: key => Settings.data.audio.visualizerType = key } @@ -351,36 +351,36 @@ ColumnLayout { NComboBox { label: I18n.tr("settings.audio.media.frame-rate.label") description: I18n.tr("settings.audio.media.frame-rate.description") - model: ListModel { - ListElement { - key: "30" - name: "30 FPS" + model: [ + { + key: "30", + name: I18n.tr("options.frame-rates.30-fps") + }, + { + key: "60", + name: I18n.tr("options.frame-rates.60-fps") + }, + { + key: "100", + name: I18n.tr("options.frame-rates.100-fps") + }, + { + key: "120", + name: I18n.tr("options.frame-rates.120-fps") + }, + { + key: "144", + name: I18n.tr("options.frame-rates.144-fps") + }, + { + key: "165", + name: I18n.tr("options.frame-rates.165-fps") + }, + { + key: "240", + name: I18n.tr("options.frame-rates.240-fps") } - ListElement { - key: "60" - name: "60 FPS" - } - ListElement { - key: "100" - name: "100 FPS" - } - ListElement { - key: "120" - name: "120 FPS" - } - ListElement { - key: "144" - name: "144 FPS" - } - ListElement { - key: "165" - name: "165 FPS" - } - ListElement { - key: "240" - name: "240 FPS" - } - } + ] currentKey: Settings.data.audio.cavaFrameRate onSelected: key => Settings.data.audio.cavaFrameRate = key } diff --git a/Modules/Settings/Tabs/GeneralTab.qml b/Modules/Settings/Tabs/GeneralTab.qml index 0d748a97..edd0fc67 100644 --- a/Modules/Settings/Tabs/GeneralTab.qml +++ b/Modules/Settings/Tabs/GeneralTab.qml @@ -36,7 +36,7 @@ ColumnLayout { }) description: I18n.tr("settings.general.profile.picture.description") text: Settings.data.general.avatarImage - placeholderText: "/home/user/.face" + placeholderText: I18n.tr("placeholders.profile-picture-path") buttonIcon: "photo" buttonTooltip: "Browse for avatar image" onInputEditingFinished: Settings.data.general.avatarImage = text diff --git a/Modules/Settings/Tabs/ScreenRecorderTab.qml b/Modules/Settings/Tabs/ScreenRecorderTab.qml index ba4bbdac..3d464439 100644 --- a/Modules/Settings/Tabs/ScreenRecorderTab.qml +++ b/Modules/Settings/Tabs/ScreenRecorderTab.qml @@ -61,16 +61,16 @@ ColumnLayout { NComboBox { label: I18n.tr("settings.screen-recorder.video.video-source.label") description: I18n.tr("settings.screen-recorder.video.video-source.description") - model: ListModel { - ListElement { - key: "portal" - name: "Portal" + model: [ + { + key: "portal", + name: I18n.tr("options.screen-recording.sources.portal") + }, + { + key: "screen", + name: I18n.tr("options.screen-recording.sources.screen") } - ListElement { - key: "screen" - name: "Screen" - } - } + ] currentKey: Settings.data.screenRecorder.videoSource onSelected: key => Settings.data.screenRecorder.videoSource = key } diff --git a/Modules/Wallpaper/WallpaperPanel.qml b/Modules/Wallpaper/WallpaperPanel.qml index 2b6b8fb6..95ad2f49 100644 --- a/Modules/Wallpaper/WallpaperPanel.qml +++ b/Modules/Wallpaper/WallpaperPanel.qml @@ -65,14 +65,14 @@ NPanel { NIconButton { icon: "refresh" - tooltipText: "Refresh wallpaper list" + tooltipText: I18n.tr("tooltips.refresh-wallpaper-list") baseSize: Style.baseWidgetSize * 0.8 onClicked: WallpaperService.refreshWallpapersList() } NIconButton { icon: "close" - tooltipText: "Close" + tooltipText: I18n.tr("tooltips.close") baseSize: Style.baseWidgetSize * 0.8 onClicked: root.close() } @@ -183,7 +183,7 @@ NPanel { NTextInput { id: searchInput - placeholderText: "Type to filter wallpapers..." + placeholderText: I18n.tr("placeholders.search-wallpapers") Layout.fillWidth: true onTextChanged: { diff --git a/Widgets/NIconPicker.qml b/Widgets/NIconPicker.qml index 4aecf9cb..86ea50a4 100644 --- a/Widgets/NIconPicker.qml +++ b/Widgets/NIconPicker.qml @@ -86,7 +86,7 @@ Popup { id: searchInput Layout.fillWidth: true label: I18n.tr("widgets.icon-picker.search.label") - placeholderText: "e.g., noctalia, niri, battery, cloud" + placeholderText: I18n.tr("placeholders.search-icons") text: root.query onTextChanged: root.query = text.trim().toLowerCase() } From 2bfed74851b44dfbb8de03694b487f99763247de Mon Sep 17 00:00:00 2001 From: Ly-sec Date: Wed, 24 Sep 2025 14:24:21 +0200 Subject: [PATCH 05/15] i18n: even more integration autoformat --- Assets/Translations/en.json | 27 +++++- Bin/check-i18n.sh | 65 +++++++++++++++ Bin/i18n-check.sh | 79 +++++------------- Modules/Bar/WiFi/WiFiPanel.qml | 4 +- Modules/Bar/Widgets/KeyboardLayout.qml | 4 +- Modules/Bar/Widgets/Microphone.qml | 4 +- Modules/Bar/Widgets/PowerProfile.qml | 4 +- Modules/Bar/Widgets/SystemMonitor.qml | 8 +- Modules/Bar/Widgets/Volume.qml | 4 +- Modules/ControlCenter/Cards/MediaCard.qml | 2 +- .../ControlCenter/Cards/PowerProfilesCard.qml | 12 ++- Modules/ControlCenter/Cards/ProfileCard.qml | 4 +- Modules/LockScreen/LockScreen.qml | 4 +- Modules/Notification/Notification.qml | 2 +- .../Settings/Bar/BarWidgetSettingsDialog.qml | 4 +- .../Bar/WidgetSettings/BatterySettings.qml | 24 +++--- .../Bar/WidgetSettings/BrightnessSettings.qml | 24 +++--- .../WidgetSettings/KeyboardLayoutSettings.qml | 24 +++--- .../Bar/WidgetSettings/MediaMiniSettings.qml | 24 +++--- .../Bar/WidgetSettings/MicrophoneSettings.qml | 24 +++--- .../Bar/WidgetSettings/VolumeSettings.qml | 24 +++--- .../Bar/WidgetSettings/WorkspaceSettings.qml | 24 +++--- Modules/Settings/Tabs/AudioTab.qml | 83 ++++++++----------- Modules/Settings/Tabs/BarTab.qml | 6 +- Modules/Settings/Tabs/DisplayTab.qml | 10 ++- Modules/Settings/Tabs/DockTab.qml | 6 +- Modules/Settings/Tabs/LocationTab.qml | 5 +- Modules/Settings/Tabs/NotificationsTab.qml | 6 +- Modules/Settings/Tabs/ScreenRecorderTab.qml | 17 ++-- Services/GitHubService.qml | 6 +- Services/IdleInhibitorService.qml | 2 +- Services/KeyboardLayoutService.qml | 2 +- Widgets/NFilePicker.qml | 4 +- Widgets/NInputAction.qml | 2 +- Widgets/NSearchableComboBox.qml | 2 +- 35 files changed, 301 insertions(+), 245 deletions(-) create mode 100644 Bin/check-i18n.sh diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index 004d5278..896e72d4 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -970,7 +970,9 @@ "previous-media": "Previous media", "pause": "Pause", "play": "Play", - "next-media": "Next media" + "next-media": "Next media", + "power-profile": "'{profile}' power profile", + "keyboard-layout": "{layout} keyboard layout" }, "clock": { "tooltip": "Open calendar" @@ -992,7 +994,11 @@ "clock-horizontal": "HH:mm ddd, MMM dd", "clock-vertical": "HH mm dd MM", "search-wallpapers": "Type to filter wallpapers...", - "search-launcher": "Search entries... or use > for commands" + "search-launcher": "Search entries... or use > for commands", + "search": "Search...", + "select": "Select", + "cancel": "Cancel", + "test": "Test" }, "options": { "display-mode": { @@ -1059,6 +1065,23 @@ "clipboard": "Clipboard history", "calculator": "Calculator" }, + "system": { + "uptime": "System uptime: {uptime}", + "welcome-back": "Welcome back, {user}!", + "monitor-description": "{model} ({width}x{height})", + "scaling-percentage": "{percentage}%", + "location-display": "{name} ({coordinates})", + "signal-strength": "{signal}%", + "cpu-temperature": "{temp}°C", + "disk-usage": "{percent}%", + "widget-settings-title": "{widget} Settings", + "unknown-app": "Unknown App", + "no-media-player-detected": "No media player detected", + "user-requested": "User requested", + "unknown": "Unknown", + "unknown-version": "Unknown", + "unknown-layout": "Unknown" + }, "lock-screen": { "secure-terminal": "SECURE TERMINAL", "unlock-command": "sudo unlock-session", diff --git a/Bin/check-i18n.sh b/Bin/check-i18n.sh new file mode 100644 index 00000000..77372b79 --- /dev/null +++ b/Bin/check-i18n.sh @@ -0,0 +1,65 @@ +#!/bin/bash + +# Comprehensive i18n checker for Noctalia Shell +# Finds hardcoded strings that should be internationalized + +check_file() { + local file="$1" + + # Check for hardcoded strings in common properties + # Includes: label, text, title, description, tooltip, tooltipText, placeholder, placeholderText + local property_issues=$(grep -n -E '(label|text|title|description|tooltip|tooltipText|placeholder|placeholderText):\s*"[^"]{3,}"' "$file" | grep -v 'I18n.tr') + + # Check for hardcoded strings in dialog titles and button texts + local dialog_issues=$(grep -n -E '(dialog\.|Dialog\.|title:|buttonText:)\s*"[^"]{3,}"' "$file" | grep -v 'I18n.tr') + + # Check for hardcoded strings in model name properties (for combo boxes) + local model_issues=$(grep -n -E 'name:\s*"[^"]{3,}"' "$file" | grep -v 'I18n.tr') + + # Check for hardcoded strings in common UI text patterns + local ui_issues=$(grep -n -E '"[^"]*\b(click|open|close|enable|disable|show|hide|settings|cancel|apply|ok|save|load|start|stop|play|pause|next|previous|volume|brightness|wifi|bluetooth|notification|wallpaper|profile|power|session|menu|panel|dialog|button|toggle|slider|checkbox|radio|combo|input|search|filter|sort|refresh|update|delete|remove|add|create|edit|modify|copy|paste|cut|undo|redo|help|about|info|warning|error|success|failed|loading|connecting|connected|disconnected|scanning|pairing|recording|playing|paused|stopped|muted|unmuted|enabled|disabled|on|off|yes|no|true|false)\b[^"]*"' "$file" | grep -v 'I18n.tr' | grep -v '//' | grep -v '/*') + + # Combine all issues + local all_issues="$property_issues" + if [[ -n "$dialog_issues" ]]; then + all_issues="$all_issues"$'\n'"$dialog_issues" + fi + if [[ -n "$model_issues" ]]; then + all_issues="$all_issues"$'\n'"$model_issues" + fi + if [[ -n "$ui_issues" ]]; then + all_issues="$all_issues"$'\n'"$ui_issues" + fi + + # Remove empty lines and duplicates + all_issues=$(echo "$all_issues" | grep -v '^$' | sort -u) + + if [[ -n "$all_issues" ]]; then + echo "$file" + echo "$all_issues" | while IFS= read -r line; do + echo " $line" + done + echo + fi +} + +echo "Comprehensive i18n Checker" +echo "=========================" +echo "Scanning QML files for hardcoded strings..." +echo + +found_issues=false + +while IFS= read -r -d '' file; do + if check_file "$file" | grep -q .; then + check_file "$file" + found_issues=true + fi +done < <(find . -name "*.qml" -not -path "./Assets/*" -print0) + +if [[ "$found_issues" == false ]]; then + echo "No hardcoded strings found! All strings appear to be internationalized." +else + echo "Note: Review each match manually - some may be false positives" + echo "(property names, IDs, technical values, comments shouldn't be translated)" +fi diff --git a/Bin/i18n-check.sh b/Bin/i18n-check.sh index 96f5cc45..553370d6 100755 --- a/Bin/i18n-check.sh +++ b/Bin/i18n-check.sh @@ -1,62 +1,27 @@ #!/bin/bash -# Noctalia Shell i18n Checker -# Scans for hardcoded strings that need internationalization +# Comprehensive i18n checker for QML files +# Finds hardcoded strings in various QML properties -# Colors -RED='\033[0;31m' -GREEN='\033[0;32m' -YELLOW='\033[1;33m' -BLUE='\033[0;34m' -CYAN='\033[0;36m' -NC='\033[0m' - -echo -e "${BLUE}Noctalia Shell i18n Checker${NC}" -echo -e "${BLUE}===========================${NC}" - -files_with_issues=0 - -# Check a single file -check_file() { - local file="$1" - local issues=$(grep -n -E '(label|text|title|description|tooltip|placeholder):\s*"[^"]{3,}"' "$file" | grep -v 'I18n.tr') +find . -name "*.qml" -type f | while read -r file; do + # Skip if file doesn't exist or is not readable + [[ ! -r "$file" ]] && continue - if [[ -n "$issues" ]]; then - echo -e "${YELLOW}$file${NC}" - echo "$issues" | sed 's/^/ /' - echo "" - return 1 + # Check for hardcoded strings in common properties + # Matches: property: "text with letters" but excludes I18n.tr calls + issues=$(grep -n -E '(label|text|title|description|placeholder|tooltipText|tooltip):\s*"[^"]*[a-zA-Z][^"]*"' "$file" | grep -v 'I18n\.tr') + + # Also check for template literals with hardcoded text + template_issues=$(grep -n -E '(label|text|title|description|placeholder|tooltipText|tooltip):\s*`[^`]*[a-zA-Z][^`]*`' "$file" | grep -v 'I18n\.tr') + + # Check for property assignments with hardcoded strings + property_issues=$(grep -n -E 'property\s+string\s+\w+:\s*"[^"]*[a-zA-Z][^"]*"' "$file" | grep -v 'I18n\.tr') + + if [[ -n "$issues" || -n "$template_issues" || -n "$property_issues" ]]; then + echo "$file" + [[ -n "$issues" ]] && echo "$issues" + [[ -n "$template_issues" ]] && echo "$template_issues" + [[ -n "$property_issues" ]] && echo "$property_issues" + echo fi - return 0 -} - -echo "Scanning QML files..." -echo "" - -# Find and check QML files -qml_files=$(find . -name "*.qml" -type f \ - ! -path "./Assets/*" \ - ! -path "./Bin/*" \ - ! -path "./Shaders/*" \ - ! -path "./Helpers/*" \ - ! -path "./.git/*") - -total_files=$(echo "$qml_files" | wc -l) - -for file in $qml_files; do - if ! check_file "$file"; then - ((files_with_issues++)) - fi -done - -# Summary -echo -e "${BLUE}Summary${NC}" -echo -e "${BLUE}=======${NC}" -echo -e "Files scanned: $total_files" -echo -e "Files needing i18n: $files_with_issues" - -if [[ $files_with_issues -eq 0 ]]; then - echo -e "${GREEN}All files use I18n.tr() properly!${NC}" -else - echo -e "${YELLOW}$files_with_issues files have potential hardcoded strings${NC}" -fi \ No newline at end of file +done \ No newline at end of file diff --git a/Modules/Bar/WiFi/WiFiPanel.qml b/Modules/Bar/WiFi/WiFiPanel.qml index 0590c795..ebb8a0b7 100644 --- a/Modules/Bar/WiFi/WiFiPanel.qml +++ b/Modules/Bar/WiFi/WiFiPanel.qml @@ -263,7 +263,9 @@ NPanel { spacing: Style.marginXS * scaling NText { - text: `${modelData.signal}%` + text: I18n.tr("system.signal-strength", { + "signal": modelData.signal + }) font.pointSize: Style.fontSizeXXS * scaling color: Color.mOnSurfaceVariant } diff --git a/Modules/Bar/Widgets/KeyboardLayout.qml b/Modules/Bar/Widgets/KeyboardLayout.qml index 38f27d82..ec83b71e 100644 --- a/Modules/Bar/Widgets/KeyboardLayout.qml +++ b/Modules/Bar/Widgets/KeyboardLayout.qml @@ -48,7 +48,9 @@ Item { icon: "keyboard" autoHide: false // Important to be false so we can hover as long as we want text: currentLayout.toUpperCase() - tooltipText: `${currentLayout.toUpperCase()} keyboard layout` + tooltipText: I18n.tr("tooltips.keyboard-layout", { + "layout": currentLayout.toUpperCase() + }) forceOpen: root.displayMode === "forceOpen" forceClose: root.displayMode === "alwaysHide" onClicked: { diff --git a/Modules/Bar/Widgets/Microphone.qml b/Modules/Bar/Widgets/Microphone.qml index 71b756d6..548670c4 100644 --- a/Modules/Bar/Widgets/Microphone.qml +++ b/Modules/Bar/Widgets/Microphone.qml @@ -97,7 +97,9 @@ Item { suffix: "%" forceOpen: displayMode === "alwaysShow" forceClose: displayMode === "alwaysHide" - tooltipText: I18n.tr("tooltips.microphone-volume-at", {"volume": Math.round(AudioService.inputVolume * 100)}) + tooltipText: I18n.tr("tooltips.microphone-volume-at", { + "volume": Math.round(AudioService.inputVolume * 100) + }) onWheel: function (delta) { wheelAccumulator += delta diff --git a/Modules/Bar/Widgets/PowerProfile.qml b/Modules/Bar/Widgets/PowerProfile.qml index adc09e8e..691c72ca 100644 --- a/Modules/Bar/Widgets/PowerProfile.qml +++ b/Modules/Bar/Widgets/PowerProfile.qml @@ -16,7 +16,9 @@ NIconButton { visible: PowerProfileService.available icon: PowerProfileService.getIcon() - tooltipText: `'${PowerProfileService.getName()}' power profile` + tooltipText: I18n.tr("tooltips.power-profile", { + "profile": PowerProfileService.getName() + }) compact: (Settings.data.bar.density === "compact") colorBg: (PowerProfileService.profile === PowerProfile.Balanced) ? (Settings.data.bar.showCapsule ? Color.mSurfaceVariant : Color.transparent) : Color.mPrimary colorFg: (PowerProfileService.profile === PowerProfile.Balanced) ? Color.mOnSurface : Color.mOnPrimary diff --git a/Modules/Bar/Widgets/SystemMonitor.qml b/Modules/Bar/Widgets/SystemMonitor.qml index 9bd1d1fb..2c14b242 100644 --- a/Modules/Bar/Widgets/SystemMonitor.qml +++ b/Modules/Bar/Widgets/SystemMonitor.qml @@ -120,7 +120,9 @@ Rectangle { columnSpacing: Style.marginXXS * scaling NText { - text: `${SystemStatService.cpuTemp}°C` + text: I18n.tr("system.cpu-temperature", { + "temp": SystemStatService.cpuTemp + }) font.family: Settings.data.ui.fontFixed font.pointSize: textSize font.weight: Style.fontWeightMedium @@ -283,7 +285,9 @@ Rectangle { columnSpacing: isVertical ? (Style.marginXXS * scaling) : (Style.marginXS * scaling) NText { - text: `${SystemStatService.diskPercent}%` + text: I18n.tr("system.disk-usage", { + "percent": SystemStatService.diskPercent + }) font.family: Settings.data.ui.fontFixed font.pointSize: textSize font.weight: Style.fontWeightMedium diff --git a/Modules/Bar/Widgets/Volume.qml b/Modules/Bar/Widgets/Volume.qml index 0d65b4b2..c58233e5 100644 --- a/Modules/Bar/Widgets/Volume.qml +++ b/Modules/Bar/Widgets/Volume.qml @@ -83,7 +83,9 @@ Item { suffix: "%" forceOpen: displayMode === "alwaysShow" forceClose: displayMode === "alwaysHide" - tooltipText: I18n.tr("tooltips.volume-at", {"volume": Math.round(AudioService.volume * 100)}) + tooltipText: I18n.tr("tooltips.volume-at", { + "volume": Math.round(AudioService.volume * 100) + }) onWheel: function (delta) { wheelAccumulator += delta diff --git a/Modules/ControlCenter/Cards/MediaCard.qml b/Modules/ControlCenter/Cards/MediaCard.qml index bed4ce83..032eb106 100644 --- a/Modules/ControlCenter/Cards/MediaCard.qml +++ b/Modules/ControlCenter/Cards/MediaCard.qml @@ -34,7 +34,7 @@ NBox { } // NText { - // text: "No media player detected" + // text: I18n.tr("system.no-media-player-detected") // color: Color.mOnSurfaceVariant // Layout.alignment: Qt.AlignHCenter // } diff --git a/Modules/ControlCenter/Cards/PowerProfilesCard.qml b/Modules/ControlCenter/Cards/PowerProfilesCard.qml index 09cfe286..d93b26ba 100644 --- a/Modules/ControlCenter/Cards/PowerProfilesCard.qml +++ b/Modules/ControlCenter/Cards/PowerProfilesCard.qml @@ -26,7 +26,9 @@ NBox { // Performance NIconButton { icon: PowerProfileService.getIcon(PowerProfile.Performance) - tooltipText: I18n.tr("tooltips.set-power-profile", {"profile": PowerProfileService.getName(PowerProfile.Performance)}) + tooltipText: I18n.tr("tooltips.set-power-profile", { + "profile": PowerProfileService.getName(PowerProfile.Performance) + }) enabled: hasPP opacity: enabled ? Style.opacityFull : Style.opacityMedium colorBg: (enabled && PowerProfileService.profile === PowerProfile.Performance) ? Color.mPrimary : Color.mSurfaceVariant @@ -36,7 +38,9 @@ NBox { // Balanced NIconButton { icon: PowerProfileService.getIcon(PowerProfile.Balanced) - tooltipText: I18n.tr("tooltips.set-power-profile", {"profile": PowerProfileService.getName(PowerProfile.Balanced)}) + tooltipText: I18n.tr("tooltips.set-power-profile", { + "profile": PowerProfileService.getName(PowerProfile.Balanced) + }) enabled: hasPP opacity: enabled ? Style.opacityFull : Style.opacityMedium colorBg: (enabled && PowerProfileService.profile === PowerProfile.Balanced) ? Color.mPrimary : Color.mSurfaceVariant @@ -46,7 +50,9 @@ NBox { // Eco NIconButton { icon: PowerProfileService.getIcon(PowerProfile.PowerSaver) - tooltipText: I18n.tr("tooltips.set-power-profile", {"profile": PowerProfileService.getName(PowerProfile.PowerSaver)}) + tooltipText: I18n.tr("tooltips.set-power-profile", { + "profile": PowerProfileService.getName(PowerProfile.PowerSaver) + }) enabled: hasPP opacity: enabled ? Style.opacityFull : Style.opacityMedium colorBg: (enabled && PowerProfileService.profile === PowerProfile.PowerSaver) ? Color.mPrimary : Color.mSurfaceVariant diff --git a/Modules/ControlCenter/Cards/ProfileCard.qml b/Modules/ControlCenter/Cards/ProfileCard.qml index 1d3e35d0..effd69fc 100644 --- a/Modules/ControlCenter/Cards/ProfileCard.qml +++ b/Modules/ControlCenter/Cards/ProfileCard.qml @@ -42,7 +42,9 @@ NBox { font.capitalization: Font.Capitalize } NText { - text: `System uptime: ${uptimeText}` + text: I18n.tr("system.uptime", { + "uptime": uptimeText + }) font.pointSize: Style.fontSizeS * scaling color: Color.mOnSurfaceVariant } diff --git a/Modules/LockScreen/LockScreen.qml b/Modules/LockScreen/LockScreen.qml index 89611629..a1b0622c 100644 --- a/Modules/LockScreen/LockScreen.qml +++ b/Modules/LockScreen/LockScreen.qml @@ -455,7 +455,9 @@ Loader { font.family: Settings.data.ui.fontFixed font.pointSize: Style.fontSizeL * scaling property int currentIndex: 0 - property string fullText: "Welcome back, " + Quickshell.env("USER") + "!" + property string fullText: I18n.tr("system.welcome-back", { + "user": Quickshell.env("USER") + }) Timer { interval: Style.animationFast diff --git a/Modules/Notification/Notification.qml b/Modules/Notification/Notification.qml index 12405c96..4cf82f73 100644 --- a/Modules/Notification/Notification.qml +++ b/Modules/Notification/Notification.qml @@ -282,7 +282,7 @@ Variants { } NText { - text: `${model.appName || "Unknown App"} · ${Time.formatRelativeTime(model.timestamp)}` + text: `${model.appName || I18n.tr("system.unknown-app")} · ${Time.formatRelativeTime(model.timestamp)}` color: Color.mSecondary font.pointSize: Style.fontSizeXS * scaling } diff --git a/Modules/Settings/Bar/BarWidgetSettingsDialog.qml b/Modules/Settings/Bar/BarWidgetSettingsDialog.qml index 72981f85..09165a07 100644 --- a/Modules/Settings/Bar/BarWidgetSettingsDialog.qml +++ b/Modules/Settings/Bar/BarWidgetSettingsDialog.qml @@ -63,7 +63,9 @@ Popup { Layout.fillWidth: true NText { - text: `${widgetSettings.widgetId} Settings` + text: I18n.tr("system.widget-settings-title", { + "widget": widgetSettings.widgetId + }) font.pointSize: Style.fontSizeL * scaling font.weight: Style.fontWeightBold color: Color.mPrimary diff --git a/Modules/Settings/Bar/WidgetSettings/BatterySettings.qml b/Modules/Settings/Bar/WidgetSettings/BatterySettings.qml index acb14169..addf7ff8 100644 --- a/Modules/Settings/Bar/WidgetSettings/BatterySettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/BatterySettings.qml @@ -28,20 +28,16 @@ ColumnLayout { label: I18n.tr("bar.widget-settings.battery.display-mode.label") description: I18n.tr("bar.widget-settings.battery.display-mode.description") minimumWidth: 134 * scaling - model: [ - { - key: "onhover", - name: I18n.tr("options.display-mode.on-hover") - }, - { - key: "alwaysShow", - name: I18n.tr("options.display-mode.always-show") - }, - { - key: "alwaysHide", - name: I18n.tr("options.display-mode.always-hide") - } - ] + model: [{ + "key": "onhover", + "name": I18n.tr("options.display-mode.on-hover") + }, { + "key": "alwaysShow", + "name": I18n.tr("options.display-mode.always-show") + }, { + "key": "alwaysHide", + "name": I18n.tr("options.display-mode.always-hide") + }] currentKey: root.valueDisplayMode onSelected: key => root.valueDisplayMode = key } diff --git a/Modules/Settings/Bar/WidgetSettings/BrightnessSettings.qml b/Modules/Settings/Bar/WidgetSettings/BrightnessSettings.qml index 9d5070e3..c21d7aae 100644 --- a/Modules/Settings/Bar/WidgetSettings/BrightnessSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/BrightnessSettings.qml @@ -26,20 +26,16 @@ ColumnLayout { label: I18n.tr("bar.widget-settings.brightness.display-mode.label") description: I18n.tr("bar.widget-settings.brightness.display-mode.description") minimumWidth: 134 * scaling - model: [ - { - key: "onhover", - name: I18n.tr("options.display-mode.on-hover") - }, - { - key: "alwaysShow", - name: I18n.tr("options.display-mode.always-show") - }, - { - key: "alwaysHide", - name: I18n.tr("options.display-mode.always-hide") - } - ] + model: [{ + "key": "onhover", + "name": I18n.tr("options.display-mode.on-hover") + }, { + "key": "alwaysShow", + "name": I18n.tr("options.display-mode.always-show") + }, { + "key": "alwaysHide", + "name": I18n.tr("options.display-mode.always-hide") + }] currentKey: valueDisplayMode onSelected: key => valueDisplayMode = key } diff --git a/Modules/Settings/Bar/WidgetSettings/KeyboardLayoutSettings.qml b/Modules/Settings/Bar/WidgetSettings/KeyboardLayoutSettings.qml index 9350e9b7..d3551044 100644 --- a/Modules/Settings/Bar/WidgetSettings/KeyboardLayoutSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/KeyboardLayoutSettings.qml @@ -26,20 +26,16 @@ ColumnLayout { label: I18n.tr("bar.widget-settings.keyboard-layout.display-mode.label") description: I18n.tr("bar.widget-settings.keyboard-layout.display-mode.description") minimumWidth: 134 * scaling - model: [ - { - key: "onhover", - name: I18n.tr("options.display-mode.on-hover") - }, - { - key: "forceOpen", - name: I18n.tr("options.display-mode.force-open") - }, - { - key: "alwaysHide", - name: I18n.tr("options.display-mode.always-hide") - } - ] + model: [{ + "key": "onhover", + "name": I18n.tr("options.display-mode.on-hover") + }, { + "key": "forceOpen", + "name": I18n.tr("options.display-mode.force-open") + }, { + "key": "alwaysHide", + "name": I18n.tr("options.display-mode.always-hide") + }] currentKey: valueDisplayMode onSelected: key => valueDisplayMode = key } diff --git a/Modules/Settings/Bar/WidgetSettings/MediaMiniSettings.qml b/Modules/Settings/Bar/WidgetSettings/MediaMiniSettings.qml index daeaf5a6..b357fa12 100644 --- a/Modules/Settings/Bar/WidgetSettings/MediaMiniSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/MediaMiniSettings.qml @@ -41,20 +41,16 @@ ColumnLayout { NComboBox { visible: valueShowVisualizer label: I18n.tr("bar.widget-settings.media-mini.visualizer-type") - model: [ - { - key: "linear", - name: I18n.tr("options.visualizer-types.linear") - }, - { - key: "mirrored", - name: I18n.tr("options.visualizer-types.mirrored") - }, - { - key: "wave", - name: I18n.tr("options.visualizer-types.wave") - } - ] + model: [{ + "key": "linear", + "name": I18n.tr("options.visualizer-types.linear") + }, { + "key": "mirrored", + "name": I18n.tr("options.visualizer-types.mirrored") + }, { + "key": "wave", + "name": I18n.tr("options.visualizer-types.wave") + }] currentKey: valueVisualizerType onSelected: key => valueVisualizerType = key minimumWidth: 200 * scaling diff --git a/Modules/Settings/Bar/WidgetSettings/MicrophoneSettings.qml b/Modules/Settings/Bar/WidgetSettings/MicrophoneSettings.qml index d7071022..5091474d 100644 --- a/Modules/Settings/Bar/WidgetSettings/MicrophoneSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/MicrophoneSettings.qml @@ -26,20 +26,16 @@ ColumnLayout { label: I18n.tr("bar.widget-settings.microphone.display-mode.label") description: I18n.tr("bar.widget-settings.microphone.display-mode.description") minimumWidth: 134 * scaling - model: [ - { - key: "onhover", - name: I18n.tr("options.display-mode.on-hover") - }, - { - key: "alwaysShow", - name: I18n.tr("options.display-mode.always-show") - }, - { - key: "alwaysHide", - name: I18n.tr("options.display-mode.always-hide") - } - ] + model: [{ + "key": "onhover", + "name": I18n.tr("options.display-mode.on-hover") + }, { + "key": "alwaysShow", + "name": I18n.tr("options.display-mode.always-show") + }, { + "key": "alwaysHide", + "name": I18n.tr("options.display-mode.always-hide") + }] currentKey: valueDisplayMode onSelected: key => valueDisplayMode = key } diff --git a/Modules/Settings/Bar/WidgetSettings/VolumeSettings.qml b/Modules/Settings/Bar/WidgetSettings/VolumeSettings.qml index 987bedbb..2781f4a6 100644 --- a/Modules/Settings/Bar/WidgetSettings/VolumeSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/VolumeSettings.qml @@ -26,20 +26,16 @@ ColumnLayout { label: I18n.tr("bar.widget-settings.volume.display-mode.label") description: I18n.tr("bar.widget-settings.volume.display-mode.description") minimumWidth: 134 * scaling - model: [ - { - key: "onhover", - name: I18n.tr("options.display-mode.on-hover") - }, - { - key: "alwaysShow", - name: I18n.tr("options.display-mode.always-show") - }, - { - key: "alwaysHide", - name: I18n.tr("options.display-mode.always-hide") - } - ] + model: [{ + "key": "onhover", + "name": I18n.tr("options.display-mode.on-hover") + }, { + "key": "alwaysShow", + "name": I18n.tr("options.display-mode.always-show") + }, { + "key": "alwaysHide", + "name": I18n.tr("options.display-mode.always-hide") + }] currentKey: valueDisplayMode onSelected: key => valueDisplayMode = key } diff --git a/Modules/Settings/Bar/WidgetSettings/WorkspaceSettings.qml b/Modules/Settings/Bar/WidgetSettings/WorkspaceSettings.qml index 3c8ce794..27c4b057 100644 --- a/Modules/Settings/Bar/WidgetSettings/WorkspaceSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/WorkspaceSettings.qml @@ -24,20 +24,16 @@ ColumnLayout { id: labelModeCombo label: I18n.tr("bar.widget-settings.workspace.label-mode") - model: [ - { - key: "none", - name: I18n.tr("options.workspace-labels.none") - }, - { - key: "index", - name: I18n.tr("options.workspace-labels.index") - }, - { - key: "name", - name: I18n.tr("options.workspace-labels.name") - } - ] + model: [{ + "key": "none", + "name": I18n.tr("options.workspace-labels.none") + }, { + "key": "index", + "name": I18n.tr("options.workspace-labels.index") + }, { + "key": "name", + "name": I18n.tr("options.workspace-labels.name") + }] currentKey: widgetData.labelMode || widgetMetadata.labelMode onSelected: key => labelModeCombo.currentKey = key minimumWidth: 200 * scaling diff --git a/Modules/Settings/Tabs/AudioTab.qml b/Modules/Settings/Tabs/AudioTab.qml index bd02fbd2..5fcdca24 100644 --- a/Modules/Settings/Tabs/AudioTab.qml +++ b/Modules/Settings/Tabs/AudioTab.qml @@ -326,24 +326,19 @@ ColumnLayout { id: audioVisualizerCombo label: I18n.tr("settings.audio.media.visualizer-type.label") description: I18n.tr("settings.audio.media.visualizer-type.description") - model: [ - { - key: "none", - name: I18n.tr("options.visualizer-types.none") - }, - { - key: "linear", - name: I18n.tr("options.visualizer-types.linear") - }, - { - key: "mirrored", - name: I18n.tr("options.visualizer-types.mirrored") - }, - { - key: "wave", - name: I18n.tr("options.visualizer-types.wave") - } - ] + model: [{ + "key": "none", + "name": I18n.tr("options.visualizer-types.none") + }, { + "key": "linear", + "name": I18n.tr("options.visualizer-types.linear") + }, { + "key": "mirrored", + "name": I18n.tr("options.visualizer-types.mirrored") + }, { + "key": "wave", + "name": I18n.tr("options.visualizer-types.wave") + }] currentKey: Settings.data.audio.visualizerType onSelected: key => Settings.data.audio.visualizerType = key } @@ -351,36 +346,28 @@ ColumnLayout { NComboBox { label: I18n.tr("settings.audio.media.frame-rate.label") description: I18n.tr("settings.audio.media.frame-rate.description") - model: [ - { - key: "30", - name: I18n.tr("options.frame-rates.30-fps") - }, - { - key: "60", - name: I18n.tr("options.frame-rates.60-fps") - }, - { - key: "100", - name: I18n.tr("options.frame-rates.100-fps") - }, - { - key: "120", - name: I18n.tr("options.frame-rates.120-fps") - }, - { - key: "144", - name: I18n.tr("options.frame-rates.144-fps") - }, - { - key: "165", - name: I18n.tr("options.frame-rates.165-fps") - }, - { - key: "240", - name: I18n.tr("options.frame-rates.240-fps") - } - ] + model: [{ + "key": "30", + "name": I18n.tr("options.frame-rates.30-fps") + }, { + "key": "60", + "name": I18n.tr("options.frame-rates.60-fps") + }, { + "key": "100", + "name": I18n.tr("options.frame-rates.100-fps") + }, { + "key": "120", + "name": I18n.tr("options.frame-rates.120-fps") + }, { + "key": "144", + "name": I18n.tr("options.frame-rates.144-fps") + }, { + "key": "165", + "name": I18n.tr("options.frame-rates.165-fps") + }, { + "key": "240", + "name": I18n.tr("options.frame-rates.240-fps") + }] currentKey: Settings.data.audio.cavaFrameRate onSelected: key => Settings.data.audio.cavaFrameRate = key } diff --git a/Modules/Settings/Tabs/BarTab.qml b/Modules/Settings/Tabs/BarTab.qml index 4743edab..17407631 100644 --- a/Modules/Settings/Tabs/BarTab.qml +++ b/Modules/Settings/Tabs/BarTab.qml @@ -277,7 +277,11 @@ ColumnLayout { delegate: NCheckbox { Layout.fillWidth: true label: modelData.name || "Unknown" - description: `${modelData.model} (${modelData.width}x${modelData.height})` + description: I18n.tr("system.monitor-description", { + "model": modelData.model, + "width": modelData.width, + "height": modelData.height + }) checked: (Settings.data.bar.monitors || []).indexOf(modelData.name) !== -1 onToggled: checked => { if (checked) { diff --git a/Modules/Settings/Tabs/DisplayTab.qml b/Modules/Settings/Tabs/DisplayTab.qml index a8a24e66..2146f825 100644 --- a/Modules/Settings/Tabs/DisplayTab.qml +++ b/Modules/Settings/Tabs/DisplayTab.qml @@ -90,7 +90,11 @@ ColumnLayout { NLabel { label: modelData.name || "Unknown" - description: `${modelData.model} (${modelData.width}x${modelData.height})` + description: I18n.tr("system.monitor-description", { + "model": modelData.model, + "width": modelData.width, + "height": modelData.height + }) } // Scale @@ -114,7 +118,9 @@ ColumnLayout { stepSize: 0.01 value: localScaling onPressedChanged: (pressed, value) => ScalingService.setScreenScale(modelData, value) - text: `${Math.round(localScaling * 100)}%` + text: I18n.tr("system.scaling-percentage", { + "percentage": Math.round(localScaling * 100) + }) Layout.fillWidth: true } diff --git a/Modules/Settings/Tabs/DockTab.qml b/Modules/Settings/Tabs/DockTab.qml index edb8679a..c3b1d559 100644 --- a/Modules/Settings/Tabs/DockTab.qml +++ b/Modules/Settings/Tabs/DockTab.qml @@ -101,7 +101,11 @@ ColumnLayout { delegate: NCheckbox { Layout.fillWidth: true label: modelData.name || "Unknown" - description: `${modelData.model} (${modelData.width}x${modelData.height})` + description: I18n.tr("system.monitor-description", { + "model": modelData.model, + "width": modelData.width, + "height": modelData.height + }) checked: (Settings.data.dock.monitors || []).indexOf(modelData.name) !== -1 onToggled: checked => { if (checked) { diff --git a/Modules/Settings/Tabs/LocationTab.qml b/Modules/Settings/Tabs/LocationTab.qml index 2e286dc4..eafa3902 100644 --- a/Modules/Settings/Tabs/LocationTab.qml +++ b/Modules/Settings/Tabs/LocationTab.qml @@ -42,7 +42,10 @@ ColumnLayout { NText { visible: LocationService.coordinatesReady - text: `${LocationService.stableName} (${LocationService.displayCoordinates})` + text: I18n.tr("system.location-display", { + "name": LocationService.stableName, + "coordinates": LocationService.displayCoordinates + }) font.pointSize: Style.fontSizeS * scaling color: Color.mOnSurfaceVariant verticalAlignment: Text.AlignVCenter diff --git a/Modules/Settings/Tabs/NotificationsTab.qml b/Modules/Settings/Tabs/NotificationsTab.qml index fab5d0d6..85a2375e 100644 --- a/Modules/Settings/Tabs/NotificationsTab.qml +++ b/Modules/Settings/Tabs/NotificationsTab.qml @@ -151,7 +151,11 @@ ColumnLayout { delegate: NCheckbox { Layout.fillWidth: true label: modelData.name || "Unknown" - description: `${modelData.model} (${modelData.width}x${modelData.height})` + description: I18n.tr("system.monitor-description", { + "model": modelData.model, + "width": modelData.width, + "height": modelData.height + }) checked: (Settings.data.notifications.monitors || []).indexOf(modelData.name) !== -1 onToggled: checked => { if (checked) { diff --git a/Modules/Settings/Tabs/ScreenRecorderTab.qml b/Modules/Settings/Tabs/ScreenRecorderTab.qml index 3d464439..d3f77e67 100644 --- a/Modules/Settings/Tabs/ScreenRecorderTab.qml +++ b/Modules/Settings/Tabs/ScreenRecorderTab.qml @@ -61,16 +61,13 @@ ColumnLayout { NComboBox { label: I18n.tr("settings.screen-recorder.video.video-source.label") description: I18n.tr("settings.screen-recorder.video.video-source.description") - model: [ - { - key: "portal", - name: I18n.tr("options.screen-recording.sources.portal") - }, - { - key: "screen", - name: I18n.tr("options.screen-recording.sources.screen") - } - ] + model: [{ + "key": "portal", + "name": I18n.tr("options.screen-recording.sources.portal") + }, { + "key": "screen", + "name": I18n.tr("options.screen-recording.sources.screen") + }] currentKey: Settings.data.screenRecorder.videoSource onSelected: key => Settings.data.screenRecorder.videoSource = key } diff --git a/Services/GitHubService.qml b/Services/GitHubService.qml index 1c5583fc..93982df9 100644 --- a/Services/GitHubService.qml +++ b/Services/GitHubService.qml @@ -16,7 +16,7 @@ Singleton { readonly property alias data: adapter // Used to access via GitHubService.data.xxx.yyy // Public properties for easy access - property string latestVersion: "Unknown" + property string latestVersion: I18n.tr("system.unknown-version") property var contributors: [] FileView { @@ -43,7 +43,7 @@ Singleton { JsonAdapter { id: adapter - property string version: "Unknown" + property string version: I18n.tr("system.unknown-version") property var contributors: [] property real timestamp: 0 } @@ -97,7 +97,7 @@ Singleton { // -------------------------------- function resetCache() { - data.version = "Unknown" + data.version = I18n.tr("system.unknown-version") data.contributors = [] data.timestamp = 0 diff --git a/Services/IdleInhibitorService.qml b/Services/IdleInhibitorService.qml index 3f5e3c4c..c804226e 100644 --- a/Services/IdleInhibitorService.qml +++ b/Services/IdleInhibitorService.qml @@ -10,7 +10,7 @@ Singleton { id: root property bool isInhibited: false - property string reason: "User requested" + property string reason: I18n.tr("system.user-requested") property var activeInhibitors: [] // Different inhibitor strategies diff --git a/Services/KeyboardLayoutService.qml b/Services/KeyboardLayoutService.qml index fc500e2a..3006d121 100644 --- a/Services/KeyboardLayoutService.qml +++ b/Services/KeyboardLayoutService.qml @@ -9,7 +9,7 @@ import qs.Services Singleton { id: root - property string currentLayout: "Unknown" + property string currentLayout: I18n.tr("system.unknown-layout") property int updateInterval: 1000 // Update every second // Timer to periodically update the layout diff --git a/Widgets/NFilePicker.qml b/Widgets/NFilePicker.qml index f5fb2336..608fde9f 100644 --- a/Widgets/NFilePicker.qml +++ b/Widgets/NFilePicker.qml @@ -15,8 +15,8 @@ Item { property string pickerType: "file" // "file" or "folder" property var nameFilters: ["All files (*)"] // e.g., ["Image files (*.png *.jpg)", "Text files (*.txt)"] property string title: pickerType === "folder" ? "Select Folder" : "Select File" - property string acceptLabel: "Select" - property string rejectLabel: "Cancel" + property string acceptLabel: I18n.tr("placeholders.select") + property string rejectLabel: I18n.tr("placeholders.cancel") // State properties property bool isOpen: false diff --git a/Widgets/NInputAction.qml b/Widgets/NInputAction.qml index abe03961..d689d304 100644 --- a/Widgets/NInputAction.qml +++ b/Widgets/NInputAction.qml @@ -13,7 +13,7 @@ RowLayout { property string description: "" property string placeholderText: "" property string text: "" - property string actionButtonText: "Test" + property string actionButtonText: I18n.tr("placeholders.test") property string actionButtonIcon: "media-play" property bool actionButtonEnabled: text !== "" diff --git a/Widgets/NSearchableComboBox.qml b/Widgets/NSearchableComboBox.qml index 27fb2a0d..be3f5e75 100644 --- a/Widgets/NSearchableComboBox.qml +++ b/Widgets/NSearchableComboBox.qml @@ -19,7 +19,7 @@ RowLayout { } property string currentKey: "" property string placeholder: "" - property string searchPlaceholder: "Search..." + property string searchPlaceholder: I18n.tr("placeholders.search") readonly property real preferredHeight: Style.baseWidgetSize * 1.1 * scaling From 04f247905adf0edbc3fdfc23d4770564ec588904 Mon Sep 17 00:00:00 2001 From: Ly-sec Date: Wed, 24 Sep 2025 14:30:30 +0200 Subject: [PATCH 06/15] i18n-check: updated detection i18n: added some odd ones --- Assets/Translations/en.json | 24 ++++++++++++++++++- Bin/i18n-check.sh | 6 ++++- Modules/Launcher/Plugins/CalculatorPlugin.qml | 8 +++---- Modules/Launcher/Plugins/ClipboardPlugin.qml | 20 ++++++++-------- Modules/SessionMenu/SessionMenu.qml | 10 ++++---- Modules/Settings/Bar/BarSectionEditor.qml | 6 ++--- 6 files changed, 50 insertions(+), 24 deletions(-) diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index 896e72d4..dcc0c456 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -938,6 +938,9 @@ "add-widget": "Add widget", "widget-settings": "Widget settings", "remove-widget": "Remove widget", + "move-to-left-section": "Move to left section", + "move-to-center-section": "Move to center section", + "move-to-right-section": "Move to right section", "open-settings": "Open settings", "session-menu": "Session Menu", "close-side-panel": "Close side panel", @@ -1060,10 +1063,29 @@ } } }, + "session-menu": { + "lock": "Lock", + "suspend": "Suspend", + "reboot": "Reboot", + "logout": "Logout", + "shutdown": "Shutdown" + }, "plugins": { "applications": "Applications", "clipboard": "Clipboard history", - "calculator": "Calculator" + "calculator": "Calculator", + "clipboard-search-description": "Search clipboard history", + "clipboard-clear-description": "Clear all clipboard history", + "clipboard-history-disabled": "Clipboard history disabled", + "clipboard-history-disabled-description": "Enable clipboard history in settings or install cliphist", + "clipboard-clear-history": "Clear clipboard history", + "clipboard-clear-description-full": "Remove all items from clipboard history", + "clipboard-loading": "Loading clipboard history...", + "clipboard-loading-description": "Please wait", + "calculator-description": "Calculator - evaluate mathematical expressions", + "calculator-name": "Calculator", + "calculator-enter-expression": "Enter a mathematical expression", + "calculator-error": "Error" }, "system": { "uptime": "System uptime: {uptime}", diff --git a/Bin/i18n-check.sh b/Bin/i18n-check.sh index 553370d6..e86abd7b 100755 --- a/Bin/i18n-check.sh +++ b/Bin/i18n-check.sh @@ -17,11 +17,15 @@ find . -name "*.qml" -type f | while read -r file; do # Check for property assignments with hardcoded strings property_issues=$(grep -n -E 'property\s+string\s+\w+:\s*"[^"]*[a-zA-Z][^"]*"' "$file" | grep -v 'I18n\.tr') - if [[ -n "$issues" || -n "$template_issues" || -n "$property_issues" ]]; then + # Check for JavaScript object properties with hardcoded strings (like in arrays/models) + js_object_issues=$(grep -n -E '"(label|text|title|description|placeholder|name)":\s*"[^"]*[a-zA-Z][^"]*"' "$file" | grep -v 'I18n\.tr') + + if [[ -n "$issues" || -n "$template_issues" || -n "$property_issues" || -n "$js_object_issues" ]]; then echo "$file" [[ -n "$issues" ]] && echo "$issues" [[ -n "$template_issues" ]] && echo "$template_issues" [[ -n "$property_issues" ]] && echo "$property_issues" + [[ -n "$js_object_issues" ]] && echo "$js_object_issues" echo fi done \ No newline at end of file diff --git a/Modules/Launcher/Plugins/CalculatorPlugin.qml b/Modules/Launcher/Plugins/CalculatorPlugin.qml index 3f0b1a03..d3573b72 100644 --- a/Modules/Launcher/Plugins/CalculatorPlugin.qml +++ b/Modules/Launcher/Plugins/CalculatorPlugin.qml @@ -14,7 +14,7 @@ Item { function commands() { return [{ "name": ">calc", - "description": "Calculator - evaluate mathematical expressions", + "description": I18n.tr("plugins.calculator-description"), "icon": "accessories-calculator", "isImage": false, "onActivate": function () { @@ -36,8 +36,8 @@ Item { if (!expression) { return [{ - "name": "Calculator", - "description": "Enter a mathematical expression", + "name": I18n.tr("plugins.calculator-name"), + "description": I18n.tr("plugins.calculator-enter-expression"), "icon": "accessories-calculator", "isImage": false, "onActivate": function () {} @@ -59,7 +59,7 @@ Item { }] } catch (error) { return [{ - "name": "Error", + "name": I18n.tr("plugins.calculator-error"), "description": error.message || "Invalid expression", "icon": "dialog-error", "isImage": false, diff --git a/Modules/Launcher/Plugins/ClipboardPlugin.qml b/Modules/Launcher/Plugins/ClipboardPlugin.qml index 271f7823..1969606c 100644 --- a/Modules/Launcher/Plugins/ClipboardPlugin.qml +++ b/Modules/Launcher/Plugins/ClipboardPlugin.qml @@ -68,7 +68,7 @@ Item { function commands() { return [{ "name": ">clip", - "description": "Search clipboard history", + "description": I18n.tr("plugins.clipboard-search-description"), "icon": "text-x-generic", "isImage": false, "onActivate": function () { @@ -76,7 +76,7 @@ Item { } }, { "name": ">clip clear", - "description": "Clear all clipboard history", + "description": I18n.tr("plugins.clipboard-clear-description"), "icon": "text-x-generic", "isImage": false, "onActivate": function () { @@ -99,8 +99,8 @@ Item { // Check if clipboard service is not active if (!ClipboardService.active) { return [{ - "name": "Clipboard history disabled", - "description": "Enable clipboard history in settings or install cliphist", + "name": I18n.tr("plugins.clipboard-history-disabled"), + "description": I18n.tr("plugins.clipboard-history-disabled-description"), "icon": "view-refresh", "isImage": false, "onActivate": function () {} @@ -110,8 +110,8 @@ Item { // Special command: clear if (query === "clear") { return [{ - "name": "Clear clipboard history", - "description": "Remove all items from clipboard history", + "name": I18n.tr("plugins.clipboard-clear-history"), + "description": I18n.tr("plugins.clipboard-clear-description-full"), "icon": "delete_sweep", "isImage": false, "onActivate": function () { @@ -124,8 +124,8 @@ Item { // Show loading state if data is being loaded if (ClipboardService.loading || isWaitingForData) { return [{ - "name": "Loading clipboard history...", - "description": "Please wait", + "name": I18n.tr("plugins.clipboard-loading"), + "description": I18n.tr("plugins.clipboard-loading-description"), "icon": "view-refresh", "isImage": false, "onActivate": function () {} @@ -140,8 +140,8 @@ Item { isWaitingForData = true ClipboardService.list(100) return [{ - "name": "Loading clipboard history...", - "description": "Please wait", + "name": I18n.tr("plugins.clipboard-loading"), + "description": I18n.tr("plugins.clipboard-loading-description"), "icon": "view-refresh", "isImage": false, "onActivate": function () {} diff --git a/Modules/SessionMenu/SessionMenu.qml b/Modules/SessionMenu/SessionMenu.qml index b3a1b1a2..a24f0343 100644 --- a/Modules/SessionMenu/SessionMenu.qml +++ b/Modules/SessionMenu/SessionMenu.qml @@ -30,27 +30,27 @@ NPanel { readonly property var powerOptions: [{ "action": "lock", "icon": "lock", - "title": "Lock", + "title": I18n.tr("session-menu.lock"), "subtitle": "Lock your session" }, { "action": "suspend", "icon": "suspend", - "title": "Suspend", + "title": I18n.tr("session-menu.suspend"), "subtitle": "Put the system to sleep" }, { "action": "reboot", "icon": "reboot", - "title": "Reboot", + "title": I18n.tr("session-menu.reboot"), "subtitle": "Restart the system" }, { "action": "logout", "icon": "logout", - "title": "Logout", + "title": I18n.tr("session-menu.logout"), "subtitle": "End your session" }, { "action": "shutdown", "icon": "shutdown", - "title": "Shutdown", + "title": I18n.tr("session-menu.shutdown"), "subtitle": "Turn off the system", "isShutdown": true }] diff --git a/Modules/Settings/Bar/BarSectionEditor.qml b/Modules/Settings/Bar/BarSectionEditor.qml index 86b5e72f..6e1fb69a 100644 --- a/Modules/Settings/Bar/BarSectionEditor.qml +++ b/Modules/Settings/Bar/BarSectionEditor.qml @@ -166,17 +166,17 @@ NBox { parent: Overlay.overlay width: 240 * scaling model: [{ - "label": "Move to left section", + "label": I18n.tr("tooltips.move-to-left-section"), "action": "left", "icon": "arrow-bar-to-left", "visible": root.sectionId !== "left" }, { - "label": "Move to center section", + "label": I18n.tr("tooltips.move-to-center-section"), "action": "center", "icon": "layout-columns", "visible": root.sectionId !== "center" }, { - "label": "Move to right section", + "label": I18n.tr("tooltips.move-to-right-section"), "action": "right", "icon": "arrow-bar-to-right", "visible": root.sectionId !== "right" From 1d98a657b27d31d7552c41b3db6905b82a592673 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Wed, 24 Sep 2025 08:50:40 -0400 Subject: [PATCH 07/15] i18n: service init asap, avoid spamming the console as some warnings are inevitable due to async loading behavior --- Commons/I18n.qml | 7 ++++--- Commons/Settings.qml | 11 ----------- 2 files changed, 4 insertions(+), 14 deletions(-) diff --git a/Commons/I18n.qml b/Commons/I18n.qml index 23457b3d..d9fe7fee 100644 --- a/Commons/I18n.qml +++ b/Commons/I18n.qml @@ -86,8 +86,7 @@ Singleton { } } - // ------------------------------------------- - function init() { + Component.onCompleted: { Logger.log("I18n", "Service started") scanAvailableLanguages() } @@ -266,7 +265,9 @@ Singleton { interpolations = {} if (!isLoaded) { - Logger.warn("I18n", "Translations not loaded yet") + // if (debug) { + // Logger.warn("I18n", "Translations not loaded yet") + // } return key } diff --git a/Commons/Settings.qml b/Commons/Settings.qml index fd2a1ed1..7e7d1225 100644 --- a/Commons/Settings.qml +++ b/Commons/Settings.qml @@ -494,24 +494,13 @@ Singleton { // ----------------------------------------------------- // Kickoff essential services function kickOffServices() { - I18n.init() - - // Ensure our location singleton is created as soon as possible so we start fetching weather asap LocationService.init() - NightLightService.apply() - ColorSchemeService.init() - MatugenService.init() - - // Ensure wallpapers are restored after settings have been loaded WallpaperService.init() - FontService.init() - HooksService.init() - BluetoothService.init() } } From 1470a925568d489c59552af674610834ea99e78a Mon Sep 17 00:00:00 2001 From: Ly-sec Date: Wed, 24 Sep 2025 14:53:09 +0200 Subject: [PATCH 08/15] i18n: more cases detected --- Assets/Translations/de.json | 631 ++++++++++++++---- Modules/Launcher/Plugins/CalculatorPlugin.qml | 1 + .../Settings/Bar/BarWidgetSettingsDialog.qml | 1 - Modules/Settings/SettingsPanel.qml | 30 +- Widgets/NFilePicker.qml | 1 + 5 files changed, 520 insertions(+), 144 deletions(-) diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json index 3a42eefd..fdc7180d 100644 --- a/Assets/Translations/de.json +++ b/Assets/Translations/de.json @@ -6,11 +6,11 @@ "profile": { "section": { "label": "Profil", - "description": "Bearbeite deine Benutzerdaten und deinen Avatar." + "description": "Bearbeiten Sie Ihre Benutzerdaten und Ihren Avatar." }, "picture": { "label": "{user}s Profilbild", - "description": "Dein Profilbild, das überall in der Oberfläche angezeigt wird." + "description": "Ihr Profilbild, das in der gesamten Benutzeroberfläche angezeigt wird." }, "select-avatar": "Avatar-Bild auswählen" }, @@ -18,15 +18,15 @@ "ui": { "section": { "label": "Benutzeroberfläche", - "description": "Passe Aussehen, Gefühl und Verhalten der Oberfläche an." + "description": "Passen Sie das Aussehen, die Haptik und das Verhalten der Oberfläche an." }, "dim-desktop": { "label": "Desktop abdunkeln", "description": "Desktop abdunkeln, wenn Panels oder Menüs geöffnet sind." }, "border-radius": { - "label": "Eckenrundung", - "description": "Bestimmt die Rundung von Fenstern, Buttons und anderen Elementen." + "label": "Eckenradius", + "description": "Steuert die Rundung der Ecken von Fenstern, Buttons und anderen Elementen." }, "animation-speed": { "label": "Animationsgeschwindigkeit", @@ -36,39 +36,43 @@ "screen-corners": { "section": { "label": "Bildschirmecken", - "description": "Rundung und visuelle Effekte der Bildschirmecken anpassen." + "description": "Bildschirmecken-Rundung und visuelle Effekte anpassen." }, "show-corners": { "label": "Bildschirmecken anzeigen", - "description": "Gerundete Ecken am Bildschirmrand anzeigen." + "description": "Gerundete Ecken am Rand des Bildschirms anzeigen." }, "solid-black": { - "label": "Durchgehend schwarze Ecken", - "description": "Verwende durchgehend schwarz statt der Hintergrundfarbe der Statusleiste." + "label": "Schwarze Ecken", + "description": "Schwarze Ecken anstelle der Leisten-Hintergrundfarbe verwenden." + }, + "radius": { + "label": "Bildschirmecken-Radius", + "description": "Rundung der Bildschirmecken anpassen." } }, "fonts": { "section": { "label": "Schriftarten", - "description": "Wähle die Schriftarten für die gesamte Oberfläche." + "description": "Wählen Sie die in der Benutzeroberfläche verwendeten Schriftarten." }, "default": { "label": "Standard-Schriftart", - "description": "Hauptschriftart für die gesamte Oberfläche.", + "description": "Hauptschriftart für die gesamte Benutzeroberfläche.", "placeholder": "Standard-Schriftart auswählen...", - "search-placeholder": "Schriftarten durchsuchen..." + "search-placeholder": "Schriftarten suchen..." }, "monospace": { "label": "Monospace-Schriftart", - "description": "Monospace-Schriftart für Zahlen und Statistiken.", + "description": "Monospace-Schriftart für Zahlen und Statistik-Anzeigen.", "placeholder": "Monospace-Schriftart auswählen...", - "search-placeholder": "Monospace-Schriftarten durchsuchen..." + "search-placeholder": "Monospace-Schriftarten suchen..." }, "accent": { "label": "Akzent-Schriftart", - "description": "Große Schriftart für prominente Anzeigen.", + "description": "Große Schriftart für hervorgehobene Anzeigen.", "placeholder": "Display-Schriftart auswählen...", - "search-placeholder": "Display-Schriftarten durchsuchen..." + "search-placeholder": "Display-Schriftarten suchen..." } } }, @@ -76,28 +80,28 @@ "title": "Audio", "volumes": { "section": { - "label": "Lautstärke", - "description": "Lautstärke-Einstellungen und Audiopegel anpassen." + "label": "Lautstärken", + "description": "Lautstärkeregler und Audiopegel anpassen." }, "output-volume": { "label": "Ausgabe-Lautstärke", "description": "Systemweite Lautstärke." }, "mute-output": { - "label": "Audio-Ausgabe stumm", - "description": "Haupt-Audio-Ausgabe des Systems stummschalten." + "label": "Audio-Ausgabe stumm schalten", + "description": "Die Haupt-Audio-Ausgabe des Systems stumm schalten." }, "input-volume": { "label": "Eingabe-Lautstärke", - "description": "Mikrofon-Eingangslautstärke." + "description": "Mikrofon-Eingabe-Lautstärke." }, "mute-input": { - "label": "Audio-Eingabe stumm", - "description": "Standard-Audio-Eingang (Mikrofon) stummschalten." + "label": "Audio-Eingabe stumm schalten", + "description": "Die Standard-Audio-Eingabe (Mikrofon) stumm schalten." }, "step-size": { "label": "Lautstärke-Schrittgröße", - "description": "Schrittgröße für Lautstärkeänderungen (Mausrad, Tastenkürzel)." + "description": "Schrittgröße für Lautstärkeänderungen anpassen (Mausrad, Tastenkombinationen)." } }, "devices": { @@ -116,34 +120,34 @@ }, "media": { "section": { - "label": "Media Player", - "description": "Bevorzugte und ignorierte Media-Anwendungen festlegen." + "label": "Medienplayer", + "description": "Bevorzugte und ignorierte Medienanwendungen festlegen." }, "primary-player": { - "label": "Haupt-Player", - "description": "Stichwort eingeben, um deinen Haupt-Player zu identifizieren.", + "label": "Hauptplayer", + "description": "Stichwort eingeben, um Ihren Hauptplayer zu identifizieren.", "placeholder": "z.B. spotify, vlc, mpv" }, "excluded-player": { - "label": "Ausgeschlossene Player", - "description": "Stichwörter für Player hinzufügen, die das System ignorieren soll. Jedes Stichwort in eine neue Zeile.", + "label": "Ausgeschlossener Player", + "description": "Stichwörter für Player hinzufügen, die das System ignorieren soll. Jedes Stichwort sollte in einer neuen Zeile stehen.", "placeholder": "Teilstring eingeben und + drücken" }, "visualizer-type": { - "label": "Visualisierung", - "description": "Visualisierung für Media-Wiedergabe auswählen" + "label": "Visualisierungstyp", + "description": "Visualisierungstyp für Medienwiedergabe wählen" }, "frame-rate": { "label": "Bildrate", - "description": "Höhere Raten sind flüssiger, brauchen aber mehr Ressourcen." + "description": "Höhere Raten sind flüssiger, verbrauchen aber mehr Ressourcen." } } }, "display": { - "title": "Display", + "title": "Anzeige", "monitors": { "section": { - "label": "Monitor-Einstellungen", + "label": "Monitor-spezifische Einstellungen", "description": "Skalierung und Helligkeit für jeden Bildschirm anpassen." }, "scale": "Skalierung", @@ -151,17 +155,17 @@ "reset-scaling": "Skalierung zurücksetzen", "brightness-step": { "label": "Helligkeits-Schrittgröße", - "description": "Schrittgröße für Helligkeitsänderungen (Mausrad und Tastenkürzel)." + "description": "Schrittgröße für Helligkeitsänderungen anpassen (Mausrad und Tastenkombinationen)." } }, "night-light": { "section": { "label": "Nachtlicht", - "description": "Blaues Licht reduzieren für besseren Schlaf und weniger Augenbelastung." + "description": "Blaulicht-Emission reduzieren für besseren Schlaf und weniger Augenbelastung." }, "enable": { "label": "Nachtlicht aktivieren", - "description": "Warmen Farbfilter anwenden, um blaues Licht zu reduzieren." + "description": "Warmen Farbfilter anwenden, um Blaulicht-Emission zu reduzieren." }, "temperature": { "label": "Farbtemperatur", @@ -170,53 +174,53 @@ "day": "Tag" }, "auto-schedule": { - "label": "Automatische Zeiten", - "description": "Basiert auf Sonnenuntergang und -aufgang in {location} - empfohlen." + "label": "Automatische Planung", + "description": "Basierend auf Sonnenuntergang und Sonnenaufgang in {location} - empfohlen." }, "manual-schedule": { - "label": "Manuelle Zeiten", - "description": "Eigene Zeiten für Sonnenauf- und -untergang festlegen.", + "label": "Manuelle Planung", + "description": "Benutzerdefinierte Zeiten für Sonnenaufgang und Sonnenuntergang festlegen.", "sunrise": "Sonnenaufgang", "sunset": "Sonnenuntergang", "select-start": "Startzeit auswählen", "select-stop": "Endzeit auswählen" }, "force-activation": { - "label": "Sofort aktivieren", - "description": "Ignoriert den Zeitplan und wendet den Nachtfilter sofort an." + "label": "Aktivierung erzwingen", + "description": "Ignoriert die Planung und wendet den Nachtfilter sofort an." } } }, "bar": { - "title": "Statusleiste", + "title": "Leiste", "appearance": { "section": { - "label": "Aussehen", - "description": "Aussehen und Position der Statusleiste anpassen." + "label": "Erscheinungsbild", + "description": "Erscheinungsbild und Position der Leiste anpassen." }, "position": { - "label": "Statusleistenposition", - "description": "Wähle, wo die Statusleiste auf dem Bildschirm platziert wird." + "label": "Leistenposition", + "description": "Wählen Sie, wo die Leiste auf dem Bildschirm platziert werden soll." }, "density": { - "label": "Statusleistendichte", - "description": "Innenabstand der Statusleiste für kompaktes oder geräumiges Aussehen anpassen." + "label": "Leistendichte", + "description": "Innenabstand der Leiste für kompaktes oder geräumiges Aussehen anpassen." }, "background-opacity": { "label": "Hintergrund-Transparenz", - "description": "Transparenz des Statusleistenhintergrunds anpassen." + "description": "Hintergrund-Transparenz der Leiste anpassen." }, "show-capsule": { "label": "Kapsel anzeigen", "description": "Widget-Hintergründe anzeigen." }, "floating": { - "label": "Schwebende Statusleiste", - "description": "Statusleiste als schwebende 'Pille' anzeigen. Hinweis: Dadurch werden die Bildschirmecken an die Ränder verschoben." + "label": "Schwebende Leiste", + "description": "Leiste als schwebende 'Pille' anzeigen. Hinweis: Dies verschiebt die Bildschirmecken an die Ränder." }, "margins": { "label": "Ränder", - "description": "Ränder um die schwebende Statusleiste anpassen.", + "description": "Ränder um die schwebende Leiste anpassen.", "vertical": "Vertikal", "horizontal": "Horizontal" } @@ -224,13 +228,13 @@ "widgets": { "section": { "label": "Widget-Positionierung", - "description": "Widgets per Drag & Drop innerhalb jeder Sektion neu ordnen oder mit den Hinzufügen/Entfernen-Buttons verwalten." + "description": "Widgets per Drag & Drop innerhalb jeder Sektion neu anordnen oder Add/Remove-Buttons zum Verwalten verwenden." } }, "monitors": { "section": { "label": "Monitor-Anzeige", - "description": "Statusleiste auf bestimmten Monitoren anzeigen. Standard ist alle, wenn keine ausgewählt." + "description": "Leiste auf bestimmten Monitoren anzeigen. Standard ist alle, wenn keine ausgewählt sind." } } }, @@ -238,30 +242,30 @@ "title": "Dock", "appearance": { "section": { - "label": "Aussehen", - "description": "Verhalten und Aussehen des Docks anpassen." + "label": "Erscheinungsbild", + "description": "Verhalten und Erscheinungsbild des Docks anpassen." }, "auto-hide": { "label": "Automatisch ausblenden", - "description": "Automatisch ausblenden, wenn nicht verwendet." + "description": "Automatisch ausblenden, wenn nicht in Gebrauch." }, "exclusive-zone": { - "label": "Exklusivbereich", + "label": "Exklusive Zone", "description": "Fensterüberlappung verhindern." }, "background-opacity": { "label": "Hintergrund-Transparenz", - "description": "Transparenz des Dock-Hintergrunds anpassen." + "description": "Hintergrund-Transparenz des Docks anpassen." }, "floating-distance": { - "label": "Schwebeabstand", + "label": "Dock-Schwebeabstand", "description": "Schwebeabstand vom Bildschirmrand anpassen." } }, "monitors": { "section": { "label": "Monitor-Anzeige", - "description": "Monitor auswählen, auf dem das Dock angezeigt wird." + "description": "Monitor auswählen, auf dem das Dock angezeigt werden soll." } } }, @@ -269,28 +273,28 @@ "title": "Starter", "settings": { "section": { - "label": "Aussehen", - "description": "Verhalten und Aussehen des Starters anpassen." + "label": "Erscheinungsbild", + "description": "Verhalten und Erscheinungsbild des Starters anpassen." }, "position": { "label": "Position", - "description": "Wähle, wo das Starter-Panel erscheint." + "description": "Wählen Sie, wo das Starter-Panel erscheint." }, "background-opacity": { "label": "Hintergrund-Transparenz", - "description": "Transparenz des Starter-Hintergrunds anpassen." + "description": "Hintergrund-Transparenz des Starters anpassen." }, "clipboard-history": { "label": "Zwischenablage-Verlauf aktivieren", - "description": "Auf zuvor kopierte Inhalte über den Starter zugreifen." + "description": "Zugriff auf zuvor kopierte Elemente über den Starter." }, "sort-by-usage": { - "label": "Nach Nutzung sortieren", + "label": "Nach Häufigkeit sortieren", "description": "Wenn aktiviert, erscheinen häufig gestartete Apps zuerst in der Liste." }, "use-app2unit": { - "label": "App2Unit zum Starten verwenden", - "description": "Verwendet eine alternative Startmethode für bessere Prozessverwaltung und weniger Probleme." + "label": "App2Unit zum Starten von Anwendungen verwenden", + "description": "Verwendet eine alternative Startmethode zur besseren Verwaltung von App-Prozessen und Problemvermeidung." } } }, @@ -298,8 +302,8 @@ "title": "Benachrichtigungen", "settings": { "section": { - "label": "Aussehen", - "description": "Aussehen und Verhalten von Benachrichtigungen konfigurieren." + "label": "Erscheinungsbild", + "description": "Erscheinungsbild und Verhalten von Benachrichtigungen konfigurieren." }, "do-not-disturb": { "label": "Nicht stören", @@ -314,20 +318,20 @@ "description": "Wo Benachrichtigungen auf dem Bildschirm erscheinen." }, "low-urgency": { - "label": "Niedrige Priorität", + "label": "Niedrige Dringlichkeit", "description": "Wie lange Benachrichtigungen niedriger Priorität sichtbar bleiben." }, "normal-urgency": { - "label": "Normale Priorität", + "label": "Normale Dringlichkeit", "description": "Wie lange Benachrichtigungen normaler Priorität sichtbar bleiben." }, "critical-urgency": { - "label": "Kritische Priorität", + "label": "Kritische Dringlichkeit", "description": "Wie lange kritische Benachrichtigungen sichtbar bleiben." }, "monitors-display": { "label": "Monitor-Anzeige", - "description": "Benachrichtigungen auf bestimmten Monitoren anzeigen. Standard ist alle, wenn keine ausgewählt." + "description": "Benachrichtigungen auf bestimmten Monitoren anzeigen. Standard ist alle, wenn keine ausgewählt sind." } } }, @@ -336,36 +340,36 @@ "settings": { "section": { "label": "Hintergrundbild-Einstellungen", - "description": "Verwaltung und Anzeige von Hintergrundbildern steuern." + "description": "Steuern Sie, wie Hintergrundbilder verwaltet und angezeigt werden." }, "enable-management": { "label": "Hintergrundbild-Verwaltung aktivieren", - "description": "Hintergrundbilder mit Noctalia verwalten. Deaktivieren, wenn du eine andere Anwendung bevorzugst." + "description": "Hintergrundbilder mit Noctalia verwalten. Deaktivieren, wenn Sie eine andere Anwendung bevorzugen." }, "folder": { "label": "Hintergrundbild-Ordner", - "description": "Pfad zu deinem Haupt-Hintergrundbild-Ordner.", + "description": "Pfad zu Ihrem Haupt-Hintergrundbild-Ordner.", "tooltip": "Nach Hintergrundbild-Ordner suchen" }, "monitor-specific": { "label": "Monitor-spezifische Verzeichnisse", - "description": "Anderen Hintergrundbild-Ordner für jeden Monitor festlegen.", - "tooltip": "Nach Monitor-Hintergrundbild-Ordner suchen" + "description": "Unterschiedlichen Hintergrundbild-Ordner für jeden Monitor festlegen.", + "tooltip": "Nach Hintergrundbild-Ordner suchen" }, "select-folder": "Hintergrundbild-Ordner auswählen", "select-monitor-folder": "Monitor-Hintergrundbild-Ordner auswählen" }, "look-feel": { "section": { - "label": "Aussehen" + "label": "Aussehen & Verhalten" }, "fill-mode": { "label": "Füllmodus", - "description": "Wähle, wie das Bild an die Auflösung deines Monitors angepasst werden soll." + "description": "Wählen Sie, wie das Bild skaliert werden soll, um zur Auflösung Ihres Monitors zu passen." }, "fill-color": { "label": "Füllfarbe", - "description": "Wähle eine Füllfarbe, die hinter dem Hintergrundbild erscheinen kann." + "description": "Füllfarbe wählen, die hinter dem Hintergrundbild erscheinen kann." }, "transition-type": { "label": "Übergangstyp", @@ -377,7 +381,7 @@ }, "edge-smoothness": { "label": "Übergangskante weichzeichnen", - "description": "Wendet einen weichen, ausgefransten Effekt auf die Kante der Übergänge an." + "description": "Wendet einen weichen, gefiederten Effekt auf die Kante von Übergängen an." } }, "automation": { @@ -386,14 +390,14 @@ }, "random-wallpaper": { "label": "Zufälliges Hintergrundbild", - "description": "Plane zufällige Hintergrundbild-Wechsel in regelmäßigen Abständen." + "description": "Zufällige Hintergrundbild-Wechsel in regelmäßigen Abständen planen." }, "interval": { "label": "Hintergrundbild-Intervall", - "description": "Wie oft Hintergrundbilder automatisch gewechselt werden." + "description": "Wie oft Hintergrundbilder automatisch gewechselt werden sollen." }, "custom-interval": { - "label": "Eigenes Intervall", + "label": "Benutzerdefiniertes Intervall", "description": "Zeit als HH:MM eingeben (z.B. 01:30)." } } @@ -407,17 +411,17 @@ }, "dark-mode": { "label": "Dunkler Modus", - "description": "Wechselt zu einem dunkleren Design für angenehmeres Sehen bei Nacht." + "description": "Wechselt zu einem dunkleren Theme für einfachere Betrachtung bei Nacht." }, "enable-matugen": { "label": "Matugen aktivieren", - "description": "Automatisch Farben basierend auf deinem aktiven Hintergrundbild generieren." + "description": "Automatisch Farben basierend auf Ihrem aktiven Hintergrundbild generieren." } }, "predefined": { "section": { "label": "Vordefinierte Farbschemata", - "description": "Um diese Farbschemata zu verwenden, musst du Matugen deaktivieren. Mit aktiviertem Matugen werden Farben automatisch aus deinem Hintergrundbild generiert." + "description": "Um diese Farbschemata zu verwenden, müssen Sie Matugen ausschalten. Mit aktiviertem Matugen werden Farben automatisch aus Ihrem Hintergrundbild generiert." } }, "matugen": { @@ -451,17 +455,17 @@ "kitty": { "label": "Kitty", "description": "Schreibt ~/.config/kitty/themes/noctalia.conf und lädt neu", - "description-missing": "Erfordert installiertes kitty Terminal" + "description-missing": "Erfordert kitty Terminal" }, "ghostty": { "label": "Ghostty", "description": "Schreibt ~/.config/ghostty/themes/noctalia und lädt neu", - "description-missing": "Erfordert installiertes ghostty Terminal" + "description-missing": "Erfordert ghostty Terminal" }, "foot": { "label": "Foot", "description": "Schreibt ~/.config/foot/themes/noctalia und lädt neu", - "description-missing": "Erfordert installiertes foot Terminal" + "description-missing": "Erfordert foot Terminal" } }, "programs": { @@ -470,22 +474,22 @@ "fuzzel": { "label": "Fuzzel", "description": "Schreibt ~/.config/fuzzel/themes/noctalia und lädt neu", - "description-missing": "Erfordert installierten fuzzel Launcher" + "description-missing": "Erfordert fuzzel Starter" }, "vesktop": { "label": "Vesktop", "description": "Schreibt ~/.config/vesktop/themes/noctalia.theme.css", - "description-missing": "Erfordert installierten vesktop Discord-Client" + "description-missing": "Erfordert vesktop Discord-Client" }, "pywalfox": { "label": "Pywalfox (Firefox)", "description": "Schreibt ~/.cache/wal/colors.json und führt pywalfox update aus", - "description-missing": "Erfordert installiertes pywalfox Paket" + "description-missing": "Erfordert pywalfox Paket" } }, "misc": { - "label": "Sonstiges", - "description": "Weitere Konfigurationsoptionen.", + "label": "Verschiedenes", + "description": "Zusätzliche Konfigurationsoptionen.", "user-templates": { "label": "Benutzer-Vorlagen", "description": "Benutzerdefinierte Matugen-Konfiguration aus ~/.config/matugen/config.toml aktivieren" @@ -497,19 +501,19 @@ "title": "Standort", "location": { "section": { - "label": "Dein Standort", - "description": "Genaues Wetter und Nachtlicht-Zeitplan durch Festlegen deines Standorts erhalten." + "label": "Ihr Standort", + "description": "Genaues Wetter und Nachtlicht-Planung durch Festlegung Ihres Standorts erhalten." }, "search": { - "label": "Nach Standort suchen", - "description": "z.B. Berlin, DE", - "placeholder": "Ortsnamen eingeben" + "label": "Nach einem Standort suchen", + "description": "z.B. Berlin, Deutschland", + "placeholder": "Standortnamen eingeben" } }, "weather": { "section": { "label": "Wetter", - "description": "Wähle deine bevorzugte Temperatureinheit." + "description": "Bevorzugte Temperatureinheit wählen." }, "fahrenheit": { "label": "Temperatur in Fahrenheit (°F) anzeigen", @@ -519,10 +523,10 @@ "date-time": { "section": { "label": "Datum & Zeit", - "description": "Anpassen, wie Datum und Zeit angezeigt werden." + "description": "Anpassen, wie Datum und Zeit erscheinen." }, "12hour-format": { - "label": "12-Stunden-Format auf dem Sperrbildschirm verwenden", + "label": "12-Stunden-Zeitformat auf dem Sperrbildschirm verwenden", "description": "An für AM/PM-Format (z.B. 8:00 PM), aus für 24-Stunden-Format (z.B. 20:00)." }, "week-numbers": { @@ -534,21 +538,21 @@ "network": { "title": "Netzwerk", "section": { - "description": "Wi-Fi- und Bluetooth-Verbindungen verwalten." + "description": "WLAN- und Bluetooth-Verbindungen verwalten." }, "wifi": { - "label": "Wi-Fi aktivieren" + "label": "WLAN aktivieren" }, "bluetooth": { "label": "Bluetooth aktivieren" } }, "screen-recorder": { - "title": "Bildschirmaufnahme", + "title": "Bildschirmrekorder", "general": { "section": { "label": "Allgemeine Einstellungen", - "description": "Ausgabe und Inhalt der Bildschirmaufnahme verwalten." + "description": "Bildschirmaufnahme-Ausgabe und -Inhalt verwalten." }, "output-folder": { "label": "Ausgabe-Ordner", @@ -564,11 +568,11 @@ "video": { "section": { "label": "Video-Einstellungen", - "description": "Video-Aufnahmeoptionen konfigurieren." + "description": "Video-Aufnahme-Optionen konfigurieren." }, "video-source": { "label": "Video-Quelle", - "description": "Portal wird empfohlen, bei Artefakten versuche Screen." + "description": "Portal wird empfohlen, bei Artefakten versuchen Sie Bildschirm." }, "frame-rate": { "label": "Bildrate", @@ -576,11 +580,11 @@ }, "video-quality": { "label": "Video-Qualität", - "description": "Höhere Qualität führt zu größeren Dateien." + "description": "Höhere Qualität führt zu größeren Dateigrößen." }, "video-codec": { "label": "Video-Codec", - "description": "h264 ist der gängigste Codec." + "description": "h264 ist der gebräuchlichste Codec." }, "color-range": { "label": "Farbbereich", @@ -590,7 +594,7 @@ "audio": { "section": { "label": "Audio-Einstellungen", - "description": "Audio-Aufnahmeoptionen konfigurieren." + "description": "Audio-Aufnahme-Optionen konfigurieren." }, "audio-source": { "label": "Audio-Quelle", @@ -598,7 +602,7 @@ }, "audio-codec": { "label": "Audio-Codec", - "description": "Opus wird für beste Performance und kleinste Audio-Dateigröße empfohlen." + "description": "Opus wird für beste Leistung und kleinste Audio-Größe empfohlen." } } }, @@ -607,7 +611,7 @@ "noctalia": { "section": { "label": "Noctalia Shell", - "description": "Eine schlanke und minimalistische Desktop-Shell, durchdacht für Wayland entwickelt, gebaut mit Quickshell." + "description": "Eine elegante und minimalistische Desktop-Shell, sorgfältig für Wayland entwickelt, gebaut mit Quickshell." }, "latest-version": "Neueste Version:", "installed-version": "Installierte Version:", @@ -616,8 +620,8 @@ "contributors": { "section": { "label": "Mitwirkende", - "description": "Shoutout an unseren {count} großartigen Mitwirkenden!", - "description_plural": "Shoutout an unsere {count} großartigen Mitwirkenden!" + "description": "Ein Dankeschön an unseren {count} großartigen Mitwirkenden!", + "description_plural": "Ein Dankeschön an unsere {count} großartigen Mitwirkenden!" } } }, @@ -635,22 +639,22 @@ }, "wallpaper-changed": { "label": "Hintergrundbild geändert", - "description": "Befehl, der ausgeführt wird, wenn das Hintergrundbild wechselt.", + "description": "Befehl, der ausgeführt wird, wenn sich das Hintergrundbild ändert.", "placeholder": "z.B. notify-send \"Hintergrundbild\" \"Geändert\"" }, "theme-changed": { - "label": "Design geändert", - "description": "Befehl, der ausgeführt wird, wenn zwischen dunklem und hellem Modus gewechselt wird.", - "placeholder": "z.B. notify-send \"Design\" \"Gewechselt\"" + "label": "Theme geändert", + "description": "Befehl, der ausgeführt wird, wenn das Theme zwischen dunklem und hellem Modus wechselt.", + "placeholder": "z.B. notify-send \"Theme\" \"Gewechselt\"" }, "info": { "command-info": { "label": "Hook-Befehl-Informationen", - "description": "• Befehle werden über Shell ausgeführt (sh -c)\n• Befehle laufen im Hintergrund (detached)\n• Test-Buttons führen mit aktuellen Werten aus" + "description": "• Befehle werden über Shell ausgeführt (sh -c)\n• Befehle laufen im Hintergrund (getrennt)\n• Test-Buttons führen mit aktuellen Werten aus" }, "parameters": { "label": "Verfügbare Parameter", - "description": "• Hintergrundbild-Hook: $1 = Hintergrundbild-Pfad, $2 = Bildschirmname\n• Design-Wechsel-Hook: $1 = true/false (Dunkler-Modus-Status)" + "description": "• Hintergrundbild-Hook: $1 = Hintergrundbild-Pfad, $2 = Bildschirmname\n• Theme-Wechsel-Hook: $1 = true/false (Dunkelmodus-Status)" } } } @@ -736,5 +740,376 @@ "cancel": "Abbrechen", "apply": "Anwenden" } + }, + "bar": { + "widget-settings": { + "dialog": { + "cancel": "Abbrechen", + "apply": "Anwenden" + }, + "section-editor": { + "placeholder": "Widget auswählen..." + }, + "active-window": { + "show-app-icon": "App-Symbol anzeigen" + }, + "system-monitor": { + "cpu-usage": "CPU-Auslastung", + "cpu-temperature": "CPU-Temperatur", + "memory-usage": "Speicherverbrauch", + "memory-percentage": "Speicher als Prozentsatz", + "network-traffic": "Netzwerkverkehr", + "storage-usage": "Speichernutzung" + }, + "notification-history": { + "show-unread-badge": "Badge für ungelesene Nachrichten anzeigen", + "hide-badge-when-zero": "Badge ausblenden, wenn null" + }, + "battery": { + "display-mode": { + "label": "Anzeigemodus", + "description": "Wählen Sie, wie dieser Wert angezeigt werden soll." + }, + "low-battery-threshold": { + "label": "Schwellenwert für niedrigen Batteriestand", + "description": "Warnung anzeigen, wenn Batterie unter diesen Prozentsatz fällt." + } + }, + "control-center": { + "use-distro-logo": "Distro-Logo anstelle von Symbol verwenden", + "icon": { + "label": "Symbol", + "description": "Symbol aus der Bibliothek oder eine benutzerdefinierte Datei auswählen." + }, + "browse-library": "Bibliothek durchsuchen", + "browse-file": "Datei durchsuchen", + "select-custom-icon": "Benutzerdefiniertes Symbol auswählen" + }, + "keyboard-layout": { + "display-mode": { + "label": "Anzeigemodus", + "description": "Wählen Sie, wie dieser Wert angezeigt werden soll." + } + }, + "volume": { + "display-mode": { + "label": "Anzeigemodus", + "description": "Wählen Sie, wie dieser Wert angezeigt werden soll." + } + }, + "workspace": { + "label-mode": "Beschriftungsmodus", + "hide-unoccupied": { + "label": "Unbesetzte ausblenden", + "description": "Arbeitsbereiche ohne Fenster nicht anzeigen." + } + }, + "microphone": { + "display-mode": { + "label": "Anzeigemodus", + "description": "Wählen Sie, wie dieser Wert angezeigt werden soll." + } + }, + "brightness": { + "display-mode": { + "label": "Anzeigemodus", + "description": "Wählen Sie, wie dieser Wert angezeigt werden soll." + } + }, + "spacer": { + "width": { + "label": "Breite", + "description": "Abstandsbreite in Pixeln" + } + }, + "custom-button": { + "icon": { + "label": "Symbol", + "description": "Symbol aus der Bibliothek auswählen." + }, + "browse": "Durchsuchen", + "left-click": "Linksklick", + "right-click": "Rechtsklick", + "middle-click": "Mittelklick", + "dynamic-text": "Dynamischer Text", + "display-command-output": { + "label": "Befehlsausgabe anzeigen", + "description": "Befehl eingeben, der in regelmäßigen Abständen ausgeführt wird. Die erste Zeile seiner Ausgabe wird als Text angezeigt." + }, + "refresh-interval": { + "label": "Aktualisierungsintervall", + "description": "Intervall in Millisekunden." + } + }, + "media-mini": { + "show-album-art": "Albumcover anzeigen", + "show-visualizer": "Visualizer anzeigen", + "visualizer-type": "Visualizer-Typ" + }, + "clock": { + "use-primary-color": { + "label": "Primärfarbe verwenden", + "description": "Wenn aktiviert, wird die Primärfarbe zur Hervorhebung angewendet." + }, + "use-monospaced-font": { + "label": "Monospace-Schriftart verwenden", + "description": "Wenn aktiviert, verwendet die Uhr die Monospace-Schriftart." + }, + "clock-display": { + "label": "Uhrenanzeige", + "description": "Passen Sie die Anzeige Ihrer Uhr an, indem Sie Token aus der Liste unten hinzufügen. Um das 12-Stunden-Format zu verwenden, müssen Sie das 'AP'-Token einschließen." + }, + "horizontal-bar": { + "label": "Horizontale Leiste", + "description": "Tipp: Verwenden Sie \\n, um einen Zeilenumbruch zu erstellen." + }, + "vertical-bar": { + "label": "Vertikale Leiste", + "description": "Verwenden Sie ein Leerzeichen, um jeden Teil in eine neue Zeile zu trennen." + }, + "preview": "Vorschau" + } + } + }, + "notifications": { + "panel": { + "title": "Benachrichtigungen", + "no-notifications": "Keine Benachrichtigungen", + "description": "Ihre Benachrichtigungen werden hier angezeigt, sobald sie eintreffen." + } + }, + "wallpaper": { + "panel": { + "title": "Hintergrundbild-Auswahl", + "apply-all-monitors": { + "label": "Auf alle Monitore anwenden", + "description": "Ausgewähltes Hintergrundbild auf alle Monitore gleichzeitig anwenden." + }, + "search": "Suchen:" + } + }, + "bluetooth": { + "panel": { + "title": "Bluetooth", + "disabled": "Bluetooth ist deaktiviert", + "enable-message": "Aktivieren Sie Bluetooth, um verfügbare Geräte zu sehen.", + "connected-devices": "Verbundene Geräte", + "known-devices": "Bekannte Geräte", + "available-devices": "Verfügbare Geräte", + "scanning": "Scannen nach Geräten...", + "pairing-mode": "Stellen Sie sicher, dass sich Ihr Gerät im Kopplungsmodus befindet." + } + }, + "wifi": { + "panel": { + "title": "WLAN", + "disabled": "WLAN ist deaktiviert", + "enable-message": "Aktivieren Sie WLAN, um verfügbare Netzwerke zu sehen.", + "searching": "Suche nach nahegelegenen Netzwerken...", + "connected": "Verbunden", + "disconnecting": "Verbindung wird getrennt...", + "forgetting": "Wird vergessen...", + "saved": "Gespeichert", + "disconnect": "Trennen", + "enter-password": "Passwort eingeben...", + "connect": "Verbinden", + "password": "Passwort", + "forget-network": "Dieses Netzwerk vergessen?", + "forget": "Vergessen", + "no-networks": "Keine Netzwerke gefunden", + "scan-again": "Erneut scannen" + } + }, + "calendar": { + "panel": { + "week": "Woche" + } + }, + "tooltips": { + "refresh": "Aktualisieren", + "close": "Schließen", + "refresh-wallpaper-list": "Hintergrundbild-Liste aktualisieren", + "refresh-devices": "Geräte aktualisieren", + "forget-network": "Netzwerk vergessen", + "clear-history": "Verlauf löschen", + "delete-notification": "Benachrichtigung löschen", + "previous-month": "Vorheriger Monat", + "next-month": "Nächster Monat", + "add-widget": "Widget hinzufügen", + "widget-settings": "Widget-Einstellungen", + "remove-widget": "Widget entfernen", + "move-to-left-section": "Zur linken Sektion verschieben", + "move-to-center-section": "Zur mittleren Sektion verschieben", + "move-to-right-section": "Zur rechten Sektion verschieben", + "open-settings": "Einstellungen öffnen", + "session-menu": "Sitzungsmenü", + "close-side-panel": "Seitenpanel schließen", + "cancel-timer": "Timer abbrechen", + "start-screen-recording": "Bildschirmaufnahme starten", + "stop-screen-recording": "Bildschirmaufnahme stoppen", + "screen-recorder-not-installed": "Bildschirmrekorder ist nicht installiert", + "enable-keep-awake": "Wach bleiben aktivieren", + "disable-keep-awake": "Wach bleiben deaktivieren", + "wallpaper-selector": "Linksklick: Hintergrundbild-Auswahl öffnen.\\nRechtsklick: Zufälliges Hintergrundbild setzen.", + "do-not-disturb-enabled": "'Nicht stören' aktiviert", + "do-not-disturb-disabled": "'Nicht stören' deaktiviert", + "connect-disconnect-devices": "Linksklick zum Verbinden. Rechtsklick zum Vergessen.", + "set-power-profile": "'{profile}' Energieprofil setzen", + "switch-to-light-mode": "Zum hellen Modus wechseln", + "switch-to-dark-mode": "Zum dunklen Modus wechseln", + "night-light-disabled": "Nachtlicht ist deaktiviert.\\nLinksklick zum Wechseln des Modus.\\nRechtsklick für Einstellungen.", + "night-light-enabled": "Nachtlicht ist aktiviert.\\nLinksklick zum Wechseln des Modus.\\nRechtsklick für Einstellungen.", + "night-light-forced": "Nachtlicht ist erzwungen.\\nLinksklick zum Wechseln des Modus.\\nRechtsklick für Einstellungen.", + "click-to-start-recording": "Klicken zum Starten der Aufnahme", + "click-to-stop-recording": "Klicken zum Stoppen der Aufnahme", + "open-side-panel": "Seitenpanel öffnen", + "volume-at": "Lautstärke bei {volume}%\\nLinksklick zum Stumm-/Lautschalten. Rechtsklick für Einstellungen.\\nScrollen zum Ändern der Lautstärke.", + "microphone-volume-at": "Mikrofon-Lautstärke bei {volume}%\\nLinksklick zum Stumm-/Lautschalten. Rechtsklick für Einstellungen.\\nScrollen zum Ändern der Lautstärke.", + "manage-wifi": "WLAN verwalten", + "bluetooth-devices": "Bluetooth-Geräte", + "open-notification-history-enable-dnd": "Benachrichtigungsverlauf öffnen\\nRechtsklick um 'Nicht stören' zu aktivieren.", + "open-notification-history-disable-dnd": "Benachrichtigungsverlauf öffnen\\nRechtsklick um 'Nicht stören' zu deaktivieren.", + "open-wallpaper-selector": "Hintergrundbild-Auswahl öffnen", + "previous-media": "Vorheriges Medium", + "pause": "Pausieren", + "play": "Wiedergeben", + "next-media": "Nächstes Medium", + "power-profile": "'{profile}' Energieprofil", + "keyboard-layout": "{layout} Tastaturlayout" + }, + "clock": { + "tooltip": "Kalender öffnen" + }, + "dock": { + "menu": { + "focus": "Fokussieren", + "pin": "Anheften", + "unpin": "Lösen", + "close": "Schließen" + } + }, + "placeholders": { + "search-icons": "z.B. noctalia, niri, battery, cloud", + "profile-picture-path": "/home/benutzer/.face", + "enter-width-pixels": "Breite in Pixeln eingeben", + "enter-command": "Befehl eingeben (App oder benutzerdefiniertes Skript)", + "command-example": "echo \"Hallo Welt\"", + "clock-horizontal": "HH:mm ddd, MMM dd", + "clock-vertical": "HH mm dd MM", + "search-wallpapers": "Zum Filtern von Hintergrundbildern eingeben...", + "search-launcher": "Einträge suchen... oder > für Befehle verwenden", + "search": "Suchen...", + "select": "Auswählen", + "cancel": "Abbrechen", + "test": "Test" + }, + "options": { + "display-mode": { + "on-hover": "Beim Darüberfahren", + "always-show": "Immer anzeigen", + "always-hide": "Immer ausblenden", + "force-open": "Erzwingen" + }, + "workspace-labels": { + "none": "Keine", + "index": "Index", + "name": "Name" + }, + "visualizer-types": { + "none": "Keine", + "linear": "Linear", + "mirrored": "Gespiegelt", + "wave": "Welle" + }, + "frame-rates": { + "30-fps": "30 FPS", + "60-fps": "60 FPS", + "100-fps": "100 FPS", + "120-fps": "120 FPS", + "144-fps": "144 FPS", + "165-fps": "165 FPS", + "240-fps": "240 FPS" + }, + "screen-recording": { + "sources": { + "portal": "Portal", + "screen": "Bildschirm" + }, + "quality": { + "medium": "Mittel", + "high": "Hoch", + "very-high": "Sehr hoch", + "ultra": "Ultra" + }, + "codecs": { + "h264": "H264", + "hevc": "HEVC", + "av1": "AV1", + "vp8": "VP8", + "vp9": "VP9" + }, + "color-range": { + "limited": "Begrenzt", + "full": "Vollständig" + }, + "audio-sources": { + "system-output": "System-Ausgabe", + "microphone-input": "Mikrofon-Eingabe", + "both": "System-Ausgabe + Mikrofon-Eingabe" + }, + "audio-codecs": { + "opus": "Opus", + "aac": "AAC" + } + } + }, + "session-menu": { + "lock": "Sperren", + "suspend": "Ruhezustand", + "reboot": "Neu starten", + "logout": "Abmelden", + "shutdown": "Herunterfahren" + }, + "plugins": { + "applications": "Anwendungen", + "clipboard": "Zwischenablage-Verlauf", + "calculator": "Rechner", + "clipboard-search-description": "Zwischenablage-Verlauf durchsuchen", + "clipboard-clear-description": "Gesamten Zwischenablage-Verlauf löschen", + "clipboard-history-disabled": "Zwischenablage-Verlauf deaktiviert", + "clipboard-history-disabled-description": "Zwischenablage-Verlauf in den Einstellungen aktivieren oder cliphist installieren", + "clipboard-clear-history": "Zwischenablage-Verlauf löschen", + "clipboard-clear-description-full": "Alle Elemente aus dem Zwischenablage-Verlauf entfernen", + "clipboard-loading": "Lade Zwischenablage-Verlauf...", + "clipboard-loading-description": "Bitte warten", + "calculator-description": "Rechner - mathematische Ausdrücke auswerten", + "calculator-name": "Rechner", + "calculator-enter-expression": "Mathematischen Ausdruck eingeben", + "calculator-error": "Fehler" + }, + "system": { + "uptime": "System-Laufzeit: {uptime}", + "welcome-back": "Willkommen zurück, {user}!", + "monitor-description": "{model} ({width}x{height})", + "scaling-percentage": "{percentage}%", + "location-display": "{name} ({coordinates})", + "signal-strength": "{signal}%", + "cpu-temperature": "{temp}°C", + "disk-usage": "{percent}%", + "widget-settings-title": "{widget} Einstellungen", + "unknown-app": "Unbekannte App", + "no-media-player-detected": "Kein Mediaplayer erkannt", + "user-requested": "Vom Benutzer angefordert", + "unknown": "Unbekannt", + "unknown-version": "Unbekannt", + "unknown-layout": "Unbekannt" + }, + "lock-screen": { + "secure-terminal": "SICHERES TERMINAL", + "unlock-command": "sudo unlock-session", + "password": "Passwort:", + "shut-down": "Herunterfahren", + "restart": "Neu starten", + "suspend": "Ruhezustand" } } \ No newline at end of file diff --git a/Modules/Launcher/Plugins/CalculatorPlugin.qml b/Modules/Launcher/Plugins/CalculatorPlugin.qml index d3573b72..e33152a1 100644 --- a/Modules/Launcher/Plugins/CalculatorPlugin.qml +++ b/Modules/Launcher/Plugins/CalculatorPlugin.qml @@ -1,5 +1,6 @@ import QtQuick import qs.Services +import qs.Commons import "../../../Helpers/AdvancedMath.js" as AdvancedMath Item { diff --git a/Modules/Settings/Bar/BarWidgetSettingsDialog.qml b/Modules/Settings/Bar/BarWidgetSettingsDialog.qml index 09165a07..cc7fe1f9 100644 --- a/Modules/Settings/Bar/BarWidgetSettingsDialog.qml +++ b/Modules/Settings/Bar/BarWidgetSettingsDialog.qml @@ -5,7 +5,6 @@ import QtQuick.Layouts import qs.Commons import qs.Widgets import qs.Services -import "./WidgetSettings" as WidgetSettings // Widget Settings Dialog Component Popup { diff --git a/Modules/Settings/SettingsPanel.qml b/Modules/Settings/SettingsPanel.qml index 0513033f..e29234d0 100644 --- a/Modules/Settings/SettingsPanel.qml +++ b/Modules/Settings/SettingsPanel.qml @@ -3,7 +3,7 @@ import QtQuick.Controls import QtQuick.Layouts import Quickshell import Quickshell.Wayland -import qs.Modules.Settings.Tabs as Tabs +import qs.Modules.Settings.Tabs import qs.Commons import qs.Services import qs.Widgets @@ -52,59 +52,59 @@ NPanel { Component { id: generalTab - Tabs.GeneralTab {} + GeneralTab {} } Component { id: launcherTab - Tabs.LauncherTab {} + LauncherTab {} } Component { id: barTab - Tabs.BarTab {} + BarTab {} } Component { id: audioTab - Tabs.AudioTab {} + AudioTab {} } Component { id: displayTab - Tabs.DisplayTab {} + DisplayTab {} } Component { id: networkTab - Tabs.NetworkTab {} + NetworkTab {} } Component { id: locationTab - Tabs.LocationTab {} + LocationTab {} } Component { id: colorSchemeTab - Tabs.ColorSchemeTab {} + ColorSchemeTab {} } Component { id: wallpaperTab - Tabs.WallpaperTab {} + WallpaperTab {} } Component { id: screenRecorderTab - Tabs.ScreenRecorderTab {} + ScreenRecorderTab {} } Component { id: aboutTab - Tabs.AboutTab {} + AboutTab {} } Component { id: hooksTab - Tabs.HooksTab {} + HooksTab {} } Component { id: dockTab - Tabs.DockTab {} + DockTab {} } Component { id: notificationsTab - Tabs.NotificationsTab {} + NotificationsTab {} } // Order *DOES* matter diff --git a/Widgets/NFilePicker.qml b/Widgets/NFilePicker.qml index 608fde9f..e96cd561 100644 --- a/Widgets/NFilePicker.qml +++ b/Widgets/NFilePicker.qml @@ -2,6 +2,7 @@ import QtCore import QtQuick import QtQuick.Dialogs import QtQuick.Controls +import qs.Commons import qs.Services Item { From 5de4330199e409828fd5ac342c0fa16801dd9440 Mon Sep 17 00:00:00 2001 From: Ly-sec Date: Wed, 24 Sep 2025 15:31:11 +0200 Subject: [PATCH 09/15] i18n: even more things appeared --- Assets/Translations/de.json | 67 +++++++ Assets/Translations/en.json | 146 +++++++++++++- Bin/check-i18n.sh | 65 ------- Modules/Bar/Widgets/Battery.qml | 4 +- Modules/Notification/Notification.qml | 2 +- .../Notification/NotificationHistoryPanel.qml | 2 +- Modules/SessionMenu/SessionMenu.qml | 11 +- Modules/Settings/Tabs/BarTab.qml | 55 +++--- Modules/Settings/Tabs/ColorSchemeTab.qml | 6 +- Modules/Settings/Tabs/DisplayTab.qml | 6 +- Modules/Settings/Tabs/LauncherTab.qml | 52 +++-- Modules/Settings/Tabs/NotificationsTab.qml | 45 ++--- Modules/Settings/Tabs/ScreenRecorderTab.qml | 179 ++++++++---------- Modules/Wallpaper/WallpaperPanel.qml | 4 +- Services/AudioService.qml | 4 +- Services/BluetoothService.qml | 4 +- Services/ClipboardService.qml | 2 +- Services/IPCService.qml | 4 +- Services/IdleInhibitorService.qml | 4 +- Services/NetworkService.qml | 12 +- Services/NightLightService.qml | 4 +- Services/NotificationService.qml | 2 +- Services/PowerProfileService.qml | 4 +- Services/ScreenRecorderService.qml | 14 +- Widgets/NFilePicker.qml | 2 +- 25 files changed, 402 insertions(+), 298 deletions(-) delete mode 100644 Bin/check-i18n.sh diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json index fdc7180d..b3d0b367 100644 --- a/Assets/Translations/de.json +++ b/Assets/Translations/de.json @@ -1064,6 +1064,9 @@ } }, "session-menu": { + "title": "Sitzungsmenü", + "click-again": "Erneut klicken für sofortige Ausführung", + "action-in-seconds": "{action} in {seconds} Sekunden...", "lock": "Sperren", "suspend": "Ruhezustand", "reboot": "Neu starten", @@ -1111,5 +1114,69 @@ "shut-down": "Herunterfahren", "restart": "Neu starten", "suspend": "Ruhezustand" + }, + "toast": { + "night-light": { + "enabled": "Aktiviert", + "disabled": "Deaktiviert", + "not-installed": "wlsunset nicht installiert", + "forced": "Aktivierung erzwungen", + "normal": "Normaler Modus" + }, + "keep-awake": { + "enabled": "Aktiviert", + "disabled": "Deaktiviert" + }, + "matugen": { + "enabled": "Aktiviert", + "disabled": "Deaktiviert", + "not-installed": "Nicht installiert" + }, + "recording": { + "stopping": "Aufnahme wird gestoppt…", + "started": "Aufnahme gestartet", + "saved": "Aufnahme gespeichert", + "failed-start": "Aufnahme konnte nicht gestartet werden", + "failed-gpu": "gpu-screen-recorder unerwartet beendet.", + "failed-general": "Der Rekorder wurde mit einem Fehler beendet.", + "no-portals": "Desktop-Portale laufen nicht", + "no-portals-desc": "Starten Sie xdg-desktop-portal und ein Compositor-Portal (wlr/hyprland/gnome/kde)." + }, + "clipboard": { + "unavailable": "Zwischenablage-Verlauf nicht verfügbar", + "unavailable-desc": "Die 'cliphist' Anwendung ist nicht installiert. Bitte installieren Sie sie, um Zwischenablage-Verlauf-Features zu nutzen." + }, + "ipc": { + "powerpanel-deprecated": "PowerPanel wurde in SessionMenu umbenannt, dieser IPC-Aufruf wird bald veraltet sein. Bitte verwenden Sie stattdessen \"ipc call sessionMenu toggle\".", + "sidepanel-deprecated": "SidePanel wurde in ControlCenter umbenannt, dieser IPC-Aufruf wird bald veraltet sein. Bitte verwenden Sie stattdessen \"ipc call controlCenter toggle\"." + }, + "wifi": { + "enabled": "Aktiviert", + "disabled": "Deaktiviert", + "connected": "Verbunden mit '{ssid}'", + "disconnected": "Getrennt von '{ssid}'" + }, + "bluetooth": { + "enabled": "Aktiviert", + "disabled": "Deaktiviert" + }, + "do-not-disturb": { + "enabled": "'Nicht stören' aktiviert", + "disabled": "'Nicht stören' deaktiviert", + "enabled-desc": "Sie finden diese Benachrichtigungen in Ihrem Verlauf.", + "disabled-desc": "Alle Benachrichtigungen werden angezeigt." + }, + "power-profile": { + "changed": "Energieprofil geändert", + "profile-name": "\"{profile}\"" + }, + "audio": { + "muted": "Stummgeschaltet", + "unmuted": "Lautgeschaltet" + }, + "battery": { + "low": "Niedriger Batteriestand", + "low-desc": "Batterie ist bei {percent}%. Bitte schließen Sie das Ladegerät an." + } } } \ No newline at end of file diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index dcc0c456..2430106f 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -663,6 +663,10 @@ "tooltip": { "placeholder": "Placeholder" }, + "file-picker": { + "select-folder": "Select Folder", + "select-file": "Select File" + }, "datetime-tokens": { "common": { "12hour-time-minutes": "12-hour time with minutes", @@ -886,7 +890,25 @@ "description": "Apply selected wallpaper to all monitors at once." }, "search": "Search:" - } + }, + "transitions": { + "none": "None", + "random": "Random", + "fade": "Fade", + "disc": "Disc", + "stripes": "Stripes", + "wipe": "Wipe" + }, + "fill-modes": { + "center": "Center", + "crop": "Crop (Fill)", + "fit": "Fit (Contain)", + "stretch": "Stretch" + }, + "no-match": "No match found.", + "no-wallpaper": "No wallpaper found.", + "try-different-search": "Try a different search query.", + "configure-directory": "Configure your wallpaper directory with images." }, "bluetooth": { "panel": { @@ -1004,6 +1026,30 @@ "test": "Test" }, "options": { + "bar": { + "position": { + "top": "Top", + "bottom": "Bottom", + "left": "Left", + "right": "Right" + }, + "density": { + "compact": "Compact", + "default": "Default", + "comfortable": "Comfortable" + } + }, + "launcher": { + "position": { + "center": "Center (default)", + "top_left": "Top left", + "top_right": "Top right", + "bottom_left": "Bottom left", + "bottom_right": "Bottom right", + "bottom_center": "Bottom center", + "top_center": "Top center" + } + }, "display-mode": { "on-hover": "On hover", "always-show": "Always show", @@ -1064,6 +1110,11 @@ } }, "session-menu": { + "title": "Session Menu", + "click-again": "Click again to execute immediately", + "action-in-seconds": "{action} in {seconds} seconds...", + "lock-subtitle": "Lock your session", + "end-subtitle": "End your session", "lock": "Lock", "suspend": "Suspend", "reboot": "Reboot", @@ -1111,5 +1162,98 @@ "shut-down": "Shut down", "restart": "Restart", "suspend": "Suspend" + }, + "toast": { + "night-light": { + "enabled": "Enabled", + "disabled": "Disabled", + "not-installed": "wlsunset not installed", + "forced": "Forced activation", + "normal": "Normal mode" + }, + "keep-awake": { + "enabled": "Enabled", + "disabled": "Disabled" + }, + "matugen": { + "enabled": "Enabled", + "disabled": "Disabled", + "not-installed": "Not installed" + }, + "recording": { + "stopping": "Stopping recording…", + "started": "Recording started", + "saved": "Recording saved", + "failed-start": "Failed to start recording", + "failed-gpu": "gpu-screen-recorder exited unexpectedly.", + "failed-general": "The recorder exited with an error.", + "no-portals": "Desktop portals not running", + "no-portals-desc": "Start xdg-desktop-portal and a compositor portal (wlr/hyprland/gnome/kde)." + }, + "clipboard": { + "unavailable": "Clipboard history unavailable", + "unavailable-desc": "The 'cliphist' application is not installed. Please install it to use clipboard history features." + }, + "ipc": { + "powerpanel-deprecated": "PowerPanel has been renamed to SessionMenu, this IPC call will be deprecated soon. Please use \"ipc call sessionMenu toggle\" instead.", + "sidepanel-deprecated": "SidePanel has been renamed to ControlCenter, this IPC call will be deprecated soon. Please use \"ipc call controlCenter toggle\" instead." + }, + "wifi": { + "enabled": "Enabled", + "disabled": "Disabled", + "connected": "Connected to '{ssid}'", + "disconnected": "Disconnected from '{ssid}'" + }, + "bluetooth": { + "enabled": "Enabled", + "disabled": "Disabled" + }, + "do-not-disturb": { + "enabled": "'Do not disturb' enabled", + "disabled": "'Do not disturb' disabled", + "enabled-desc": "You'll find these notifications in your history.", + "disabled-desc": "Showing all notifications." + }, + "power-profile": { + "changed": "Power profile changed", + "profile-name": "\"{profile}\"" + }, + "audio": { + "muted": "Muted", + "unmuted": "Unmuted" + }, + "battery": { + "low": "Low Battery", + "low-desc": "Battery is at {percent}%. Please connect the charger." + } + }, + "weather": { + "clear-sky": "Clear sky", + "mainly-clear": "Mainly clear", + "partly-cloudy": "Partly cloudy", + "overcast": "Overcast", + "fog": "Fog", + "drizzle": "Drizzle", + "snow": "Snow", + "rain-showers": "Rain showers", + "thunderstorm": "Thunderstorm", + "unknown": "Unknown" + }, + + "authentication": { + "failed": "Authentication failed", + "error": "Authentication error" + }, + "general": { + "no-results": "No results", + "no-summary": "No summary", + "unknown": "Unknown" + }, + "battery": { + "no-battery-detected": "No battery detected.", + "charging-rate": "Charging rate: {rate} W.", + "discharging-rate": "Discharging rate: {rate} W.", + "charging": "Charging.", + "discharging": "Discharging." } } diff --git a/Bin/check-i18n.sh b/Bin/check-i18n.sh deleted file mode 100644 index 77372b79..00000000 --- a/Bin/check-i18n.sh +++ /dev/null @@ -1,65 +0,0 @@ -#!/bin/bash - -# Comprehensive i18n checker for Noctalia Shell -# Finds hardcoded strings that should be internationalized - -check_file() { - local file="$1" - - # Check for hardcoded strings in common properties - # Includes: label, text, title, description, tooltip, tooltipText, placeholder, placeholderText - local property_issues=$(grep -n -E '(label|text|title|description|tooltip|tooltipText|placeholder|placeholderText):\s*"[^"]{3,}"' "$file" | grep -v 'I18n.tr') - - # Check for hardcoded strings in dialog titles and button texts - local dialog_issues=$(grep -n -E '(dialog\.|Dialog\.|title:|buttonText:)\s*"[^"]{3,}"' "$file" | grep -v 'I18n.tr') - - # Check for hardcoded strings in model name properties (for combo boxes) - local model_issues=$(grep -n -E 'name:\s*"[^"]{3,}"' "$file" | grep -v 'I18n.tr') - - # Check for hardcoded strings in common UI text patterns - local ui_issues=$(grep -n -E '"[^"]*\b(click|open|close|enable|disable|show|hide|settings|cancel|apply|ok|save|load|start|stop|play|pause|next|previous|volume|brightness|wifi|bluetooth|notification|wallpaper|profile|power|session|menu|panel|dialog|button|toggle|slider|checkbox|radio|combo|input|search|filter|sort|refresh|update|delete|remove|add|create|edit|modify|copy|paste|cut|undo|redo|help|about|info|warning|error|success|failed|loading|connecting|connected|disconnected|scanning|pairing|recording|playing|paused|stopped|muted|unmuted|enabled|disabled|on|off|yes|no|true|false)\b[^"]*"' "$file" | grep -v 'I18n.tr' | grep -v '//' | grep -v '/*') - - # Combine all issues - local all_issues="$property_issues" - if [[ -n "$dialog_issues" ]]; then - all_issues="$all_issues"$'\n'"$dialog_issues" - fi - if [[ -n "$model_issues" ]]; then - all_issues="$all_issues"$'\n'"$model_issues" - fi - if [[ -n "$ui_issues" ]]; then - all_issues="$all_issues"$'\n'"$ui_issues" - fi - - # Remove empty lines and duplicates - all_issues=$(echo "$all_issues" | grep -v '^$' | sort -u) - - if [[ -n "$all_issues" ]]; then - echo "$file" - echo "$all_issues" | while IFS= read -r line; do - echo " $line" - done - echo - fi -} - -echo "Comprehensive i18n Checker" -echo "=========================" -echo "Scanning QML files for hardcoded strings..." -echo - -found_issues=false - -while IFS= read -r -d '' file; do - if check_file "$file" | grep -q .; then - check_file "$file" - found_issues=true - fi -done < <(find . -name "*.qml" -not -path "./Assets/*" -print0) - -if [[ "$found_issues" == false ]]; then - echo "No hardcoded strings found! All strings appear to be internationalized." -else - echo "Note: Review each match manually - some may be false positives" - echo "(property names, IDs, technical values, comments shouldn't be translated)" -fi diff --git a/Modules/Bar/Widgets/Battery.qml b/Modules/Bar/Widgets/Battery.qml index 1d2d3f7e..336ee925 100644 --- a/Modules/Bar/Widgets/Battery.qml +++ b/Modules/Bar/Widgets/Battery.qml @@ -54,7 +54,9 @@ Item { // Only notify once we are a below threshold if (!charging && !root.hasNotifiedLowBattery && percent <= warningThreshold) { root.hasNotifiedLowBattery = true - ToastService.showWarning("Low Battery", `Battery is at ${Math.round(percent)}%. Please connect the charger.`) + ToastService.showWarning(I18n.tr("toast.battery.low"), I18n.tr("toast.battery.low-desc", { + "percent": Math.round(percent) + })) } else if (root.hasNotifiedLowBattery && (charging || percent > warningThreshold + 5)) { // Reset when charging starts or when battery recovers 5% above threshold root.hasNotifiedLowBattery = false diff --git a/Modules/Notification/Notification.qml b/Modules/Notification/Notification.qml index 4cf82f73..fce49571 100644 --- a/Modules/Notification/Notification.qml +++ b/Modules/Notification/Notification.qml @@ -293,7 +293,7 @@ Variants { } NText { - text: model.summary || "No summary" + text: model.summary || I18n.tr("general.no-summary") font.pointSize: Style.fontSizeL * scaling font.weight: Style.fontWeightMedium color: Color.mOnSurface diff --git a/Modules/Notification/NotificationHistoryPanel.qml b/Modules/Notification/NotificationHistoryPanel.qml index cdc1bcfa..f5bd43d7 100644 --- a/Modules/Notification/NotificationHistoryPanel.qml +++ b/Modules/Notification/NotificationHistoryPanel.qml @@ -216,7 +216,7 @@ NPanel { // Summary NText { - text: model.summary || "No summary" + text: model.summary || I18n.tr("general.no-summary") font.pointSize: Style.fontSizeM * scaling font.weight: Font.Medium color: Color.mOnSurface diff --git a/Modules/SessionMenu/SessionMenu.qml b/Modules/SessionMenu/SessionMenu.qml index a24f0343..0a9c2271 100644 --- a/Modules/SessionMenu/SessionMenu.qml +++ b/Modules/SessionMenu/SessionMenu.qml @@ -31,7 +31,7 @@ NPanel { "action": "lock", "icon": "lock", "title": I18n.tr("session-menu.lock"), - "subtitle": "Lock your session" + "subtitle": I18n.tr("session-menu.lock-subtitle") }, { "action": "suspend", "icon": "suspend", @@ -46,7 +46,7 @@ NPanel { "action": "logout", "icon": "logout", "title": I18n.tr("session-menu.logout"), - "subtitle": "End your session" + "subtitle": I18n.tr("session-menu.end-subtitle") }, { "action": "shutdown", "icon": "shutdown", @@ -263,7 +263,10 @@ NPanel { Layout.preferredHeight: Style.baseWidgetSize * 0.8 * scaling NText { - text: timerActive ? `${pendingAction.charAt(0).toUpperCase() + pendingAction.slice(1)} in ${Math.ceil(timeRemaining / 1000)} seconds...` : "Session Menu" + text: timerActive ? I18n.tr("session-menu.action-in-seconds", { + "action": pendingAction.charAt(0).toUpperCase() + pendingAction.slice(1), + "seconds": Math.ceil(timeRemaining / 1000) + }) : I18n.tr("session-menu.title") font.weight: Style.fontWeightBold font.pointSize: Style.fontSizeL * scaling color: timerActive ? Color.mPrimary : Color.mOnSurface @@ -419,7 +422,7 @@ NPanel { NText { text: { if (buttonRoot.pending) { - return "Click again to execute immediately" + return I18n.tr("session-menu.click-again") } return buttonRoot.subtitle } diff --git a/Modules/Settings/Tabs/BarTab.qml b/Modules/Settings/Tabs/BarTab.qml index 17407631..88715105 100644 --- a/Modules/Settings/Tabs/BarTab.qml +++ b/Modules/Settings/Tabs/BarTab.qml @@ -49,24 +49,19 @@ ColumnLayout { Layout.fillWidth: true label: I18n.tr("settings.bar.appearance.position.label") description: I18n.tr("settings.bar.appearance.position.description") - model: ListModel { - ListElement { - key: "top" - name: "Top" - } - ListElement { - key: "bottom" - name: "Bottom" - } - ListElement { - key: "left" - name: "Left" - } - ListElement { - key: "right" - name: "Right" - } - } + model: [{ + "key": "top", + "name": I18n.tr("options.bar.position.top") + }, { + "key": "bottom", + "name": I18n.tr("options.bar.position.bottom") + }, { + "key": "left", + "name": I18n.tr("options.bar.position.left") + }, { + "key": "right", + "name": I18n.tr("options.bar.position.right") + }] currentKey: Settings.data.bar.position onSelected: key => Settings.data.bar.position = key } @@ -75,20 +70,16 @@ ColumnLayout { Layout.fillWidth: true label: I18n.tr("settings.bar.appearance.density.label") description: I18n.tr("settings.bar.appearance.density.description") - model: ListModel { - ListElement { - key: "compact" - name: "Compact" - } - ListElement { - key: "default" - name: "Default" - } - ListElement { - key: "comfortable" - name: "Comfortable" - } - } + model: [{ + "key": "compact", + "name": I18n.tr("options.bar.density.compact") + }, { + "key": "default", + "name": I18n.tr("options.bar.density.default") + }, { + "key": "comfortable", + "name": I18n.tr("options.bar.density.comfortable") + }] currentKey: Settings.data.bar.density onSelected: key => Settings.data.bar.density = key } diff --git a/Modules/Settings/Tabs/ColorSchemeTab.qml b/Modules/Settings/Tabs/ColorSchemeTab.qml index d7ef97ad..303b7098 100644 --- a/Modules/Settings/Tabs/ColorSchemeTab.qml +++ b/Modules/Settings/Tabs/ColorSchemeTab.qml @@ -65,10 +65,10 @@ ColumnLayout { // Matugen exists, enable it Settings.data.colorSchemes.useWallpaperColors = true MatugenService.generateFromWallpaper() - ToastService.showNotice("Matugen", "Enabled") + ToastService.showNotice(I18n.tr("settings.color-scheme.color-source.enable-matugen.label"), I18n.tr("toast.matugen.enabled")) } else { // Matugen not found - ToastService.showWarning("Matugen", "Not installed") + ToastService.showWarning(I18n.tr("settings.color-scheme.color-source.enable-matugen.label"), I18n.tr("toast.matugen.not-installed")) } } @@ -130,7 +130,7 @@ ColumnLayout { matugenCheck.running = true } else { Settings.data.colorSchemes.useWallpaperColors = false - ToastService.showNotice("Matugen", "Disabled") + ToastService.showNotice(I18n.tr("settings.color-scheme.color-source.enable-matugen.label"), I18n.tr("toast.matugen.disabled")) if (Settings.data.colorSchemes.predefinedScheme) { diff --git a/Modules/Settings/Tabs/DisplayTab.qml b/Modules/Settings/Tabs/DisplayTab.qml index 2146f825..e4431285 100644 --- a/Modules/Settings/Tabs/DisplayTab.qml +++ b/Modules/Settings/Tabs/DisplayTab.qml @@ -38,10 +38,10 @@ ColumnLayout { if (exitCode === 0) { Settings.data.nightLight.enabled = true NightLightService.apply() - ToastService.showNotice("Night light", "Enabled") + ToastService.showNotice(I18n.tr("settings.display.night-light.section.label"), I18n.tr("toast.night-light.enabled")) } else { Settings.data.nightLight.enabled = false - ToastService.showWarning("Night light", "wlsunset not installed") + ToastService.showWarning(I18n.tr("settings.display.night-light.section.label"), I18n.tr("toast.night-light.not-installed")) } } @@ -234,7 +234,7 @@ ColumnLayout { Settings.data.nightLight.enabled = false Settings.data.nightLight.forced = false NightLightService.apply() - ToastService.showNotice("Night light", "Disabled") + ToastService.showNotice(I18n.tr("settings.display.night-light.section.label"), I18n.tr("toast.night-light.disabled")) } } } diff --git a/Modules/Settings/Tabs/LauncherTab.qml b/Modules/Settings/Tabs/LauncherTab.qml index fc456dee..1a77f880 100644 --- a/Modules/Settings/Tabs/LauncherTab.qml +++ b/Modules/Settings/Tabs/LauncherTab.qml @@ -19,36 +19,28 @@ ColumnLayout { label: I18n.tr("settings.launcher.settings.position.label") description: I18n.tr("settings.launcher.settings.position.description") Layout.fillWidth: true - model: ListModel { - ListElement { - key: "center" - name: "Center (default)" - } - ListElement { - key: "top_left" - name: "Top left" - } - ListElement { - key: "top_right" - name: "Top right" - } - ListElement { - key: "bottom_left" - name: "Bottom left" - } - ListElement { - key: "bottom_right" - name: "Bottom right" - } - ListElement { - key: "bottom_center" - name: "Bottom center" - } - ListElement { - key: "top_center" - name: "Top center" - } - } + model: [{ + "key": "center", + "name": I18n.tr("options.launcher.position.center") + }, { + "key": "top_left", + "name": I18n.tr("options.launcher.position.top_left") + }, { + "key": "top_right", + "name": I18n.tr("options.launcher.position.top_right") + }, { + "key": "bottom_left", + "name": I18n.tr("options.launcher.position.bottom_left") + }, { + "key": "bottom_right", + "name": I18n.tr("options.launcher.position.bottom_right") + }, { + "key": "bottom_center", + "name": I18n.tr("options.launcher.position.bottom_center") + }, { + "key": "top_center", + "name": I18n.tr("options.launcher.position.top_center") + }] currentKey: Settings.data.appLauncher.position onSelected: function (key) { Settings.data.appLauncher.position = key diff --git a/Modules/Settings/Tabs/NotificationsTab.qml b/Modules/Settings/Tabs/NotificationsTab.qml index 85a2375e..64a5805c 100644 --- a/Modules/Settings/Tabs/NotificationsTab.qml +++ b/Modules/Settings/Tabs/NotificationsTab.qml @@ -49,32 +49,25 @@ ColumnLayout { NComboBox { label: I18n.tr("settings.notifications.settings.location.label") description: I18n.tr("settings.notifications.settings.location.description") - model: ListModel { - ListElement { - key: "top" - name: "Top" - } - ListElement { - key: "top_left" - name: "Top left" - } - ListElement { - key: "top_right" - name: "Top right" - } - ListElement { - key: "bottom" - name: "Bottom" - } - ListElement { - key: "bottom_left" - name: "Bottom left" - } - ListElement { - key: "bottom_right" - name: "Bottom right" - } - } + model: [{ + "key": "top", + "name": I18n.tr("options.launcher.position.top_center") + }, { + "key": "top_left", + "name": I18n.tr("options.launcher.position.top_left") + }, { + "key": "top_right", + "name": I18n.tr("options.launcher.position.top_right") + }, { + "key": "bottom", + "name": I18n.tr("options.launcher.position.bottom_center") + }, { + "key": "bottom_left", + "name": I18n.tr("options.launcher.position.bottom_left") + }, { + "key": "bottom_right", + "name": I18n.tr("options.launcher.position.bottom_right") + }] currentKey: Settings.data.notifications.location || "top_right" onSelected: key => Settings.data.notifications.location = key } diff --git a/Modules/Settings/Tabs/ScreenRecorderTab.qml b/Modules/Settings/Tabs/ScreenRecorderTab.qml index d3f77e67..4a42eda4 100644 --- a/Modules/Settings/Tabs/ScreenRecorderTab.qml +++ b/Modules/Settings/Tabs/ScreenRecorderTab.qml @@ -76,36 +76,28 @@ ColumnLayout { NComboBox { label: I18n.tr("settings.screen-recorder.video.frame-rate.label") description: I18n.tr("settings.screen-recorder.video.frame-rate.description") - model: ListModel { - ListElement { - key: "30" - name: "30 FPS" - } - ListElement { - key: "60" - name: "60 FPS" - } - ListElement { - key: "100" - name: "100 FPS" - } - ListElement { - key: "120" - name: "120 FPS" - } - ListElement { - key: "144" - name: "144 FPS" - } - ListElement { - key: "165" - name: "165 FPS" - } - ListElement { - key: "240" - name: "240 FPS" - } - } + model: [{ + "key": "30", + "name": I18n.tr("options.frame-rates.30-fps") + }, { + "key": "60", + "name": I18n.tr("options.frame-rates.60-fps") + }, { + "key": "100", + "name": I18n.tr("options.frame-rates.100-fps") + }, { + "key": "120", + "name": I18n.tr("options.frame-rates.120-fps") + }, { + "key": "144", + "name": I18n.tr("options.frame-rates.144-fps") + }, { + "key": "165", + "name": I18n.tr("options.frame-rates.165-fps") + }, { + "key": "240", + "name": I18n.tr("options.frame-rates.240-fps") + }] currentKey: Settings.data.screenRecorder.frameRate onSelected: key => Settings.data.screenRecorder.frameRate = key } @@ -114,24 +106,19 @@ ColumnLayout { NComboBox { label: I18n.tr("settings.screen-recorder.video.video-quality.label") description: I18n.tr("settings.screen-recorder.video.video-quality.description") - model: ListModel { - ListElement { - key: "medium" - name: "Medium" - } - ListElement { - key: "high" - name: "High" - } - ListElement { - key: "very_high" - name: "Very high" - } - ListElement { - key: "ultra" - name: "Ultra" - } - } + model: [{ + "key": "medium", + "name": I18n.tr("options.screen-recording.quality.medium") + }, { + "key": "high", + "name": I18n.tr("options.screen-recording.quality.high") + }, { + "key": "very_high", + "name": I18n.tr("options.screen-recording.quality.very-high") + }, { + "key": "ultra", + "name": I18n.tr("options.screen-recording.quality.ultra") + }] currentKey: Settings.data.screenRecorder.quality onSelected: key => Settings.data.screenRecorder.quality = key } @@ -140,28 +127,22 @@ ColumnLayout { NComboBox { label: I18n.tr("settings.screen-recorder.video.video-codec.label") description: I18n.tr("settings.screen-recorder.video.video-codec.description") - model: ListModel { - ListElement { - key: "h264" - name: "H264" - } - ListElement { - key: "hevc" - name: "HEVC" - } - ListElement { - key: "av1" - name: "AV1" - } - ListElement { - key: "vp8" - name: "VP8" - } - ListElement { - key: "vp9" - name: "VP9" - } - } + model: [{ + "key": "h264", + "name": I18n.tr("options.screen-recording.codecs.h264") + }, { + "key": "hevc", + "name": I18n.tr("options.screen-recording.codecs.hevc") + }, { + "key": "av1", + "name": I18n.tr("options.screen-recording.codecs.av1") + }, { + "key": "vp8", + "name": I18n.tr("options.screen-recording.codecs.vp8") + }, { + "key": "vp9", + "name": I18n.tr("options.screen-recording.codecs.vp9") + }] currentKey: Settings.data.screenRecorder.videoCodec onSelected: key => Settings.data.screenRecorder.videoCodec = key } @@ -170,16 +151,13 @@ ColumnLayout { NComboBox { label: I18n.tr("settings.screen-recorder.video.color-range.label") description: I18n.tr("settings.screen-recorder.video.color-range.description") - model: ListModel { - ListElement { - key: "limited" - name: "Limited" - } - ListElement { - key: "full" - name: "Full" - } - } + model: [{ + "key": "limited", + "name": I18n.tr("options.screen-recording.color-range.limited") + }, { + "key": "full", + "name": I18n.tr("options.screen-recording.color-range.full") + }] currentKey: Settings.data.screenRecorder.colorRange onSelected: key => Settings.data.screenRecorder.colorRange = key } @@ -205,20 +183,16 @@ ColumnLayout { NComboBox { label: I18n.tr("settings.screen-recorder.audio.audio-source.label") description: I18n.tr("settings.screen-recorder.audio.audio-source.description") - model: ListModel { - ListElement { - key: "default_output" - name: "System output" - } - ListElement { - key: "default_input" - name: "Microphone input" - } - ListElement { - key: "both" - name: "System output + microphone input" - } - } + model: [{ + "key": "default_output", + "name": I18n.tr("options.screen-recording.audio-sources.system-output") + }, { + "key": "default_input", + "name": I18n.tr("options.screen-recording.audio-sources.microphone-input") + }, { + "key": "both", + "name": I18n.tr("options.screen-recording.audio-sources.both") + }] currentKey: Settings.data.screenRecorder.audioSource onSelected: key => Settings.data.screenRecorder.audioSource = key } @@ -227,16 +201,13 @@ ColumnLayout { NComboBox { label: I18n.tr("settings.screen-recorder.audio.audio-codec.label") description: I18n.tr("settings.screen-recorder.audio.audio-codec.description") - model: ListModel { - ListElement { - key: "opus" - name: "Opus" - } - ListElement { - key: "aac" - name: "AAC" - } - } + model: [{ + "key": "opus", + "name": I18n.tr("options.screen-recording.audio-codecs.opus") + }, { + "key": "aac", + "name": I18n.tr("options.screen-recording.audio-codecs.aac") + }] currentKey: Settings.data.screenRecorder.audioCodec onSelected: key => Settings.data.screenRecorder.audioCodec = key } diff --git a/Modules/Wallpaper/WallpaperPanel.qml b/Modules/Wallpaper/WallpaperPanel.qml index 95ad2f49..6266aa2b 100644 --- a/Modules/Wallpaper/WallpaperPanel.qml +++ b/Modules/Wallpaper/WallpaperPanel.qml @@ -436,13 +436,13 @@ NPanel { Layout.alignment: Qt.AlignHCenter } NText { - text: (wallpaperPanel.filterText && wallpaperPanel.filterText.length > 0) ? "No match found." : "No wallpaper found." + text: (wallpaperPanel.filterText && wallpaperPanel.filterText.length > 0) ? I18n.tr("wallpaper.no-match") : I18n.tr("wallpaper.no-wallpaper") color: Color.mOnSurface font.weight: Style.fontWeightBold Layout.alignment: Qt.AlignHCenter } NText { - text: (wallpaperPanel.filterText && wallpaperPanel.filterText.length > 0) ? "Try a different search query." : "Configure your wallpaper directory with images." + text: (wallpaperPanel.filterText && wallpaperPanel.filterText.length > 0) ? I18n.tr("wallpaper.try-different-search") : I18n.tr("wallpaper.configure-directory") color: Color.mOnSurfaceVariant wrapMode: Text.WordWrap Layout.alignment: Qt.AlignHCenter diff --git a/Services/AudioService.qml b/Services/AudioService.qml index 8438d03e..e44dd493 100644 --- a/Services/AudioService.qml +++ b/Services/AudioService.qml @@ -62,7 +62,7 @@ Singleton { function onMutedChanged() { root._muted = (sink?.audio.muted ?? true) Logger.log("AudioService", "OnMuteChanged:", root._muted) - ToastService.showNotice("Audio Output", root._muted ? "Muted" : "Unmuted") + ToastService.showNotice(I18n.tr("settings.audio.devices.output-device.label"), root._muted ? I18n.tr("toast.audio.muted") : I18n.tr("toast.audio.unmuted")) } } @@ -80,7 +80,7 @@ Singleton { function onMutedChanged() { root._inputMuted = (source?.audio.muted ?? true) Logger.log("AudioService", "OnInputMuteChanged:", root._inputMuted) - ToastService.showNotice("Microphone", root._inputMuted ? "Muted" : "Unmuted") + ToastService.showNotice(I18n.tr("settings.audio.devices.input-device.label"), root._inputMuted ? I18n.tr("toast.audio.muted") : I18n.tr("toast.audio.unmuted")) } } diff --git a/Services/BluetoothService.qml b/Services/BluetoothService.qml index e25e2639..43ac4dd8 100644 --- a/Services/BluetoothService.qml +++ b/Services/BluetoothService.qml @@ -66,9 +66,9 @@ Singleton { } lastAdapterState = adapter.enabled if (adapter.enabled) { - ToastService.showNotice("Bluetooth", "Enabled") + ToastService.showNotice(I18n.tr("bluetooth.panel.title"), I18n.tr("toast.bluetooth.enabled")) } else { - ToastService.showNotice("Bluetooth", "Disabled") + ToastService.showNotice(I18n.tr("bluetooth.panel.title"), I18n.tr("toast.bluetooth.disabled")) } } } diff --git a/Services/ClipboardService.qml b/Services/ClipboardService.qml index d48dfb17..f8804edb 100644 --- a/Services/ClipboardService.qml +++ b/Services/ClipboardService.qml @@ -70,7 +70,7 @@ Singleton { root.cliphistAvailable = false // Show toast notification if feature is enabled but cliphist is missing if (Settings.data.appLauncher.enableClipboardHistory) { - ToastService.showWarning("Clipboard history unavailable", "The 'cliphist' application is not installed. Please install it to use clipboard history features.", false, 6000) + ToastService.showWarning(I18n.tr("toast.clipboard.unavailable"), I18n.tr("toast.clipboard.unavailable-desc"), false, 6000) } } } diff --git a/Services/IPCService.qml b/Services/IPCService.qml index 5031bbbc..1d01f3fd 100644 --- a/Services/IPCService.qml +++ b/Services/IPCService.qml @@ -114,7 +114,7 @@ Item { target: "powerPanel" function toggle() { sessionMenuPanel.toggle() - ToastService.showWarning("IPC", "PowerPanel has been renamed to SessionMenu, this IPC call will be deprecated soon. Please use \"ipc call sessionMenu toggle\" instead.", 8000) + ToastService.showWarning("IPC", I18n.tr("toast.ipc.powerpanel-deprecated"), 8000) } } IpcHandler { @@ -130,7 +130,7 @@ Item { function toggle() { // Will attempt to open the panel next to the bar button if any. controlCenterPanel.toggle(BarService.lookupWidget("ControlCenter")) - ToastService.showWarning("IPC", "SidePanel has been renamed to ControlCenter, this IPC call will be deprecated soon. Please use \"ipc call controlCenter toggle\" instead.", 8000) + ToastService.showWarning("IPC", I18n.tr("toast.ipc.sidepanel-deprecated"), 8000) } } IpcHandler { diff --git a/Services/IdleInhibitorService.qml b/Services/IdleInhibitorService.qml index c804226e..9a2504a6 100644 --- a/Services/IdleInhibitorService.qml +++ b/Services/IdleInhibitorService.qml @@ -163,13 +163,13 @@ Singleton { if (activeInhibitors.includes("manual")) { removeInhibitor("manual") Settings.data.ui.idleInhibitorEnabled = false - ToastService.showNotice("Keep awake", "Disabled") + ToastService.showNotice(I18n.tr("tooltips.keep-awake"), I18n.tr("toast.keep-awake.disabled")) Logger.log("IdleInhibitor", "Manual inhibition disabled and saved to settings") return false } else { addInhibitor("manual", "Manually activated by user") Settings.data.ui.idleInhibitorEnabled = true - ToastService.showNotice("Keep awake", "Enabled") + ToastService.showNotice(I18n.tr("tooltips.keep-awake"), I18n.tr("toast.keep-awake.enabled")) Logger.log("IdleInhibitor", "Manual inhibition enabled and saved to settings") return true } diff --git a/Services/NetworkService.qml b/Services/NetworkService.qml index 2287fc45..0caaf025 100644 --- a/Services/NetworkService.qml +++ b/Services/NetworkService.qml @@ -48,9 +48,9 @@ Singleton { target: Settings.data.network function onWifiEnabledChanged() { if (Settings.data.network.wifiEnabled) { - ToastService.showNotice("Wi-Fi", "Enabled") + ToastService.showNotice(I18n.tr("wifi.panel.title"), I18n.tr("toast.wifi.enabled")) } else { - ToastService.showNotice("Wi-Fi", "Disabled") + ToastService.showNotice(I18n.tr("wifi.panel.title"), I18n.tr("toast.wifi.disabled")) } } } @@ -492,7 +492,9 @@ Singleton { root.connecting = false root.connectingTo = "" Logger.log("Network", `Connected to network: '${connectProcess.ssid}'`) - ToastService.showNotice("Wi-Fi", `Connected to '${connectProcess.ssid}'`) + ToastService.showNotice(I18n.tr("wifi.panel.title"), I18n.tr("toast.wifi.connected", { + "ssid": connectProcess.ssid + })) // Still do a scan to get accurate signal and security info delayedScanTimer.interval = 5000 @@ -533,7 +535,9 @@ Singleton { stdout: StdioCollector { onStreamFinished: { Logger.log("Network", `Disconnected from network: '${disconnectProcess.ssid}'`) - ToastService.showNotice("Wi-Fi", `Disconnected from '${disconnectProcess.ssid}'`) + ToastService.showNotice(I18n.tr("wifi.panel.title"), I18n.tr("toast.wifi.disconnected", { + "ssid": disconnectProcess.ssid + })) // Immediately update UI on successful disconnect root.updateNetworkStatus(disconnectProcess.ssid, false) diff --git a/Services/NightLightService.qml b/Services/NightLightService.qml index ba37ca21..a52be4d8 100644 --- a/Services/NightLightService.qml +++ b/Services/NightLightService.qml @@ -63,12 +63,12 @@ Singleton { apply() // Toast: night light toggled const enabled = !!Settings.data.nightLight.enabled - ToastService.showNotice("Night light", enabled ? "Enabled" : "Disabled") + ToastService.showNotice(I18n.tr("settings.display.night-light.section.label"), enabled ? I18n.tr("toast.night-light.enabled") : I18n.tr("toast.night-light.disabled")) } function onForcedChanged() { apply() if (Settings.data.nightLight.enabled) { - ToastService.showNotice("Night Light", Settings.data.nightLight.forced ? "Forced activation" : "Normal mode") + ToastService.showNotice(I18n.tr("settings.display.night-light.section.label"), Settings.data.nightLight.forced ? I18n.tr("toast.night-light.forced") : I18n.tr("toast.night-light.normal")) } } function onNightTempChanged() { diff --git a/Services/NotificationService.qml b/Services/NotificationService.qml index 8f0999dd..fcad5e85 100644 --- a/Services/NotificationService.qml +++ b/Services/NotificationService.qml @@ -386,7 +386,7 @@ Singleton { target: Settings.data.notifications function onDoNotDisturbChanged() { const enabled = Settings.data.notifications.doNotDisturb - ToastService.showNotice(enabled ? "'Do not disturb' enabled" : "'Do not disturb' disabled", enabled ? "You'll find these notifications in your history." : "Showing all notifications.") + ToastService.showNotice(enabled ? I18n.tr("toast.do-not-disturb.enabled") : I18n.tr("toast.do-not-disturb.disabled"), enabled ? I18n.tr("toast.do-not-disturb.enabled-desc") : I18n.tr("toast.do-not-disturb.disabled-desc")) } } } diff --git a/Services/PowerProfileService.qml b/Services/PowerProfileService.qml index e14f7f7c..98acfb71 100644 --- a/Services/PowerProfileService.qml +++ b/Services/PowerProfileService.qml @@ -78,7 +78,9 @@ Singleton { // Only show toast if we have a valid profile name (not "Unknown") const profileName = root.getName() if (profileName !== "Unknown") { - ToastService.showNotice("Power profile changed", `"${profileName}"`) + ToastService.showNotice(I18n.tr("toast.power-profile.changed"), I18n.tr("toast.power-profile.profile-name", { + "profile": profileName + })) } } } diff --git a/Services/ScreenRecorderService.qml b/Services/ScreenRecorderService.qml index e45a3785..17bd92e9 100644 --- a/Services/ScreenRecorderService.qml +++ b/Services/ScreenRecorderService.qml @@ -82,7 +82,7 @@ Singleton { return } - ToastService.showNotice("Stopping recording…", outputPath, 2000) + ToastService.showNotice(I18n.tr("toast.recording.stopping"), outputPath, 2000) Quickshell.execDetached(["sh", "-c", "pkill -SIGINT -f 'gpu-screen-recorder' || pkill -SIGINT -f 'com.dec05eba.gpu_screen_recorder'"]) @@ -110,9 +110,9 @@ Singleton { if (exitCode !== 0) { const err = String(stderr.text || "").trim() if (err.length > 0) - ToastService.showError("Failed to start recording", err, 7000) + ToastService.showError(I18n.tr("toast.recording.failed-start"), err, 7000) else - ToastService.showError("Failed to start recording", "gpu-screen-recorder exited unexpectedly.", 7000) + ToastService.showError(I18n.tr("toast.recording.failed-start"), I18n.tr("toast.recording.failed-gpu"), 7000) } } else if (isRecording) { // Process ended normally while recording @@ -120,13 +120,13 @@ Singleton { monitorTimer.running = false // Consider successful save if exitCode == 0 if (exitCode === 0) { - ToastService.showNotice("Recording saved", outputPath, 5000) + ToastService.showNotice(I18n.tr("toast.recording.saved"), outputPath, 5000) } else { const err2 = String(stderr.text || "").trim() if (err2.length > 0) - ToastService.showError("Recording failed", err2, 7000) + ToastService.showError(I18n.tr("toast.recording.failed-start"), err2, 7000) else - ToastService.showError("Recording failed", "The recorder exited with an error.", 7000) + ToastService.showError(I18n.tr("toast.recording.failed-start"), I18n.tr("toast.recording.failed-general"), 7000) } } } @@ -142,7 +142,7 @@ Singleton { } else { isPending = false hasActiveRecording = false - ToastService.showError("Desktop portals not running", "Start xdg-desktop-portal and a compositor portal (wlr/hyprland/gnome/kde).", 8000) + ToastService.showError(I18n.tr("toast.recording.no-portals"), I18n.tr("toast.recording.no-portals-desc"), 8000) } } } diff --git a/Widgets/NFilePicker.qml b/Widgets/NFilePicker.qml index e96cd561..54072943 100644 --- a/Widgets/NFilePicker.qml +++ b/Widgets/NFilePicker.qml @@ -15,7 +15,7 @@ Item { property bool multipleSelection: false property string pickerType: "file" // "file" or "folder" property var nameFilters: ["All files (*)"] // e.g., ["Image files (*.png *.jpg)", "Text files (*.txt)"] - property string title: pickerType === "folder" ? "Select Folder" : "Select File" + property string title: pickerType === "folder" ? I18n.tr("widgets.file-picker.select-folder") : I18n.tr("widgets.file-picker.select-file") property string acceptLabel: I18n.tr("placeholders.select") property string rejectLabel: I18n.tr("placeholders.cancel") From 9cfe49dec3e90d552df2f3ebb30dd330ba4e9920 Mon Sep 17 00:00:00 2001 From: Ly-sec Date: Wed, 24 Sep 2025 16:02:24 +0200 Subject: [PATCH 10/15] NComboBox: fix other languages display Translations/de: update accordingly --- Assets/Translations/de.json | 89 ++++++++++++++++++++++++++++++------- Widgets/NComboBox.qml | 52 ++++++++++++++++------ 2 files changed, 113 insertions(+), 28 deletions(-) diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json index b3d0b367..6820c1ad 100644 --- a/Assets/Translations/de.json +++ b/Assets/Translations/de.json @@ -44,7 +44,7 @@ }, "solid-black": { "label": "Schwarze Ecken", - "description": "Schwarze Ecken anstelle der Leisten-Hintergrundfarbe verwenden." + "description": "Schwarze Ecken anstelle der Statusleisten-Hintergrundfarbe verwenden." }, "radius": { "label": "Bildschirmecken-Radius", @@ -192,35 +192,35 @@ } }, "bar": { - "title": "Leiste", + "title": "Statusleiste", "appearance": { "section": { "label": "Erscheinungsbild", - "description": "Erscheinungsbild und Position der Leiste anpassen." + "description": "Erscheinungsbild und Position der Statusleiste anpassen." }, "position": { - "label": "Leistenposition", - "description": "Wählen Sie, wo die Leiste auf dem Bildschirm platziert werden soll." + "label": "Statusleistenposition", + "description": "Wählen Sie, wo die Statusleiste auf dem Bildschirm platziert werden soll." }, "density": { - "label": "Leistendichte", - "description": "Innenabstand der Leiste für kompaktes oder geräumiges Aussehen anpassen." + "label": "Statusleistendichte", + "description": "Innenabstand der Statusleiste für kompaktes oder geräumiges Aussehen anpassen." }, "background-opacity": { "label": "Hintergrund-Transparenz", - "description": "Hintergrund-Transparenz der Leiste anpassen." + "description": "Hintergrund-Transparenz der Statusleiste anpassen." }, "show-capsule": { "label": "Kapsel anzeigen", "description": "Widget-Hintergründe anzeigen." }, "floating": { - "label": "Schwebende Leiste", - "description": "Leiste als schwebende 'Pille' anzeigen. Hinweis: Dies verschiebt die Bildschirmecken an die Ränder." + "label": "Schwebende Statusleiste", + "description": "Statusleiste als schwebende 'Pille' anzeigen. Hinweis: Dies verschiebt die Bildschirmecken an die Ränder." }, "margins": { "label": "Ränder", - "description": "Ränder um die schwebende Leiste anpassen.", + "description": "Ränder um die schwebende Statusleiste anpassen.", "vertical": "Vertikal", "horizontal": "Horizontal" } @@ -234,7 +234,7 @@ "monitors": { "section": { "label": "Monitor-Anzeige", - "description": "Leiste auf bestimmten Monitoren anzeigen. Standard ist alle, wenn keine ausgewählt sind." + "description": "Statusleiste auf bestimmten Monitoren anzeigen. Standard ist alle, wenn keine ausgewählt sind." } } }, @@ -663,6 +663,10 @@ "tooltip": { "placeholder": "Platzhalter" }, + "file-picker": { + "select-folder": "Ordner auswählen", + "select-file": "Datei auswählen" + }, "datetime-tokens": { "common": { "12hour-time-minutes": "12-Stunden-Zeit mit Minuten", @@ -860,11 +864,11 @@ "description": "Passen Sie die Anzeige Ihrer Uhr an, indem Sie Token aus der Liste unten hinzufügen. Um das 12-Stunden-Format zu verwenden, müssen Sie das 'AP'-Token einschließen." }, "horizontal-bar": { - "label": "Horizontale Leiste", + "label": "Horizontale Statusleiste", "description": "Tipp: Verwenden Sie \\n, um einen Zeilenumbruch zu erstellen." }, "vertical-bar": { - "label": "Vertikale Leiste", + "label": "Vertikale Statusleiste", "description": "Verwenden Sie ein Leerzeichen, um jeden Teil in eine neue Zeile zu trennen." }, "preview": "Vorschau" @@ -886,7 +890,25 @@ "description": "Ausgewähltes Hintergrundbild auf alle Monitore gleichzeitig anwenden." }, "search": "Suchen:" - } + }, + "transitions": { + "none": "Keine", + "random": "Zufällig", + "fade": "Überblenden", + "disc": "Scheibe", + "stripes": "Streifen", + "wipe": "Wischen" + }, + "fill-modes": { + "center": "Zentrieren", + "crop": "Zuschneiden (Füllen)", + "fit": "Einpassen (Beibehalten)", + "stretch": "Strecken" + }, + "no-match": "Keine Übereinstimmung gefunden.", + "no-wallpaper": "Kein Hintergrundbild gefunden.", + "try-different-search": "Versuchen Sie eine andere Suchanfrage.", + "configure-directory": "Konfigurieren Sie Ihr Hintergrundbild-Verzeichnis mit Bildern." }, "bluetooth": { "panel": { @@ -1004,6 +1026,30 @@ "test": "Test" }, "options": { + "bar": { + "position": { + "top": "Oben", + "bottom": "Unten", + "left": "Links", + "right": "Rechts" + }, + "density": { + "compact": "Kompakt", + "default": "Standard", + "comfortable": "Bequem" + } + }, + "launcher": { + "position": { + "center": "Mitte (Standard)", + "top_left": "Oben links", + "top_right": "Oben rechts", + "bottom_left": "Unten links", + "bottom_right": "Unten rechts", + "bottom_center": "Unten mittig", + "top_center": "Oben mittig" + } + }, "display-mode": { "on-hover": "Beim Darüberfahren", "always-show": "Immer anzeigen", @@ -1067,6 +1113,8 @@ "title": "Sitzungsmenü", "click-again": "Erneut klicken für sofortige Ausführung", "action-in-seconds": "{action} in {seconds} Sekunden...", + "lock-subtitle": "Sitzung sperren", + "end-subtitle": "Sitzung beenden", "lock": "Sperren", "suspend": "Ruhezustand", "reboot": "Neu starten", @@ -1107,6 +1155,17 @@ "unknown-version": "Unbekannt", "unknown-layout": "Unbekannt" }, + "battery": { + "no-battery-detected": "Keine Batterie erkannt.", + "charging-rate": "Laderate: {rate} W.", + "discharging-rate": "Entladerate: {rate} W.", + "charging": "Wird geladen.", + "discharging": "Wird entladen." + }, + "authentication": { + "failed": "Authentifizierung fehlgeschlagen", + "error": "Authentifizierungsfehler" + }, "lock-screen": { "secure-terminal": "SICHERES TERMINAL", "unlock-command": "sudo unlock-session", diff --git a/Widgets/NComboBox.qml b/Widgets/NComboBox.qml index 635876a0..34b0f92a 100644 --- a/Widgets/NComboBox.qml +++ b/Widgets/NComboBox.qml @@ -13,9 +13,7 @@ RowLayout { property string label: "" property string description: "" - property ListModel model: { - - } + property var model property string currentKey: "" property string placeholder: "" @@ -26,11 +24,31 @@ RowLayout { spacing: Style.marginL * scaling Layout.fillWidth: true + function itemCount() { + if (!root.model) + return 0 + if (typeof root.model.count === 'number') + return root.model.count + if (Array.isArray(root.model)) + return root.model.length + return 0 + } + + function getItem(index) { + if (!root.model) + return null + if (typeof root.model.get === 'function') + return root.model.get(index) + if (Array.isArray(root.model)) + return root.model[index] + return null + } + function findIndexByKey(key) { - for (var i = 0; i < root.model.count; i++) { - if (root.model.get(i).key === key) { + for (var i = 0; i < itemCount(); i++) { + var item = getItem(i) + if (item && item.key === key) return i - } } return -1 } @@ -48,7 +66,9 @@ RowLayout { model: model currentIndex: findIndexByKey(currentKey) onActivated: { - root.selected(model.get(combo.currentIndex).key) + var item = getItem(combo.currentIndex) + if (item && item.key !== undefined) + root.selected(item.key) } background: Rectangle { @@ -72,8 +92,8 @@ RowLayout { font.pointSize: Style.fontSizeM * scaling verticalAlignment: Text.AlignVCenter elide: Text.ElideRight - color: (combo.currentIndex >= 0 && combo.currentIndex < root.model.count) ? Color.mOnSurface : Color.mOnSurfaceVariant - text: (combo.currentIndex >= 0 && combo.currentIndex < root.model.count) ? root.model.get(combo.currentIndex).name : root.placeholder + color: (combo.currentIndex >= 0 && combo.currentIndex < itemCount()) ? Color.mOnSurface : Color.mOnSurfaceVariant + text: (combo.currentIndex >= 0 && combo.currentIndex < itemCount()) ? (getItem(combo.currentIndex) ? getItem(combo.currentIndex).name : root.placeholder) : root.placeholder } indicator: NIcon { @@ -115,9 +135,12 @@ RowLayout { } onClicked: { - root.selected(root.model.get(index).key) - combo.currentIndex = index - combo.popup.close() + var item = root.getItem(index) + if (item && item.key !== undefined) { + root.selected(item.key) + combo.currentIndex = index + combo.popup.close() + } } background: Rectangle { @@ -132,7 +155,10 @@ RowLayout { } contentItem: NText { - text: name + text: (function () { + var item = root.getItem(index) + return item && item.name ? item.name : "" + })() font.pointSize: Style.fontSizeM * scaling color: highlighted ? Color.mOnTertiary : Color.mOnSurface verticalAlignment: Text.AlignVCenter From 9105ec6b0d91b51da879c0bf4dae2ae7c7156c8d Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Wed, 24 Sep 2025 10:17:28 -0400 Subject: [PATCH 11/15] i18n: no more close side panel as its called control center --- Assets/Translations/de.json | 1 - Assets/Translations/en.json | 1 - Assets/Translations/fr.json | 1248 ++++++++++++++++++- Modules/ControlCenter/Cards/ProfileCard.qml | 2 +- 4 files changed, 1244 insertions(+), 8 deletions(-) diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json index 6820c1ad..8fcebb69 100644 --- a/Assets/Translations/de.json +++ b/Assets/Translations/de.json @@ -965,7 +965,6 @@ "move-to-right-section": "Zur rechten Sektion verschieben", "open-settings": "Einstellungen öffnen", "session-menu": "Sitzungsmenü", - "close-side-panel": "Seitenpanel schließen", "cancel-timer": "Timer abbrechen", "start-screen-recording": "Bildschirmaufnahme starten", "stop-screen-recording": "Bildschirmaufnahme stoppen", diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index 2430106f..df3c0258 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -965,7 +965,6 @@ "move-to-right-section": "Move to right section", "open-settings": "Open settings", "session-menu": "Session Menu", - "close-side-panel": "Close side panel", "cancel-timer": "Cancel timer", "start-screen-recording": "Start screen recording", "stop-screen-recording": "Stop screen recording", diff --git a/Assets/Translations/fr.json b/Assets/Translations/fr.json index 92fa46a5..fc7dc83c 100644 --- a/Assets/Translations/fr.json +++ b/Assets/Translations/fr.json @@ -1,17 +1,1255 @@ { "settings": { "general": { - "title": "General", + "title": "Général", "profile": { "section": { - "label": "Profile", - "description": "Modifiez vos informations d'utilisateur et votre avatar." + "label": "Profil", + "description": "Modifiez vos informations utilisateur et votre avatar." }, "picture": { - "label": "Image de profile de {user}", - "description": "Votre photo de profil qui apparaît tout au long de l'interface." + "label": "Photo de profil de {user}", + "description": "Votre photo de profil qui apparaît dans toute l'interface." + }, + "select-avatar": "Sélectionner une image d'avatar" + }, + "ui": { + "section": { + "label": "Interface utilisateur", + "description": "Personnalisez l'apparence, l'ergonomie et le comportement de l'interface." + }, + "dim-desktop": { + "label": "Assombrir le bureau", + "description": "Assombrir le bureau lorsque des panneaux ou des menus sont ouverts." + }, + "border-radius": { + "label": "Rayon de bordure", + "description": "Contrôle l'arrondi des coins des fenêtres, des boutons et d'autres éléments." + }, + "animation-speed": { + "label": "Vitesse d'animation", + "description": "Ajustez la vitesse globale des animations." + } + }, + "screen-corners": { + "section": { + "label": "Coins de l'écran", + "description": "Personnalisez l'arrondi des coins de l'écran et les effets visuels." + }, + "show-corners": { + "label": "Afficher les coins de l'écran", + "description": "Affichez des coins arrondis sur le bord de l'écran." + }, + "solid-black": { + "label": "Coins noirs unis", + "description": "Utilisez du noir uni au lieu de la couleur de fond de la barre." + }, + "radius": { + "label": "Rayon des coins de l'écran", + "description": "Ajustez l'arrondi des coins de l'écran." + } + }, + "fonts": { + "section": { + "label": "Polices", + "description": "Choisissez les polices utilisées dans toute l'interface." + }, + "default": { + "label": "Police par défaut", + "description": "Police principale utilisée dans toute l'interface.", + "placeholder": "Sélectionner la police par défaut...", + "search-placeholder": "Rechercher des polices..." + }, + "monospace": { + "label": "Police à chasse fixe", + "description": "Police à chasse fixe utilisée pour l'affichage des chiffres et des statistiques.", + "placeholder": "Sélectionner la police à chasse fixe...", + "search-placeholder": "Rechercher des polices à chasse fixe..." + }, + "accent": { + "label": "Police d'accentuation", + "description": "Grande police utilisée pour les affichages proéminents.", + "placeholder": "Sélectionner la police d'affichage...", + "search-placeholder": "Rechercher des polices d'affichage..." + } + } + }, + "audio": { + "title": "Audio", + "volumes": { + "section": { + "label": "Volumes", + "description": "Ajustez les contrôles de volume et les niveaux audio." + }, + "output-volume": { + "label": "Volume de sortie", + "description": "Niveau de volume de l'ensemble du système." + }, + "mute-output": { + "label": "Couper la sortie audio", + "description": "Couper la sortie audio principale du système." + }, + "input-volume": { + "label": "Volume d'entrée", + "description": "Niveau du volume d'entrée du microphone." + }, + "mute-input": { + "label": "Couper l'entrée audio", + "description": "Couper l'entrée audio par défaut (microphone)." + }, + "step-size": { + "label": "Incrément de volume", + "description": "Ajustez l'incrément pour les changements de volume (molette de la souris, raccourcis clavier)." + } + }, + "devices": { + "section": { + "label": "Périphériques audio", + "description": "Configurez les périphériques d'entrée et de sortie audio disponibles." + }, + "output-device": { + "label": "Périphérique de sortie", + "description": "Sélectionnez le périphérique de sortie audio souhaité." + }, + "input-device": { + "label": "Périphérique d'entrée", + "description": "Sélectionnez le périphérique d'entrée audio souhaité." + } + }, + "media": { + "section": { + "label": "Lecteurs multimédias", + "description": "Définissez vos applications multimédias préférées et ignorées." + }, + "primary-player": { + "label": "Lecteur principal", + "description": "Entrez un mot-clé pour identifier votre lecteur principal.", + "placeholder": "ex. spotify, vlc, mpv" + }, + "excluded-player": { + "label": "Lecteur exclu", + "description": "Ajoutez des mots-clés pour les lecteurs que le système doit ignorer. Chaque mot-clé doit être sur une nouvelle ligne.", + "placeholder": "tapez la sous-chaîne et appuyez sur +" + }, + "visualizer-type": { + "label": "Type de visualisation", + "description": "Choisissez un type de visualisation pour la lecture multimédia." + }, + "frame-rate": { + "label": "Fréquence d'images", + "description": "Des fréquences plus élevées sont plus fluides mais utilisent plus de ressources." + } + } + }, + "display": { + "title": "Affichage", + "monitors": { + "section": { + "label": "Paramètres par moniteur", + "description": "Ajustez la mise à l'échelle et la luminosité pour chaque écran." + }, + "scale": "Mise à l'échelle", + "brightness": "Luminosité", + "reset-scaling": "Réinitialiser la mise à l'échelle", + "brightness-step": { + "label": "Incrément de luminosité", + "description": "Ajustez l'incrément pour les changements de luminosité (molette de la souris et raccourcis clavier)." + } + }, + "night-light": { + "section": { + "label": "Éclairage nocturne", + "description": "Réduit l'émission de lumière bleue pour vous aider à mieux dormir et réduire la fatigue oculaire." + }, + "enable": { + "label": "Activer l'éclairage nocturne", + "description": "Applique un filtre de couleur chaude pour réduire l'émission de lumière bleue." + }, + "temperature": { + "label": "Température de couleur", + "description": "Réglez la chaleur des couleurs pour la nuit et le jour.", + "night": "Nuit", + "day": "Jour" + }, + "auto-schedule": { + "label": "Planification automatique", + "description": "Basé sur l'heure du coucher et du lever du soleil à {location} - recommandé." + }, + "manual-schedule": { + "label": "Planification manuelle", + "description": "Définissez des heures personnalisées pour le lever et le coucher du soleil.", + "sunrise": "Heure du lever du soleil", + "sunset": "Heure du coucher du soleil", + "select-start": "Sélectionner l'heure de début", + "select-stop": "Sélectionner l'heure de fin" + }, + "force-activation": { + "label": "Forcer l'activation", + "description": "Ignore la planification et applique le filtre nocturne immédiatement." + } + } + }, + "bar": { + "title": "Barre", + "appearance": { + "section": { + "label": "Apparence", + "description": "Personnalisez l'apparence et la position de la barre." + }, + "position": { + "label": "Position de la barre", + "description": "Choisissez où placer la barre sur l'écran." + }, + "density": { + "label": "Densité de la barre", + "description": "Ajustez le remplissage de la barre pour un aspect compact ou spacieux." + }, + "background-opacity": { + "label": "Opacité de l'arrière-plan", + "description": "Ajustez l'opacité de l'arrière-plan de la barre." + }, + "show-capsule": { + "label": "Afficher la capsule", + "description": "Afficher les arrière-plans des widgets." + }, + "floating": { + "label": "Barre flottante", + "description": "Affiche la barre sous forme de 'pilule' flottante. Note : Ceci déplacera les coins de l'écran vers les bords." + }, + "margins": { + "label": "Marges", + "description": "Ajustez les marges autour de la barre flottante.", + "vertical": "Verticale", + "horizontal": "Horizontale" + } + }, + "widgets": { + "section": { + "label": "Positionnement des widgets", + "description": "Glissez-déposez les widgets pour les réorganiser dans chaque section, ou utilisez les boutons ajouter/supprimer pour gérer les widgets." + } + }, + "monitors": { + "section": { + "label": "Affichage sur le moniteur", + "description": "Afficher la barre sur des moniteurs spécifiques. Par défaut, sur tous si aucun n'est choisi." + } + } + }, + "dock": { + "title": "Dock", + "appearance": { + "section": { + "label": "Apparence", + "description": "Personnalisez le comportement et l'apparence du dock." + }, + "auto-hide": { + "label": "Masquer automatiquement", + "description": "Masquer automatiquement lorsqu'il n'est pas utilisé." + }, + "exclusive-zone": { + "label": "Zone exclusive", + "description": "Empêcher le chevauchement des fenêtres." + }, + "background-opacity": { + "label": "Opacité de l'arrière-plan", + "description": "Ajustez l'opacité de l'arrière-plan du dock." + }, + "floating-distance": { + "label": "Distance de flottaison du dock", + "description": "Ajustez la distance de flottaison par rapport au bord de l'écran." + } + }, + "monitors": { + "section": { + "label": "Affichage sur le moniteur", + "description": "Choisissez sur quel moniteur afficher le dock." + } + } + }, + "launcher": { + "title": "Lanceur", + "settings": { + "section": { + "label": "Apparence", + "description": "Personnalisez le comportement et l'apparence du lanceur." + }, + "position": { + "label": "Position", + "description": "Choisissez où le panneau du lanceur apparaît." + }, + "background-opacity": { + "label": "Opacité de l'arrière-plan", + "description": "Ajustez l'opacité de l'arrière-plan du lanceur." + }, + "clipboard-history": { + "label": "Activer l'historique du presse-papiers", + "description": "Accédez aux éléments précédemment copiés depuis le lanceur." + }, + "sort-by-usage": { + "label": "Trier par les plus utilisés", + "description": "Lorsque cette option est activée, les applications fréquemment lancées apparaissent en premier dans la liste." + }, + "use-app2unit": { + "label": "Utiliser App2Unit pour lancer les applications", + "description": "Utilise une méthode de lancement alternative pour mieux gérer les processus des applications et prévenir les problèmes." + } + } + }, + "notifications": { + "title": "Notifications", + "settings": { + "section": { + "label": "Apparence", + "description": "Configurez l'apparence et le comportement des notifications." + }, + "do-not-disturb": { + "label": "Ne pas déranger", + "description": "Désactive toutes les fenêtres de notification lorsque cette option est activée." + }, + "enable-osd": { + "label": "Activer l'affichage à l'écran (OSD)", + "description": "Afficher les changements de volume et de luminosité en temps réel." + }, + "location": { + "label": "Emplacement", + "description": "Où les notifications apparaissent à l'écran." + }, + "low-urgency": { + "label": "Urgence faible", + "description": "Durée de visibilité des notifications de faible priorité." + }, + "normal-urgency": { + "label": "Urgence normale", + "description": "Durée de visibilité des notifications de priorité normale." + }, + "critical-urgency": { + "label": "Urgence critique", + "description": "Durée de visibilité des notifications de priorité critique." + }, + "monitors-display": { + "label": "Affichage sur les moniteurs", + "description": "Afficher les notifications sur des moniteurs spécifiques. Par défaut, sur tous si aucun n'est choisi." + } + } + }, + "wallpaper": { + "title": "Fond d'écran", + "settings": { + "section": { + "label": "Paramètres du fond d'écran", + "description": "Contrôlez comment les fonds d'écran sont gérés et affichés." + }, + "enable-management": { + "label": "Activer la gestion des fonds d'écran", + "description": "Gérez les fonds d'écran avec Noctalia. Décochez si vous préférez utiliser une autre application." + }, + "folder": { + "label": "Dossier des fonds d'écran", + "description": "Chemin vers votre dossier principal de fonds d'écran.", + "tooltip": "Parcourir le dossier des fonds d'écran" + }, + "monitor-specific": { + "label": "Dossiers spécifiques au moniteur", + "description": "Définissez un dossier de fond d'écran différent pour chaque moniteur.", + "tooltip": "Parcourir le dossier des fonds d'écran" + }, + "select-folder": "Sélectionner le dossier des fonds d'écran", + "select-monitor-folder": "Sélectionner le dossier des fonds d'écran du moniteur" + }, + "look-feel": { + "section": { + "label": "Apparence et ergonomie" + }, + "fill-mode": { + "label": "Mode de remplissage", + "description": "Sélectionnez comment l'image doit être mise à l'échelle pour correspondre à la résolution de votre moniteur." + }, + "fill-color": { + "label": "Couleur de remplissage", + "description": "Choisissez une couleur de remplissage qui peut apparaître derrière le fond d'écran." + }, + "transition-type": { + "label": "Type de transition", + "description": "Type d'animation lors du changement de fond d'écran." + }, + "transition-duration": { + "label": "Durée de la transition", + "description": "Durée des animations de transition en secondes." + }, + "edge-smoothness": { + "label": "Adoucir le bord de la transition", + "description": "Applique un effet de flou progressif au bord des transitions." + } + }, + "automation": { + "section": { + "label": "Automatisation" + }, + "random-wallpaper": { + "label": "Fond d'écran aléatoire", + "description": "Planifiez des changements de fond d'écran aléatoires à intervalles réguliers." + }, + "interval": { + "label": "Intervalle du fond d'écran", + "description": "Fréquence de changement automatique des fonds d'écran." + }, + "custom-interval": { + "label": "Intervalle personnalisé", + "description": "Entrez l'heure au format HH:MM (ex: 01:30)." + } + } + }, + "color-scheme": { + "title": "Jeu de couleurs", + "color-source": { + "section": { + "label": "Source des couleurs", + "description": "Paramètres principaux pour les couleurs de Noctalia." + }, + "dark-mode": { + "label": "Mode sombre", + "description": "Passe à un thème plus sombre pour une visualisation plus facile la nuit." + }, + "enable-matugen": { + "label": "Activer Matugen", + "description": "Générez automatiquement des couleurs en fonction de votre fond d'écran actif." + } + }, + "predefined": { + "section": { + "label": "Jeux de couleurs prédéfinis", + "description": "Pour utiliser ces jeux de couleurs, vous devez désactiver Matugen. Avec Matugen activé, les couleurs sont générées automatiquement à partir de votre fond d'écran." + } + }, + "matugen": { + "section": { + "label": "Modèles Matugen", + "description": "Appliquez des couleurs aux applications externes." + }, + "ui": { + "label": "UI", + "description": "Thématisation de l'environnement de bureau et de la boîte à outils d'interface utilisateur.", + "gtk4": { + "label": "GTK 4 (libadwaita)", + "description": "Écrire ~/.config/gtk-4.0/gtk.css" + }, + "gtk3": { + "label": "GTK 3", + "description": "Écrire ~/.config/gtk-3.0/gtk.css" + }, + "qt6": { + "label": "Qt6ct", + "description": "Écrire ~/.config/qt6ct/colors/noctalia.conf" + }, + "qt5": { + "label": "Qt5ct", + "description": "Écrire ~/.config/qt5ct/colors/noctalia.conf" + } + }, + "terminal": { + "label": "Terminal", + "description": "Thématisation de l'émulateur de terminal.", + "kitty": { + "label": "Kitty", + "description": "Écrire ~/.config/kitty/themes/noctalia.conf et recharger", + "description-missing": "Nécessite que le terminal Kitty soit installé" + }, + "ghostty": { + "label": "Ghostty", + "description": "Écrire ~/.config/ghostty/themes/noctalia et recharger", + "description-missing": "Nécessite que le terminal ghostty soit installé" + }, + "foot": { + "label": "Foot", + "description": "Écrire ~/.config/foot/themes/noctalia et recharger", + "description-missing": "Nécessite que le terminal foot soit installé" + } + }, + "programs": { + "label": "Programmes", + "description": "Thématisation spécifique aux applications.", + "fuzzel": { + "label": "Fuzzel", + "description": "Écrire ~/.config/fuzzel/themes/noctalia et recharger", + "description-missing": "Nécessite que le lanceur fuzzel soit installé" + }, + "vesktop": { + "label": "Vesktop", + "description": "Écrire ~/.config/vesktop/themes/noctalia.theme.css", + "description-missing": "Nécessite que le client Discord vesktop soit installé" + }, + "pywalfox": { + "label": "Pywalfox (Firefox)", + "description": "Écrire ~/.cache/wal/colors.json et exécuter pywalfox update", + "description-missing": "Nécessite que le paquet pywalfox soit installé" + } + }, + "misc": { + "label": "Divers", + "description": "Options de configuration supplémentaires.", + "user-templates": { + "label": "Modèles utilisateur", + "description": "Activer la configuration Matugen définie par l'utilisateur depuis ~/.config/matugen/config.toml" + } + } + } + }, + "location": { + "title": "Emplacement", + "location": { + "section": { + "label": "Votre emplacement", + "description": "Obtenez une météo et une planification de l'éclairage nocturne précises en définissant votre emplacement." + }, + "search": { + "label": "Rechercher un emplacement", + "description": "ex: Toronto, ON", + "placeholder": "Entrez le nom de l'emplacement" + } + }, + "weather": { + "section": { + "label": "Météo", + "description": "Choisissez votre unité de température préférée." + }, + "fahrenheit": { + "label": "Afficher la température en Fahrenheit (°F)", + "description": "Afficher la température en Fahrenheit au lieu de Celsius." + } + }, + "date-time": { + "section": { + "label": "Date & heure", + "description": "Personnalisez l'affichage de la date et de l'heure." + }, + "12hour-format": { + "label": "Utiliser le format horaire de 12 heures sur l'écran de verrouillage", + "description": "Activé pour le format AM/PM (ex: 8:00 PM), désactivé pour le format 24 heures (ex: 20:00)." + }, + "week-numbers": { + "label": "Afficher les numéros de semaine", + "description": "Affiche la semaine de l'année (ex: Semaine 38) dans le calendrier." + } + } + }, + "network": { + "title": "Réseau", + "section": { + "description": "Gérez les connexions Wi-Fi et Bluetooth." + }, + "wifi": { + "label": "Activer le Wi-Fi" + }, + "bluetooth": { + "label": "Activer le Bluetooth" + } + }, + "screen-recorder": { + "title": "Enregistreur d'écran", + "general": { + "section": { + "label": "Paramètres généraux", + "description": "Gérez la sortie et le contenu de l'enregistrement d'écran." + }, + "output-folder": { + "label": "Dossier de sortie", + "description": "Dossier où les enregistrements d'écran seront sauvegardés.", + "tooltip": "Parcourir le dossier de sortie" + }, + "show-cursor": { + "label": "Afficher le curseur", + "description": "Enregistrez le curseur de la souris dans la vidéo." + }, + "select-output-folder": "Sélectionner le dossier de sortie" + }, + "video": { + "section": { + "label": "Paramètres vidéo", + "description": "Configurez les options d'enregistrement vidéo." + }, + "video-source": { + "label": "Source vidéo", + "description": "Portail est recommandé, si vous obtenez des artefacts, essayez Écran." + }, + "frame-rate": { + "label": "Fréquence d'images", + "description": "Fréquence d'images cible pour les enregistrements d'écran." + }, + "video-quality": { + "label": "Qualité vidéo", + "description": "Une qualité supérieure entraîne des fichiers de plus grande taille." + }, + "video-codec": { + "label": "Codec vidéo", + "description": "h264 est le codec le plus courant." + }, + "color-range": { + "label": "Gamme de couleurs", + "description": "Limitée est recommandée pour une meilleure compatibilité." + } + }, + "audio": { + "section": { + "label": "Paramètres audio", + "description": "Configurez les options d'enregistrement audio." + }, + "audio-source": { + "label": "Source audio", + "description": "Source audio à capturer pendant l'enregistrement." + }, + "audio-codec": { + "label": "Codec audio", + "description": "Opus est recommandé pour de meilleures performances et une taille audio minimale." + } + } + }, + "about": { + "title": "À propos", + "noctalia": { + "section": { + "label": "Shell Noctalia", + "description": "Un shell de bureau élégant et minimaliste, conçu avec soin pour Wayland et bâti avec Quickshell." + }, + "latest-version": "Dernière version :", + "installed-version": "Version installée :", + "download-latest": "Télécharger la dernière version" + }, + "contributors": { + "section": { + "label": "Contributeurs", + "description": "Un grand merci à notre {count} super contributeur !", + "description_plural": "Un grand merci à nos {count} super contributeurs !" + } + } + }, + "hooks": { + "title": "Hooks", + "system-hooks": { + "section": { + "label": "Hooks système", + "description": "Configurez des commandes à exécuter lors d'événements système." + }, + "enable": { + "label": "Activer les hooks", + "description": "Activer ou désactiver toutes les commandes de hook." + } + }, + "wallpaper-changed": { + "label": "Fond d'écran changé", + "description": "Commande à exécuter lorsque le fond d'écran change.", + "placeholder": "ex: notify-send \"Fond d'écran\" \"Changé\"" + }, + "theme-changed": { + "label": "Thème changé", + "description": "Commande à exécuter lorsque le thème bascule entre le mode sombre et clair.", + "placeholder": "ex: notify-send \"Thème\" \"Basculé\"" + }, + "info": { + "command-info": { + "label": "Informations sur la commande de hook", + "description": "• Les commandes sont exécutées via le shell (sh -c)\n• Les commandes s'exécutent en arrière-plan (détachées)\n• Les boutons de test s'exécutent avec les valeurs actuelles" + }, + "parameters": { + "label": "Paramètres disponibles", + "description": "• Hook Fond d'écran : $1 = chemin du fond d'écran, $2 = nom de l'écran\n• Hook de bascule de thème : $1 = true/false (état du mode sombre)" } } } + }, + "widgets": { + "tooltip": { + "placeholder": "Espace réservé" + }, + "file-picker": { + "select-folder": "Sélectionner un dossier", + "select-file": "Sélectionner un fichier" + }, + "datetime-tokens": { + "common": { + "12hour-time-minutes": "Heure sur 12 heures avec minutes", + "24hour-time-minutes": "Heure sur 24 heures avec minutes", + "24hour-time-seconds": "Heure sur 24 heures avec secondes", + "weekday-month-day": "Jour de la semaine, mois et jour", + "iso-date": "Format de date ISO", + "us-date": "Format de date américain", + "european-date": "Format de date européen", + "weekday-date": "Jour de la semaine avec date" + }, + "hour": { + "no-leading-zero": "Heure sans zéro initial (0-23) - format 24 heures", + "leading-zero": "Heure avec zéro initial (00-23) - format 24 heures" + }, + "minute": { + "no-leading-zero": "Minute sans zéro initial (0-59)", + "leading-zero": "Minute avec zéro initial (00-59)" + }, + "second": { + "no-leading-zero": "Seconde sans zéro initial (0-59)", + "leading-zero": "Seconde avec zéro initial (00-59)" + }, + "ampm": { + "uppercase": "AM/PM en majuscules", + "lowercase": "am/pm en minuscules" + }, + "timezone": { + "abbreviation": "Abréviation du fuseau horaire" + }, + "year": { + "two-digit": "Année sur deux chiffres (00-99)", + "four-digit": "Année sur quatre chiffres" + }, + "month": { + "number-no-zero": "Mois en chiffre sans zéro initial (1-12)", + "number-leading-zero": "Mois en chiffre avec zéro initial (01-12)", + "abbreviated": "Nom du mois abrégé", + "full": "Nom complet du mois" + }, + "day": { + "no-leading-zero": "Jour sans zéro initial (1-31)", + "leading-zero": "Jour avec zéro initial (01-31)", + "abbreviated": "Nom du jour abrégé", + "full": "Nom complet du jour" + } + }, + "icon-picker": { + "title": "Sélecteur d'icônes", + "search": { + "label": "Rechercher" + }, + "cancel": "Annuler", + "apply": "Appliquer" + }, + "color-picker": { + "title": "Sélecteur de couleurs", + "hex": { + "label": "Couleur hexadécimale", + "description": "Entrez un code couleur hexadécimal." + }, + "rgb": { + "label": "Valeurs RVB", + "description": "Ajustez les valeurs de rouge, vert, bleu et de luminosité." + }, + "brightness": "Luminosité", + "theme-colors": { + "label": "Couleurs du thème", + "description": "Accès rapide à la palette de couleurs de votre thème." + }, + "palette": { + "label": "Palette", + "description": "Choisissez parmi une large gamme de couleurs prédéfinies." + }, + "cancel": "Annuler", + "apply": "Appliquer" + } + }, + "bar": { + "widget-settings": { + "dialog": { + "cancel": "Annuler", + "apply": "Appliquer" + }, + "section-editor": { + "placeholder": "Sélectionnez un widget à ajouter..." + }, + "active-window": { + "show-app-icon": "Afficher l'icône de l'application" + }, + "system-monitor": { + "cpu-usage": "Utilisation du CPU", + "cpu-temperature": "Température du CPU", + "memory-usage": "Utilisation de la mémoire", + "memory-percentage": "Mémoire en pourcentage", + "network-traffic": "Trafic réseau", + "storage-usage": "Utilisation du stockage" + }, + "notification-history": { + "show-unread-badge": "Afficher le badge non lu", + "hide-badge-when-zero": "Masquer le badge si zéro" + }, + "battery": { + "display-mode": { + "label": "Mode d'affichage", + "description": "Choisissez comment vous souhaitez que cette valeur apparaisse." + }, + "low-battery-threshold": { + "label": "Seuil d'avertissement de batterie faible", + "description": "Afficher un avertissement lorsque la batterie tombe en dessous de ce pourcentage." + } + }, + "control-center": { + "use-distro-logo": "Utiliser le logo de la distribution au lieu de l'icône", + "icon": { + "label": "Icône", + "description": "Sélectionnez une icône de la bibliothèque ou un fichier personnalisé." + }, + "browse-library": "Parcourir la bibliothèque", + "browse-file": "Parcourir les fichiers", + "select-custom-icon": "Sélectionner une icône personnalisée" + }, + "keyboard-layout": { + "display-mode": { + "label": "Mode d'affichage", + "description": "Choisissez comment vous souhaitez que cette valeur apparaisse." + } + }, + "volume": { + "display-mode": { + "label": "Mode d'affichage", + "description": "Choisissez comment vous souhaitez que cette valeur apparaisse." + } + }, + "workspace": { + "label-mode": "Mode d'étiquette", + "hide-unoccupied": { + "label": "Masquer les inoccupés", + "description": "Ne pas afficher les espaces de travail sans fenêtres." + } + }, + "microphone": { + "display-mode": { + "label": "Mode d'affichage", + "description": "Choisissez comment vous souhaitez que cette valeur apparaisse." + } + }, + "brightness": { + "display-mode": { + "label": "Mode d'affichage", + "description": "Choisissez comment vous souhaitez que cette valeur apparaisse." + } + }, + "spacer": { + "width": { + "label": "Largeur", + "description": "Largeur de l'espacement en pixels" + } + }, + "custom-button": { + "icon": { + "label": "Icône", + "description": "Sélectionnez une icône dans la bibliothèque." + }, + "browse": "Parcourir", + "left-click": "Clic gauche", + "right-click": "Clic droit", + "middle-click": "Clic du milieu", + "dynamic-text": "Texte dynamique", + "display-command-output": { + "label": "Afficher la sortie de la commande", + "description": "Entrez une commande à exécuter à intervalle régulier. La première ligne de sa sortie sera affichée sous forme de texte." + }, + "refresh-interval": { + "label": "Intervalle d'actualisation", + "description": "Intervalle en millisecondes." + } + }, + "media-mini": { + "show-album-art": "Afficher la pochette de l'album", + "show-visualizer": "Afficher le visualiseur", + "visualizer-type": "Type de visualiseur" + }, + "clock": { + "use-primary-color": { + "label": "Utiliser la couleur principale", + "description": "Lorsque cette option est activée, la couleur principale est utilisée pour la mise en évidence." + }, + "use-monospaced-font": { + "label": "Utiliser une police à chasse fixe", + "description": "Lorsque cette option est activée, l'horloge utilisera la police à chasse fixe." + }, + "clock-display": { + "label": "Affichage de l'horloge", + "description": "Personnalisez l'affichage de votre horloge en ajoutant des jetons de la liste ci-dessous. Pour utiliser le format 12 heures, vous devez inclure le jeton 'AP'." + }, + "horizontal-bar": { + "label": "Barre horizontale", + "description": "Astuce : Utilisez \\n pour créer un saut de ligne." + }, + "vertical-bar": { + "label": "Barre verticale", + "description": "Utilisez un espace pour séparer chaque partie sur une nouvelle ligne." + }, + "preview": "Aperçu" + } + } + }, + "notifications": { + "panel": { + "title": "Notifications", + "no-notifications": "Aucune notification", + "description": "Vos notifications apparaîtront ici à mesure qu'elles arriveront." + } + }, + "wallpaper": { + "panel": { + "title": "Sélecteur de fond d'écran", + "apply-all-monitors": { + "label": "Appliquer à tous les moniteurs", + "description": "Appliquer le fond d'écran sélectionné à tous les moniteurs en même temps." + }, + "search": "Rechercher :" + }, + "transitions": { + "none": "Aucune", + "random": "Aléatoire", + "fade": "Fondu", + "disc": "Disque", + "stripes": "Rayures", + "wipe": "Balayage" + }, + "fill-modes": { + "center": "Centrer", + "crop": "Recadrer (Remplir)", + "fit": "Ajuster (Contenir)", + "stretch": "Étirer" + }, + "no-match": "Aucun résultat trouvé.", + "no-wallpaper": "Aucun fond d'écran trouvé.", + "try-different-search": "Essayez une autre requête de recherche.", + "configure-directory": "Configurez votre répertoire de fonds d'écran avec des images." + }, + "bluetooth": { + "panel": { + "title": "Bluetooth", + "disabled": "Le Bluetooth est désactivé", + "enable-message": "Activez le Bluetooth pour voir les appareils disponibles.", + "connected-devices": "Appareils connectés", + "known-devices": "Appareils connus", + "available-devices": "Appareils disponibles", + "scanning": "Recherche d'appareils en cours...", + "pairing-mode": "Assurez-vous que votre appareil est en mode d'appairage." + } + }, + "wifi": { + "panel": { + "title": "Wi-Fi", + "disabled": "Le Wi-Fi est désactivé", + "enable-message": "Activez le Wi-Fi pour voir les réseaux disponibles.", + "searching": "Recherche de réseaux à proximité en cours...", + "connected": "Connecté", + "disconnecting": "Déconnexion en cours...", + "forgetting": "Oubli en cours...", + "saved": "Enregistré", + "disconnect": "Déconnecter", + "enter-password": "Entrez le mot de passe...", + "connect": "Connecter", + "password": "Mot de passe", + "forget-network": "Oublier ce réseau ?", + "forget": "Oublier", + "no-networks": "Aucun réseau trouvé", + "scan-again": "Analyser à nouveau" + } + }, + "calendar": { + "panel": { + "week": "Semaine" + } + }, + "tooltips": { + "refresh": "Actualiser", + "close": "Fermer", + "refresh-wallpaper-list": "Actualiser la liste des fonds d'écran", + "refresh-devices": "Actualiser les appareils", + "forget-network": "Oublier le réseau", + "clear-history": "Effacer l'historique", + "delete-notification": "Supprimer la notification", + "previous-month": "Mois précédent", + "next-month": "Mois suivant", + "add-widget": "Ajouter un widget", + "widget-settings": "Paramètres du widget", + "remove-widget": "Supprimer le widget", + "move-to-left-section": "Déplacer vers la section de gauche", + "move-to-center-section": "Déplacer vers la section centrale", + "move-to-right-section": "Déplacer vers la section de droite", + "open-settings": "Ouvrir les paramètres", + "session-menu": "Menu de session", + "cancel-timer": "Annuler le minuteur", + "start-screen-recording": "Démarrer l'enregistrement d'écran", + "stop-screen-recording": "Arrêter l'enregistrement d'écran", + "screen-recorder-not-installed": "L'enregistreur d'écran n'est pas installé", + "enable-keep-awake": "Activer le mode 'rester éveillé'", + "disable-keep-awake": "Désactiver le mode 'rester éveillé'", + "wallpaper-selector": "Clic gauche : Ouvrir le sélecteur de fond d'écran.\nClic droit : Définir un fond d'écran aléatoire.", + "do-not-disturb-enabled": "'Ne pas déranger' activé", + "do-not-disturb-disabled": "'Ne pas déranger' désactivé", + "connect-disconnect-devices": "Clic gauche pour connecter. Clic droit pour oublier.", + "set-power-profile": "Définir le profil d'alimentation \"{profile}\"", + "switch-to-light-mode": "Passer en mode clair", + "switch-to-dark-mode": "Passer en mode sombre", + "night-light-disabled": "L'éclairage nocturne est désactivé.\nClic gauche pour changer de mode.\nClic droit pour accéder aux paramètres.", + "night-light-enabled": "L'éclairage nocturne est activé.\nClic gauche pour changer de mode.\nClic droit pour accéder aux paramètres.", + "night-light-forced": "L'éclairage nocturne est forcé.\nClic gauche pour changer de mode.\nClic droit pour accéder aux paramètres.", + "click-to-start-recording": "Cliquez pour démarrer l'enregistrement", + "click-to-stop-recording": "Cliquez pour arrêter l'enregistrement", + "open-side-panel": "Ouvrir le panneau latéral", + "volume-at": "Volume à {volume}%\nClic gauche pour couper/rétablir le son. Clic droit pour les paramètres.\nFaites défiler pour modifier le volume.", + "microphone-volume-at": "Volume du microphone à {volume}%\nClic gauche pour couper/rétablir le son. Clic droit pour les paramètres.\nFaites défiler pour modifier le volume.", + "manage-wifi": "Gérer le Wi-Fi", + "bluetooth-devices": "Appareils Bluetooth", + "open-notification-history-enable-dnd": "Ouvrir l'historique des notifications\nClic droit pour activer \"Ne pas déranger\".", + "open-notification-history-disable-dnd": "Ouvrir l'historique des notifications\nClic droit pour désactiver \"Ne pas déranger\".", + "open-wallpaper-selector": "Ouvrir le sélecteur de fond d'écran", + "previous-media": "Média précédent", + "pause": "Pause", + "play": "Lecture", + "next-media": "Média suivant", + "power-profile": "Profil d'alimentation '{profile}'", + "keyboard-layout": "Disposition du clavier {layout}" + }, + "clock": { + "tooltip": "Ouvrir le calendrier" + }, + "dock": { + "menu": { + "focus": "Mettre au premier plan", + "pin": "Épingler", + "unpin": "Détacher", + "close": "Fermer" + } + }, + "placeholders": { + "search-icons": "ex: noctalia, niri, batterie, nuage", + "profile-picture-path": "/home/user/.face", + "enter-width-pixels": "Entrez la largeur en pixels", + "enter-command": "Entrez la commande à exécuter (application ou script personnalisé)", + "command-example": "echo \"Bonjour le monde\"", + "clock-horizontal": "HH:mm jjj, dd MMM", + "clock-vertical": "HH mm dd MM", + "search-wallpapers": "Tapez pour filtrer les fonds d'écran...", + "search-launcher": "Rechercher des entrées... ou utilisez > pour les commandes", + "search": "Rechercher...", + "select": "Sélectionner", + "cancel": "Annuler", + "test": "Tester" + }, + "options": { + "bar": { + "position": { + "top": "Haut", + "bottom": "Bas", + "left": "Gauche", + "right": "Droite" + }, + "density": { + "compact": "Compact", + "default": "Défaut", + "comfortable": "Confortable" + } + }, + "launcher": { + "position": { + "center": "Centre (par défaut)", + "top_left": "En haut à gauche", + "top_right": "En haut à droite", + "bottom_left": "En bas à gauche", + "bottom_right": "En bas à droite", + "bottom_center": "En bas au centre", + "top_center": "En haut au centre" + } + }, + "display-mode": { + "on-hover": "Au survol", + "always-show": "Toujours afficher", + "always-hide": "Toujours masquer", + "force-open": "Forcer l'ouverture" + }, + "workspace-labels": { + "none": "Aucun", + "index": "Index", + "name": "Nom" + }, + "visualizer-types": { + "none": "Aucun", + "linear": "Linéaire", + "mirrored": "Miroir", + "wave": "Vague" + }, + "frame-rates": { + "30-fps": "30 FPS", + "60-fps": "60 FPS", + "100-fps": "100 FPS", + "120-fps": "120 FPS", + "144-fps": "144 FPS", + "165-fps": "165 FPS", + "240-fps": "240 FPS" + }, + "screen-recording": { + "sources": { + "portal": "Portail", + "screen": "Écran" + }, + "quality": { + "medium": "Moyenne", + "high": "Haute", + "very-high": "Très haute", + "ultra": "Ultra" + }, + "codecs": { + "h264": "H264", + "hevc": "HEVC", + "av1": "AV1", + "vp8": "VP8", + "vp9": "VP9" + }, + "color-range": { + "limited": "Limitée", + "full": "Complète" + }, + "audio-sources": { + "system-output": "Sortie système", + "microphone-input": "Entrée microphone", + "both": "Sortie système + entrée microphone" + }, + "audio-codecs": { + "opus": "Opus", + "aac": "AAC" + } + } + }, + "session-menu": { + "title": "Menu de session", + "click-again": "Cliquez à nouveau pour exécuter immédiatement", + "action-in-seconds": "{action} dans {seconds} secondes...", + "lock-subtitle": "Verrouiller votre session", + "end-subtitle": "Terminer votre session", + "lock": "Verrouiller", + "suspend": "Mettre en veille", + "reboot": "Redémarrer", + "logout": "Déconnexion", + "shutdown": "Éteindre" + }, + "plugins": { + "applications": "Applications", + "clipboard": "Historique du presse-papiers", + "calculator": "Calculatrice", + "clipboard-search-description": "Rechercher dans l'historique du presse-papiers", + "clipboard-clear-description": "Effacer tout l'historique du presse-papiers", + "clipboard-history-disabled": "Historique du presse-papiers désactivé", + "clipboard-history-disabled-description": "Activez l'historique du presse-papiers dans les paramètres ou installez cliphist", + "clipboard-clear-history": "Effacer l'historique du presse-papiers", + "clipboard-clear-description-full": "Supprimer tous les éléments de l'historique du presse-papiers", + "clipboard-loading": "Chargement de l'historique du presse-papiers...", + "clipboard-loading-description": "Veuillez patienter", + "calculator-description": "Calculatrice - évaluez des expressions mathématiques", + "calculator-name": "Calculatrice", + "calculator-enter-expression": "Entrez une expression mathématique", + "calculator-error": "Erreur" + }, + "system": { + "uptime": "Temps d'activité : {uptime}", + "welcome-back": "Bon retour, {user} !", + "monitor-description": "{model} ({width}x{height})", + "scaling-percentage": "{percentage}%", + "location-display": "{name} ({coordinates})", + "signal-strength": "{signal}%", + "cpu-temperature": "{temp}°C", + "disk-usage": "{percent}%", + "widget-settings-title": "Paramètres de {widget}", + "unknown-app": "Application inconnue", + "no-media-player-detected": "Aucun lecteur multimédia détecté", + "user-requested": "Demandé par l'utilisateur", + "unknown": "Inconnu", + "unknown-version": "Inconnue", + "unknown-layout": "Inconnue" + }, + "lock-screen": { + "secure-terminal": "TERMINAL SÉCURISÉ", + "unlock-command": "sudo unlock-session", + "password": "Mot de passe :", + "shut-down": "Éteindre", + "restart": "Redémarrer", + "suspend": "Mettre en veille" + }, + "toast": { + "night-light": { + "enabled": "Activé", + "disabled": "Désactivé", + "not-installed": "wlsunset non installé", + "forced": "Activation forcée", + "normal": "Mode normal" + }, + "keep-awake": { + "enabled": "Activé", + "disabled": "Désactivé" + }, + "matugen": { + "enabled": "Activé", + "disabled": "Désactivé", + "not-installed": "Non installé" + }, + "recording": { + "stopping": "Arrêt de l'enregistrement...", + "started": "Enregistrement démarré", + "saved": "Enregistrement sauvegardé", + "failed-start": "Échec du démarrage de l'enregistrement", + "failed-gpu": "gpu-screen-recorder s'est arrêté de manière inattendue.", + "failed-general": "L'enregistreur s'est arrêté avec une erreur.", + "no-portals": "Les portails de bureau ne sont pas en cours d'exécution", + "no-portals-desc": "Démarrez xdg-desktop-portal et un portail de compositeur (wlr/hyprland/gnome/kde)." + }, + "clipboard": { + "unavailable": "Historique du presse-papiers indisponible", + "unavailable-desc": "L'application 'cliphist' n'est pas installée. Veuillez l'installer pour utiliser les fonctionnalités d'historique du presse-papiers." + }, + "ipc": { + "powerpanel-deprecated": "PowerPanel a été renommé en SessionMenu, cet appel IPC sera bientôt obsolète. Veuillez utiliser \"ipc call sessionMenu toggle\" à la place.", + "sidepanel-deprecated": "SidePanel a été renommé en ControlCenter, cet appel IPC sera bientôt obsolète. Veuillez utiliser \"ipc call controlCenter toggle\" à la place." + }, + "wifi": { + "enabled": "Activé", + "disabled": "Désactivé", + "connected": "Connecté à '{ssid}'", + "disconnected": "Déconnecté de '{ssid}'" + }, + "bluetooth": { + "enabled": "Activé", + "disabled": "Désactivé" + }, + "do-not-disturb": { + "enabled": "'Ne pas déranger' activé", + "disabled": "'Ne pas déranger' désactivé", + "enabled-desc": "Vous trouverez ces notifications dans votre historique.", + "disabled-desc": "Affichage de toutes les notifications." + }, + "power-profile": { + "changed": "Profil d'alimentation changé", + "profile-name": "\"{profile}\"" + }, + "audio": { + "muted": "Son coupé", + "unmuted": "Son rétabli" + }, + "battery": { + "low": "Batterie faible", + "low-desc": "La batterie est à {percent}%. Veuillez brancher le chargeur." + } + }, + "weather": { + "clear-sky": "Ciel dégagé", + "mainly-clear": "Généralement dégagé", + "partly-cloudy": "Partiellement nuageux", + "overcast": "Couvert", + "fog": "Brouillard", + "drizzle": "Bruine", + "snow": "Neige", + "rain-showers": "Averses de pluie", + "thunderstorm": "Orage", + "unknown": "Inconnu" + }, + "authentication": { + "failed": "Échec de l'authentification", + "error": "Erreur d'authentification" + }, + "general": { + "no-results": "Aucun résultat", + "no-summary": "Aucun résumé", + "unknown": "Inconnu" + }, + "battery": { + "no-battery-detected": "Aucune batterie détectée.", + "charging-rate": "Taux de charge : {rate} W.", + "discharging-rate": "Taux de décharge : {rate} W.", + "charging": "En charge.", + "discharging": "En décharge." } } \ No newline at end of file diff --git a/Modules/ControlCenter/Cards/ProfileCard.qml b/Modules/ControlCenter/Cards/ProfileCard.qml index effd69fc..9b619edf 100644 --- a/Modules/ControlCenter/Cards/ProfileCard.qml +++ b/Modules/ControlCenter/Cards/ProfileCard.qml @@ -78,7 +78,7 @@ NBox { NIconButton { id: closeButton icon: "close" - tooltipText: I18n.tr("tooltips.close-side-panel") + tooltipText: I18n.tr("tooltips.close") onClicked: { controlCenterPanel.close() } From 084fb39abdfdd78b1ec4867c895deadec8c89044 Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Wed, 24 Sep 2025 10:24:45 -0400 Subject: [PATCH 12/15] NComboBox: simple js function --- Widgets/NComboBox.qml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Widgets/NComboBox.qml b/Widgets/NComboBox.qml index 34b0f92a..6035b620 100644 --- a/Widgets/NComboBox.qml +++ b/Widgets/NComboBox.qml @@ -155,10 +155,10 @@ RowLayout { } contentItem: NText { - text: (function () { + text: { var item = root.getItem(index) return item && item.name ? item.name : "" - })() + } font.pointSize: Style.fontSizeM * scaling color: highlighted ? Color.mOnTertiary : Color.mOnSurface verticalAlignment: Text.AlignVCenter From 7f9acccce7204f7a2ece8620cede8fa1ee7d63fa Mon Sep 17 00:00:00 2001 From: Ly-sec Date: Wed, 24 Sep 2025 16:48:43 +0200 Subject: [PATCH 13/15] i18n: remove some entries, edit some entries --- Assets/Translations/de.json | 50 ++++------------ Assets/Translations/en.json | 50 ++++------------ Commons/I18n.qml | 2 +- .../Bar/WidgetSettings/ClockSettings.qml | 5 +- Modules/Settings/Tabs/ColorSchemeTab.qml | 60 ++++++++++++------- Modules/Settings/Tabs/ScreenRecorderTab.qml | 41 +++++-------- 6 files changed, 82 insertions(+), 126 deletions(-) diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json index 6820c1ad..e18868ec 100644 --- a/Assets/Translations/de.json +++ b/Assets/Translations/de.json @@ -433,38 +433,31 @@ "label": "UI", "description": "Desktop-Umgebung und UI-Toolkit-Theming.", "gtk4": { - "label": "GTK 4 (libadwaita)", - "description": "Schreibt ~/.config/gtk-4.0/gtk.css" + "description": "Schreibt {filepath}" }, "gtk3": { - "label": "GTK 3", - "description": "Schreibt ~/.config/gtk-3.0/gtk.css" + "description": "Schreibt {filepath}" }, "qt6": { - "label": "Qt6ct", - "description": "Schreibt ~/.config/qt6ct/colors/noctalia.conf" + "description": "Schreibt {filepath}" }, "qt5": { - "label": "Qt5ct", - "description": "Schreibt ~/.config/qt5ct/colors/noctalia.conf" + "description": "Schreibt {filepath}" } }, "terminal": { "label": "Terminal", "description": "Terminal-Emulator-Theming.", "kitty": { - "label": "Kitty", - "description": "Schreibt ~/.config/kitty/themes/noctalia.conf und lädt neu", + "description": "Schreibt {filepath} und lädt neu", "description-missing": "Erfordert kitty Terminal" }, "ghostty": { - "label": "Ghostty", - "description": "Schreibt ~/.config/ghostty/themes/noctalia und lädt neu", + "description": "Schreibt {filepath} und lädt neu", "description-missing": "Erfordert ghostty Terminal" }, "foot": { - "label": "Foot", - "description": "Schreibt ~/.config/foot/themes/noctalia und lädt neu", + "description": "Schreibt {filepath} und lädt neu", "description-missing": "Erfordert foot Terminal" } }, @@ -472,18 +465,15 @@ "label": "Programme", "description": "Anwendungsspezifisches Theming.", "fuzzel": { - "label": "Fuzzel", - "description": "Schreibt ~/.config/fuzzel/themes/noctalia und lädt neu", + "description": "Schreibt {filepath} und lädt neu", "description-missing": "Erfordert fuzzel Starter" }, "vesktop": { - "label": "Vesktop", - "description": "Schreibt ~/.config/vesktop/themes/noctalia.theme.css", + "description": "Schreibt {filepath}", "description-missing": "Erfordert vesktop Discord-Client" }, "pywalfox": { - "label": "Pywalfox (Firefox)", - "description": "Schreibt ~/.cache/wal/colors.json und führt pywalfox update aus", + "description": "Schreibt {filepath} und führt pywalfox update aus", "description-missing": "Erfordert pywalfox Paket" } }, @@ -1016,8 +1006,7 @@ "enter-width-pixels": "Breite in Pixeln eingeben", "enter-command": "Befehl eingeben (App oder benutzerdefiniertes Skript)", "command-example": "echo \"Hallo Welt\"", - "clock-horizontal": "HH:mm ddd, MMM dd", - "clock-vertical": "HH mm dd MM", + "search-wallpapers": "Zum Filtern von Hintergrundbildern eingeben...", "search-launcher": "Einträge suchen... oder > für Befehle verwenden", "search": "Suchen...", @@ -1067,15 +1056,7 @@ "mirrored": "Gespiegelt", "wave": "Welle" }, - "frame-rates": { - "30-fps": "30 FPS", - "60-fps": "60 FPS", - "100-fps": "100 FPS", - "120-fps": "120 FPS", - "144-fps": "144 FPS", - "165-fps": "165 FPS", - "240-fps": "240 FPS" - }, + "screen-recording": { "sources": { "portal": "Portal", @@ -1087,13 +1068,6 @@ "very-high": "Sehr hoch", "ultra": "Ultra" }, - "codecs": { - "h264": "H264", - "hevc": "HEVC", - "av1": "AV1", - "vp8": "VP8", - "vp9": "VP9" - }, "color-range": { "limited": "Begrenzt", "full": "Vollständig" diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index 2430106f..90497cc4 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -433,38 +433,31 @@ "label": "UI", "description": "Desktop environment and UI toolkit theming.", "gtk4": { - "label": "GTK 4 (libadwaita)", - "description": "Write ~/.config/gtk-4.0/gtk.css" + "description": "Write {filepath}" }, "gtk3": { - "label": "GTK 3", - "description": "Write ~/.config/gtk-3.0/gtk.css" + "description": "Write {filepath}" }, "qt6": { - "label": "Qt6ct", - "description": "Write ~/.config/qt6ct/colors/noctalia.conf" + "description": "Write {filepath}" }, "qt5": { - "label": "Qt5ct", - "description": "Write ~/.config/qt5ct/colors/noctalia.conf" + "description": "Write {filepath}" } }, "terminal": { "label": "Terminal", "description": "Terminal emulator theming.", "kitty": { - "label": "Kitty", - "description": "Write ~/.config/kitty/themes/noctalia.conf and reload", + "description": "Write {filepath} and reload", "description-missing": "Requires kitty terminal to be installed" }, "ghostty": { - "label": "Ghostty", - "description": "Write ~/.config/ghostty/themes/noctalia and reload", + "description": "Write {filepath} and reload", "description-missing": "Requires ghostty terminal to be installed" }, "foot": { - "label": "Foot", - "description": "Write ~/.config/foot/themes/noctalia and reload", + "description": "Write {filepath} and reload", "description-missing": "Requires foot terminal to be installed" } }, @@ -472,18 +465,15 @@ "label": "Programs", "description": "Application-specific theming.", "fuzzel": { - "label": "Fuzzel", - "description": "Write ~/.config/fuzzel/themes/noctalia and reload", + "description": "Write {filepath} and reload", "description-missing": "Requires fuzzel launcher to be installed" }, "vesktop": { - "label": "Vesktop", - "description": "Write ~/.config/vesktop/themes/noctalia.theme.css", + "description": "Write {filepath}", "description-missing": "Requires vesktop Discord client to be installed" }, "pywalfox": { - "label": "Pywalfox (Firefox)", - "description": "Write ~/.cache/wal/colors.json and run pywalfox update", + "description": "Write {filepath} and run pywalfox update", "description-missing": "Requires pywalfox package to be installed" } }, @@ -1016,8 +1006,7 @@ "enter-width-pixels": "Enter width in pixels", "enter-command": "Enter command to execute (app or custom script)", "command-example": "echo \"Hello World\"", - "clock-horizontal": "HH:mm ddd, MMM dd", - "clock-vertical": "HH mm dd MM", + "search-wallpapers": "Type to filter wallpapers...", "search-launcher": "Search entries... or use > for commands", "search": "Search...", @@ -1067,15 +1056,7 @@ "mirrored": "Mirrored", "wave": "Wave" }, - "frame-rates": { - "30-fps": "30 FPS", - "60-fps": "60 FPS", - "100-fps": "100 FPS", - "120-fps": "120 FPS", - "144-fps": "144 FPS", - "165-fps": "165 FPS", - "240-fps": "240 FPS" - }, + "screen-recording": { "sources": { "portal": "Portal", @@ -1087,13 +1068,6 @@ "very-high": "Very high", "ultra": "Ultra" }, - "codecs": { - "h264": "H264", - "hevc": "HEVC", - "av1": "AV1", - "vp8": "VP8", - "vp9": "VP9" - }, "color-range": { "limited": "Limited", "full": "Full" diff --git a/Commons/I18n.qml b/Commons/I18n.qml index d9fe7fee..5bfc1380 100644 --- a/Commons/I18n.qml +++ b/Commons/I18n.qml @@ -9,7 +9,7 @@ Singleton { id: root property bool debug: true - property string debugForceLanguage: "" + property string debugForceLanguage: "de" property bool isLoaded: false property string langCode: "" diff --git a/Modules/Settings/Bar/WidgetSettings/ClockSettings.qml b/Modules/Settings/Bar/WidgetSettings/ClockSettings.qml index 099c5ff1..6214590a 100644 --- a/Modules/Settings/Bar/WidgetSettings/ClockSettings.qml +++ b/Modules/Settings/Bar/WidgetSettings/ClockSettings.qml @@ -106,7 +106,7 @@ ColumnLayout { Layout.fillWidth: true label: I18n.tr("bar.widget-settings.clock.horizontal-bar.label") description: I18n.tr("bar.widget-settings.clock.horizontal-bar.description") - placeholderText: I18n.tr("placeholders.clock-horizontal") + placeholderText: "HH:mm ddd, MMM dd" text: valueFormatHorizontal onTextChanged: valueFormatHorizontal = text Component.onCompleted: { @@ -129,7 +129,8 @@ ColumnLayout { Layout.fillWidth: true label: I18n.tr("bar.widget-settings.clock.vertical-bar.label") description: I18n.tr("bar.widget-settings.clock.vertical-bar.description") - placeholderText: I18n.tr("placeholders.clock-vertical") + // Tokens are Qt format tokens and must not be localized + placeholderText: "HH mm dd MM" text: valueFormatVertical onTextChanged: valueFormatVertical = text Component.onCompleted: { diff --git a/Modules/Settings/Tabs/ColorSchemeTab.qml b/Modules/Settings/Tabs/ColorSchemeTab.qml index 303b7098..80be38fb 100644 --- a/Modules/Settings/Tabs/ColorSchemeTab.qml +++ b/Modules/Settings/Tabs/ColorSchemeTab.qml @@ -337,8 +337,10 @@ ColumnLayout { defaultExpanded: false NCheckbox { - label: I18n.tr("settings.color-scheme.matugen.ui.gtk4.label") - description: I18n.tr("settings.color-scheme.matugen.ui.gtk4.description") + label: "GTK 4 (libadwaita)" + description: I18n.tr("settings.color-scheme.matugen.ui.gtk4.description", { + "filepath": "~/.config/gtk-4.0/gtk.css" + }) checked: Settings.data.matugen.gtk4 onToggled: checked => { Settings.data.matugen.gtk4 = checked @@ -348,8 +350,10 @@ ColumnLayout { } NCheckbox { - label: I18n.tr("settings.color-scheme.matugen.ui.gtk3.label") - description: I18n.tr("settings.color-scheme.matugen.ui.gtk3.description") + label: "GTK 3" + description: I18n.tr("settings.color-scheme.matugen.ui.gtk3.description", { + "filepath": "~/.config/gtk-3.0/gtk.css" + }) checked: Settings.data.matugen.gtk3 onToggled: checked => { Settings.data.matugen.gtk3 = checked @@ -359,8 +363,10 @@ ColumnLayout { } NCheckbox { - label: I18n.tr("settings.color-scheme.matugen.ui.qt6.label") - description: I18n.tr("settings.color-scheme.matugen.ui.qt6.description") + label: "Qt6ct" + description: I18n.tr("settings.color-scheme.matugen.ui.qt6.description", { + "filepath": "~/.config/qt6ct/colors/noctalia.conf" + }) checked: Settings.data.matugen.qt6 onToggled: checked => { Settings.data.matugen.qt6 = checked @@ -370,8 +376,10 @@ ColumnLayout { } NCheckbox { - label: I18n.tr("settings.color-scheme.matugen.ui.qt5.label") - description: I18n.tr("settings.color-scheme.matugen.ui.qt5.description") + label: "Qt5ct" + description: I18n.tr("settings.color-scheme.matugen.ui.qt5.description", { + "filepath": "~/.config/qt5ct/colors/noctalia.conf" + }) checked: Settings.data.matugen.qt5 onToggled: checked => { Settings.data.matugen.qt5 = checked @@ -389,8 +397,10 @@ ColumnLayout { defaultExpanded: false NCheckbox { - label: I18n.tr("settings.color-scheme.matugen.terminal.kitty.label") - description: ProgramCheckerService.kittyAvailable ? I18n.tr("settings.color-scheme.matugen.terminal.kitty.description") : I18n.tr("settings.color-scheme.matugen.terminal.kitty.description-missing") + label: "Kitty" + description: ProgramCheckerService.kittyAvailable ? I18n.tr("settings.color-scheme.matugen.terminal.kitty.description", { + "filepath": "~/.config/kitty/themes/noctalia.conf" + }) : I18n.tr("settings.color-scheme.matugen.terminal.kitty.description-missing") checked: Settings.data.matugen.kitty enabled: ProgramCheckerService.kittyAvailable opacity: ProgramCheckerService.kittyAvailable ? 1.0 : 0.6 @@ -404,8 +414,10 @@ ColumnLayout { } NCheckbox { - label: I18n.tr("settings.color-scheme.matugen.terminal.ghostty.label") - description: ProgramCheckerService.ghosttyAvailable ? I18n.tr("settings.color-scheme.matugen.terminal.ghostty.description") : I18n.tr("settings.color-scheme.matugen.terminal.ghostty.description-missing") + label: "Ghostty" + description: ProgramCheckerService.ghosttyAvailable ? I18n.tr("settings.color-scheme.matugen.terminal.ghostty.description", { + "filepath": "~/.config/ghostty/themes/noctalia" + }) : I18n.tr("settings.color-scheme.matugen.terminal.ghostty.description-missing") checked: Settings.data.matugen.ghostty enabled: ProgramCheckerService.ghosttyAvailable opacity: ProgramCheckerService.ghosttyAvailable ? 1.0 : 0.6 @@ -419,8 +431,10 @@ ColumnLayout { } NCheckbox { - label: I18n.tr("settings.color-scheme.matugen.terminal.foot.label") - description: ProgramCheckerService.footAvailable ? I18n.tr("settings.color-scheme.matugen.terminal.foot.description") : I18n.tr("settings.color-scheme.matugen.terminal.foot.description-missing") + label: "Foot" + description: ProgramCheckerService.footAvailable ? I18n.tr("settings.color-scheme.matugen.terminal.foot.description", { + "filepath": "~/.config/foot/themes/noctalia" + }) : I18n.tr("settings.color-scheme.matugen.terminal.foot.description-missing") checked: Settings.data.matugen.foot enabled: ProgramCheckerService.footAvailable opacity: ProgramCheckerService.footAvailable ? 1.0 : 0.6 @@ -442,8 +456,10 @@ ColumnLayout { defaultExpanded: false NCheckbox { - label: I18n.tr("settings.color-scheme.matugen.programs.fuzzel.label") - description: ProgramCheckerService.fuzzelAvailable ? I18n.tr("settings.color-scheme.matugen.programs.fuzzel.description") : I18n.tr("settings.color-scheme.matugen.programs.fuzzel.description-missing") + label: "Fuzzel" + description: ProgramCheckerService.fuzzelAvailable ? I18n.tr("settings.color-scheme.matugen.programs.fuzzel.description", { + "filepath": "~/.config/fuzzel/themes/noctalia" + }) : I18n.tr("settings.color-scheme.matugen.programs.fuzzel.description-missing") checked: Settings.data.matugen.fuzzel enabled: ProgramCheckerService.fuzzelAvailable opacity: ProgramCheckerService.fuzzelAvailable ? 1.0 : 0.6 @@ -457,8 +473,10 @@ ColumnLayout { } NCheckbox { - label: I18n.tr("settings.color-scheme.matugen.programs.vesktop.label") - description: ProgramCheckerService.vesktopAvailable ? I18n.tr("settings.color-scheme.matugen.programs.vesktop.description") : I18n.tr("settings.color-scheme.matugen.programs.vesktop.description-missing") + label: "Vesktop" + description: ProgramCheckerService.vesktopAvailable ? I18n.tr("settings.color-scheme.matugen.programs.vesktop.description", { + "filepath": "~/.config/vesktop/themes/noctalia.theme.css" + }) : I18n.tr("settings.color-scheme.matugen.programs.vesktop.description-missing") checked: Settings.data.matugen.vesktop enabled: ProgramCheckerService.vesktopAvailable opacity: ProgramCheckerService.vesktopAvailable ? 1.0 : 0.6 @@ -472,8 +490,10 @@ ColumnLayout { } NCheckbox { - label: I18n.tr("settings.color-scheme.matugen.programs.pywalfox.label") - description: ProgramCheckerService.pywalfoxAvailable ? I18n.tr("settings.color-scheme.matugen.programs.pywalfox.description") : I18n.tr("settings.color-scheme.matugen.programs.pywalfox.description-missing") + label: "Pywalfox" + description: ProgramCheckerService.pywalfoxAvailable ? I18n.tr("settings.color-scheme.matugen.programs.pywalfox.description", { + "filepath": "~/.cache/wal/colors.json" + }) : I18n.tr("settings.color-scheme.matugen.programs.pywalfox.description-missing") checked: Settings.data.matugen.pywalfox enabled: ProgramCheckerService.pywalfoxAvailable opacity: ProgramCheckerService.pywalfoxAvailable ? 1.0 : 0.6 diff --git a/Modules/Settings/Tabs/ScreenRecorderTab.qml b/Modules/Settings/Tabs/ScreenRecorderTab.qml index 4a42eda4..8c129117 100644 --- a/Modules/Settings/Tabs/ScreenRecorderTab.qml +++ b/Modules/Settings/Tabs/ScreenRecorderTab.qml @@ -76,28 +76,15 @@ ColumnLayout { NComboBox { label: I18n.tr("settings.screen-recorder.video.frame-rate.label") description: I18n.tr("settings.screen-recorder.video.frame-rate.description") - model: [{ - "key": "30", - "name": I18n.tr("options.frame-rates.30-fps") - }, { - "key": "60", - "name": I18n.tr("options.frame-rates.60-fps") - }, { - "key": "100", - "name": I18n.tr("options.frame-rates.100-fps") - }, { - "key": "120", - "name": I18n.tr("options.frame-rates.120-fps") - }, { - "key": "144", - "name": I18n.tr("options.frame-rates.144-fps") - }, { - "key": "165", - "name": I18n.tr("options.frame-rates.165-fps") - }, { - "key": "240", - "name": I18n.tr("options.frame-rates.240-fps") - }] + model: (function () { + const values = ["30", "60", "100", "120", "144", "165", "240"] + return values.map(function (v) { + return { + "key": v, + "name": (v + " FPS") + } + }) + })() currentKey: Settings.data.screenRecorder.frameRate onSelected: key => Settings.data.screenRecorder.frameRate = key } @@ -129,19 +116,19 @@ ColumnLayout { description: I18n.tr("settings.screen-recorder.video.video-codec.description") model: [{ "key": "h264", - "name": I18n.tr("options.screen-recording.codecs.h264") + "name": "H264" }, { "key": "hevc", - "name": I18n.tr("options.screen-recording.codecs.hevc") + "name": "HEVC" }, { "key": "av1", - "name": I18n.tr("options.screen-recording.codecs.av1") + "name": "AV1" }, { "key": "vp8", - "name": I18n.tr("options.screen-recording.codecs.vp8") + "name": "VP8" }, { "key": "vp9", - "name": I18n.tr("options.screen-recording.codecs.vp9") + "name": "VP9" }] currentKey: Settings.data.screenRecorder.videoCodec onSelected: key => Settings.data.screenRecorder.videoCodec = key From 7da4b1d63c1fc83dd03f2f89c99e0fb07a449f0d Mon Sep 17 00:00:00 2001 From: ItsLemmy Date: Wed, 24 Sep 2025 10:58:31 -0400 Subject: [PATCH 14/15] i18n: no debug --- Commons/I18n.qml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Commons/I18n.qml b/Commons/I18n.qml index d9fe7fee..20e59297 100644 --- a/Commons/I18n.qml +++ b/Commons/I18n.qml @@ -8,7 +8,7 @@ import qs.Commons Singleton { id: root - property bool debug: true + property bool debug: false property string debugForceLanguage: "" property bool isLoaded: false From aca831e54d749df2dfbf1977cc1421894ec2c4b8 Mon Sep 17 00:00:00 2001 From: Ly-sec Date: Wed, 24 Sep 2025 17:01:31 +0200 Subject: [PATCH 15/15] i18n: remove debug language --- Assets/Translations/en.json | 12 ++++++------ Commons/I18n.qml | 2 +- Modules/Settings/Tabs/ColorSchemeTab.qml | 12 ++++++------ 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/Assets/Translations/en.json b/Assets/Translations/en.json index 90497cc4..b8fe0026 100644 --- a/Assets/Translations/en.json +++ b/Assets/Translations/en.json @@ -450,15 +450,15 @@ "description": "Terminal emulator theming.", "kitty": { "description": "Write {filepath} and reload", - "description-missing": "Requires kitty terminal to be installed" + "description-missing": "Requires {app} to be installed" }, "ghostty": { "description": "Write {filepath} and reload", - "description-missing": "Requires ghostty terminal to be installed" + "description-missing": "Requires {app} to be installed" }, "foot": { "description": "Write {filepath} and reload", - "description-missing": "Requires foot terminal to be installed" + "description-missing": "Requires {app} to be installed" } }, "programs": { @@ -466,15 +466,15 @@ "description": "Application-specific theming.", "fuzzel": { "description": "Write {filepath} and reload", - "description-missing": "Requires fuzzel launcher to be installed" + "description-missing": "Requires {app} to be installed" }, "vesktop": { "description": "Write {filepath}", - "description-missing": "Requires vesktop Discord client to be installed" + "description-missing": "Requires {app} to be installed" }, "pywalfox": { "description": "Write {filepath} and run pywalfox update", - "description-missing": "Requires pywalfox package to be installed" + "description-missing": "Requires {app} to be installed" } }, "misc": { diff --git a/Commons/I18n.qml b/Commons/I18n.qml index 5bfc1380..d9fe7fee 100644 --- a/Commons/I18n.qml +++ b/Commons/I18n.qml @@ -9,7 +9,7 @@ Singleton { id: root property bool debug: true - property string debugForceLanguage: "de" + property string debugForceLanguage: "" property bool isLoaded: false property string langCode: "" diff --git a/Modules/Settings/Tabs/ColorSchemeTab.qml b/Modules/Settings/Tabs/ColorSchemeTab.qml index 80be38fb..713c7037 100644 --- a/Modules/Settings/Tabs/ColorSchemeTab.qml +++ b/Modules/Settings/Tabs/ColorSchemeTab.qml @@ -400,7 +400,7 @@ ColumnLayout { label: "Kitty" description: ProgramCheckerService.kittyAvailable ? I18n.tr("settings.color-scheme.matugen.terminal.kitty.description", { "filepath": "~/.config/kitty/themes/noctalia.conf" - }) : I18n.tr("settings.color-scheme.matugen.terminal.kitty.description-missing") + }) : I18n.tr("settings.color-scheme.matugen.terminal.kitty.description-missing", {"app": "kitty"}) checked: Settings.data.matugen.kitty enabled: ProgramCheckerService.kittyAvailable opacity: ProgramCheckerService.kittyAvailable ? 1.0 : 0.6 @@ -417,7 +417,7 @@ ColumnLayout { label: "Ghostty" description: ProgramCheckerService.ghosttyAvailable ? I18n.tr("settings.color-scheme.matugen.terminal.ghostty.description", { "filepath": "~/.config/ghostty/themes/noctalia" - }) : I18n.tr("settings.color-scheme.matugen.terminal.ghostty.description-missing") + }) : I18n.tr("settings.color-scheme.matugen.terminal.ghostty.description-missing", {"app": "ghostty"}) checked: Settings.data.matugen.ghostty enabled: ProgramCheckerService.ghosttyAvailable opacity: ProgramCheckerService.ghosttyAvailable ? 1.0 : 0.6 @@ -434,7 +434,7 @@ ColumnLayout { label: "Foot" description: ProgramCheckerService.footAvailable ? I18n.tr("settings.color-scheme.matugen.terminal.foot.description", { "filepath": "~/.config/foot/themes/noctalia" - }) : I18n.tr("settings.color-scheme.matugen.terminal.foot.description-missing") + }) : I18n.tr("settings.color-scheme.matugen.terminal.foot.description-missing", {"app": "foot"}) checked: Settings.data.matugen.foot enabled: ProgramCheckerService.footAvailable opacity: ProgramCheckerService.footAvailable ? 1.0 : 0.6 @@ -459,7 +459,7 @@ ColumnLayout { label: "Fuzzel" description: ProgramCheckerService.fuzzelAvailable ? I18n.tr("settings.color-scheme.matugen.programs.fuzzel.description", { "filepath": "~/.config/fuzzel/themes/noctalia" - }) : I18n.tr("settings.color-scheme.matugen.programs.fuzzel.description-missing") + }) : I18n.tr("settings.color-scheme.matugen.programs.fuzzel.description-missing", {"app": "fuzzel"}) checked: Settings.data.matugen.fuzzel enabled: ProgramCheckerService.fuzzelAvailable opacity: ProgramCheckerService.fuzzelAvailable ? 1.0 : 0.6 @@ -476,7 +476,7 @@ ColumnLayout { label: "Vesktop" description: ProgramCheckerService.vesktopAvailable ? I18n.tr("settings.color-scheme.matugen.programs.vesktop.description", { "filepath": "~/.config/vesktop/themes/noctalia.theme.css" - }) : I18n.tr("settings.color-scheme.matugen.programs.vesktop.description-missing") + }) : I18n.tr("settings.color-scheme.matugen.programs.vesktop.description-missing", {"app": "vesktop"}) checked: Settings.data.matugen.vesktop enabled: ProgramCheckerService.vesktopAvailable opacity: ProgramCheckerService.vesktopAvailable ? 1.0 : 0.6 @@ -493,7 +493,7 @@ ColumnLayout { label: "Pywalfox" description: ProgramCheckerService.pywalfoxAvailable ? I18n.tr("settings.color-scheme.matugen.programs.pywalfox.description", { "filepath": "~/.cache/wal/colors.json" - }) : I18n.tr("settings.color-scheme.matugen.programs.pywalfox.description-missing") + }) : I18n.tr("settings.color-scheme.matugen.programs.pywalfox.description-missing", {"app": "pywalfox"}) checked: Settings.data.matugen.pywalfox enabled: ProgramCheckerService.pywalfoxAvailable opacity: ProgramCheckerService.pywalfoxAvailable ? 1.0 : 0.6