diff --git a/Assets/Translations/de.json b/Assets/Translations/de.json
new file mode 100644
index 00000000..589ea73e
--- /dev/null
+++ b/Assets/Translations/de.json
@@ -0,0 +1,1218 @@
+{
+ "settings": {
+ "general": {
+ "title": "Allgemein",
+
+ "profile": {
+ "section": {
+ "label": "Profil",
+ "description": "Bearbeiten Sie Ihre Benutzerdaten und Ihren Avatar."
+ },
+ "picture": {
+ "label": "{user}s Profilbild",
+ "description": "Ihr Profilbild, das in der gesamten Benutzeroberfläche angezeigt wird."
+ },
+ "select-avatar": "Avatar-Bild auswählen"
+ },
+
+ "ui": {
+ "section": {
+ "label": "Benutzeroberfläche",
+ "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": "Eckenradius",
+ "description": "Steuert die Rundung der Ecken von Fenstern, Buttons und anderen Elementen."
+ },
+ "animation-speed": {
+ "label": "Animationsgeschwindigkeit",
+ "description": "Globale Animationsgeschwindigkeit anpassen."
+ }
+ },
+ "screen-corners": {
+ "section": {
+ "label": "Bildschirmecken",
+ "description": "Bildschirmecken-Rundung und visuelle Effekte anpassen."
+ },
+ "show-corners": {
+ "label": "Bildschirmecken anzeigen",
+ "description": "Gerundete Ecken am Rand des Bildschirms anzeigen."
+ },
+ "solid-black": {
+ "label": "Schwarze Ecken",
+ "description": "Schwarze Ecken anstelle der Statusleisten-Hintergrundfarbe verwenden."
+ },
+ "radius": {
+ "label": "Bildschirmecken-Radius",
+ "description": "Rundung der Bildschirmecken anpassen."
+ }
+ },
+ "fonts": {
+ "section": {
+ "label": "Schriftarten",
+ "description": "Wählen Sie die in der Benutzeroberfläche verwendeten Schriftarten."
+ },
+ "default": {
+ "label": "Standard-Schriftart",
+ "description": "Hauptschriftart für die gesamte Benutzeroberfläche.",
+ "placeholder": "Standard-Schriftart auswählen...",
+ "search-placeholder": "Schriftarten suchen..."
+ },
+ "monospace": {
+ "label": "Monospace-Schriftart",
+ "description": "Monospace-Schriftart für Zahlen und Statistik-Anzeigen.",
+ "placeholder": "Monospace-Schriftart auswählen...",
+ "search-placeholder": "Monospace-Schriftarten suchen..."
+ },
+ "accent": {
+ "label": "Akzent-Schriftart",
+ "description": "Große Schriftart für hervorgehobene Anzeigen.",
+ "placeholder": "Display-Schriftart auswählen...",
+ "search-placeholder": "Display-Schriftarten suchen..."
+ }
+ }
+ },
+ "audio": {
+ "title": "Audio",
+ "volumes": {
+ "section": {
+ "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 schalten",
+ "description": "Die Haupt-Audio-Ausgabe des Systems stumm schalten."
+ },
+ "input-volume": {
+ "label": "Eingabe-Lautstärke",
+ "description": "Mikrofon-Eingabe-Lautstärke."
+ },
+ "mute-input": {
+ "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 anpassen (Mausrad, Tastenkombinationen)."
+ }
+ },
+ "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": "Medienplayer",
+ "description": "Bevorzugte und ignorierte Medienanwendungen festlegen."
+ },
+ "primary-player": {
+ "label": "Hauptplayer",
+ "description": "Stichwort eingeben, um Ihren Hauptplayer zu identifizieren.",
+ "placeholder": "z.B. spotify, vlc, mpv"
+ },
+ "excluded-player": {
+ "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": "Visualisierungstyp",
+ "description": "Visualisierungstyp für Medienwiedergabe wählen"
+ },
+ "frame-rate": {
+ "label": "Bildrate",
+ "description": "Höhere Raten sind flüssiger, verbrauchen aber mehr Ressourcen."
+ }
+ }
+ },
+ "display": {
+ "title": "Anzeige",
+ "monitors": {
+ "section": {
+ "label": "Monitor-spezifische 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 anpassen (Mausrad und Tastenkombinationen)."
+ }
+ },
+ "night-light": {
+ "section": {
+ "label": "Nachtlicht",
+ "description": "Blaulicht-Emission reduzieren für besseren Schlaf und weniger Augenbelastung."
+ },
+ "enable": {
+ "label": "Nachtlicht aktivieren",
+ "description": "Warmen Farbfilter anwenden, um Blaulicht-Emission zu reduzieren."
+ },
+ "temperature": {
+ "label": "Farbtemperatur",
+ "description": "Farbwärme für Nacht- und Tageszeit einstellen.",
+ "night": "Nacht",
+ "day": "Tag"
+ },
+ "auto-schedule": {
+ "label": "Automatische Planung",
+ "description": "Basierend auf Sonnenuntergang und Sonnenaufgang in {location} - empfohlen."
+ },
+ "manual-schedule": {
+ "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": "Aktivierung erzwingen",
+ "description": "Ignoriert die Planung und wendet den Nachtfilter sofort an."
+ }
+ }
+ },
+ "bar": {
+ "title": "Statusleiste",
+ "appearance": {
+ "section": {
+ "label": "Erscheinungsbild",
+ "description": "Erscheinungsbild und Position der Statusleiste anpassen."
+ },
+ "position": {
+ "label": "Statusleistenposition",
+ "description": "Wählen Sie, wo die Statusleiste auf dem Bildschirm platziert werden soll."
+ },
+ "density": {
+ "label": "Statusleistendichte",
+ "description": "Innenabstand der Statusleiste für kompaktes oder geräumiges Aussehen anpassen."
+ },
+ "background-opacity": {
+ "label": "Hintergrund-Transparenz",
+ "description": "Hintergrund-Transparenz der Statusleiste anpassen."
+ },
+ "show-capsule": {
+ "label": "Kapsel anzeigen",
+ "description": "Widget-Hintergründe anzeigen."
+ },
+ "floating": {
+ "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 Statusleiste anpassen.",
+ "vertical": "Vertikal",
+ "horizontal": "Horizontal"
+ }
+ },
+ "widgets": {
+ "section": {
+ "label": "Widget-Positionierung",
+ "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 sind."
+ }
+ }
+ },
+ "dock": {
+ "title": "Dock",
+ "appearance": {
+ "section": {
+ "label": "Erscheinungsbild",
+ "description": "Verhalten und Erscheinungsbild des Docks anpassen."
+ },
+ "auto-hide": {
+ "label": "Automatisch ausblenden",
+ "description": "Automatisch ausblenden, wenn nicht in Gebrauch."
+ },
+ "exclusive-zone": {
+ "label": "Exklusive Zone",
+ "description": "Fensterüberlappung verhindern."
+ },
+ "background-opacity": {
+ "label": "Hintergrund-Transparenz",
+ "description": "Hintergrund-Transparenz des Docks anpassen."
+ },
+ "floating-distance": {
+ "label": "Dock-Schwebeabstand",
+ "description": "Schwebeabstand vom Bildschirmrand anpassen."
+ }
+ },
+ "monitors": {
+ "section": {
+ "label": "Monitor-Anzeige",
+ "description": "Monitor auswählen, auf dem das Dock angezeigt werden soll."
+ }
+ }
+ },
+ "launcher": {
+ "title": "Starter",
+ "settings": {
+ "section": {
+ "label": "Erscheinungsbild",
+ "description": "Verhalten und Erscheinungsbild des Starters anpassen."
+ },
+ "position": {
+ "label": "Position",
+ "description": "Wählen Sie, wo das Starter-Panel erscheint."
+ },
+ "background-opacity": {
+ "label": "Hintergrund-Transparenz",
+ "description": "Hintergrund-Transparenz des Starters anpassen."
+ },
+ "clipboard-history": {
+ "label": "Zwischenablage-Verlauf aktivieren",
+ "description": "Zugriff auf zuvor kopierte Elemente über den Starter."
+ },
+ "sort-by-usage": {
+ "label": "Nach Häufigkeit sortieren",
+ "description": "Wenn aktiviert, erscheinen häufig gestartete Apps zuerst in der Liste."
+ },
+ "use-app2unit": {
+ "label": "App2Unit zum Starten von Anwendungen verwenden",
+ "description": "Verwendet eine alternative Startmethode zur besseren Verwaltung von App-Prozessen und Problemvermeidung."
+ }
+ }
+ },
+ "notifications": {
+ "title": "Benachrichtigungen",
+ "settings": {
+ "section": {
+ "label": "Erscheinungsbild",
+ "description": "Erscheinungsbild 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."
+ }
+ },
+ "duration": {
+ "low-urgency": {
+ "label": "Niedrige Dringlichkeit",
+ "description": "Wie lange Benachrichtigungen niedriger Priorität sichtbar bleiben."
+ },
+ "normal-urgency": {
+ "label": "Normale Dringlichkeit",
+ "description": "Wie lange Benachrichtigungen normaler Priorität sichtbar bleiben."
+ },
+ "critical-urgency": {
+ "label": "Kritische Dringlichkeit",
+ "description": "Wie lange kritische Benachrichtigungen sichtbar bleiben."
+ }
+ },
+ "monitors": {
+ "section": {
+ "label": "Monitor-Anzeige",
+ "description": "Benachrichtigungen auf bestimmten Monitoren anzeigen. Standard ist alle, wenn keine ausgewählt sind."
+ }
+ }
+ },
+ "wallpaper": {
+ "title": "Hintergrundbild",
+ "settings": {
+ "section": {
+ "label": "Hintergrundbild-Einstellungen",
+ "description": "Steuern Sie, wie Hintergrundbilder verwaltet und angezeigt werden."
+ },
+ "enable-management": {
+ "label": "Hintergrundbild-Verwaltung aktivieren",
+ "description": "Hintergrundbilder mit Noctalia verwalten. Deaktivieren, wenn Sie eine andere Anwendung bevorzugen."
+ },
+ "folder": {
+ "label": "Hintergrundbild-Ordner",
+ "description": "Pfad zu Ihrem Haupt-Hintergrundbild-Ordner.",
+ "tooltip": "Nach Hintergrundbild-Ordner suchen"
+ },
+ "monitor-specific": {
+ "label": "Monitor-spezifische Verzeichnisse",
+ "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 & Verhalten"
+ },
+ "fill-mode": {
+ "label": "Füllmodus",
+ "description": "Wählen Sie, wie das Bild skaliert werden soll, um zur Auflösung Ihres Monitors zu passen."
+ },
+ "fill-color": {
+ "label": "Füllfarbe",
+ "description": "Füllfarbe wählen, 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, gefiederten Effekt auf die Kante von Übergängen an."
+ }
+ },
+ "automation": {
+ "section": {
+ "label": "Automatisierung"
+ },
+ "random-wallpaper": {
+ "label": "Zufälliges Hintergrundbild",
+ "description": "Zufällige Hintergrundbild-Wechsel in regelmäßigen Abständen planen."
+ },
+ "interval": {
+ "label": "Hintergrundbild-Intervall",
+ "description": "Wie oft Hintergrundbilder automatisch gewechselt werden sollen."
+ },
+ "custom-interval": {
+ "label": "Benutzerdefiniertes 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 Theme für einfachere Betrachtung bei Nacht."
+ },
+ "enable-matugen": {
+ "label": "Matugen aktivieren",
+ "description": "Automatisch Farben basierend auf Ihrem aktiven Hintergrundbild generieren."
+ }
+ },
+ "predefined": {
+ "section": {
+ "label": "Vordefinierte Farbschemata",
+ "description": "Um diese Farbschemata zu verwenden, müssen Sie Matugen ausschalten. Mit aktiviertem Matugen werden Farben automatisch aus Ihrem Hintergrundbild generiert."
+ }
+ },
+ "matugen": {
+ "section": {
+ "label": "Matugen-Vorlagen",
+ "description": "Farben auf externe Anwendungen anwenden."
+ },
+ "ui": {
+ "label": "UI",
+ "description": "Desktop-Umgebung und UI-Toolkit-Theming.",
+ "gtk4": {
+ "description": "Schreibt {filepath}"
+ },
+ "gtk3": {
+ "description": "Schreibt {filepath}"
+ },
+ "qt6": {
+ "description": "Schreibt {filepath}"
+ },
+ "qt5": {
+ "description": "Schreibt {filepath}"
+ }
+ },
+ "terminal": {
+ "label": "Terminal",
+ "description": "Terminal-Emulator-Theming.",
+ "kitty": {
+ "description": "Schreibt {filepath} und lädt neu",
+ "description-missing": "Erfordert kitty Terminal"
+ },
+ "ghostty": {
+ "description": "Schreibt {filepath} und lädt neu",
+ "description-missing": "Erfordert ghostty Terminal"
+ },
+ "foot": {
+ "description": "Schreibt {filepath} und lädt neu",
+ "description-missing": "Erfordert foot Terminal"
+ }
+ },
+ "programs": {
+ "label": "Programme",
+ "description": "Anwendungsspezifisches Theming.",
+ "fuzzel": {
+ "description": "Schreibt {filepath} und lädt neu",
+ "description-missing": "Erfordert fuzzel Starter"
+ },
+ "vesktop": {
+ "description": "Schreibt {filepath}",
+ "description-missing": "Erfordert vesktop Discord-Client"
+ },
+ "pywalfox": {
+ "description": "Schreibt {filepath} und führt pywalfox update aus",
+ "description-missing": "Erfordert pywalfox Paket"
+ }
+ },
+ "misc": {
+ "label": "Verschiedenes",
+ "description": "Zusätzliche Konfigurationsoptionen.",
+ "user-templates": {
+ "label": "Benutzer-Vorlagen",
+ "description": "Benutzerdefinierte Matugen-Konfiguration aus ~/.config/matugen/config.toml aktivieren"
+ }
+ }
+ }
+ },
+ "location": {
+ "title": "Standort",
+ "location": {
+ "section": {
+ "label": "Ihr Standort",
+ "description": "Genaues Wetter und Nachtlicht-Planung durch Festlegung Ihres Standorts erhalten."
+ },
+ "search": {
+ "label": "Nach einem Standort suchen",
+ "description": "z.B. Berlin, Deutschland",
+ "placeholder": "Standortnamen eingeben"
+ }
+ },
+ "weather": {
+ "section": {
+ "label": "Wetter",
+ "description": "Bevorzugte Temperatureinheit wählen."
+ },
+ "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 erscheinen."
+ },
+ "12hour-format": {
+ "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": {
+ "label": "Wochennummern anzeigen",
+ "description": "Zeigt die Woche des Jahres (z.B. Woche 38) im Kalender an."
+ }
+ }
+ },
+ "network": {
+ "title": "Netzwerk",
+ "section": {
+ "description": "WLAN- und Bluetooth-Verbindungen verwalten."
+ },
+ "wifi": {
+ "label": "WLAN aktivieren"
+ },
+ "bluetooth": {
+ "label": "Bluetooth aktivieren"
+ }
+ },
+ "screen-recorder": {
+ "title": "Bildschirmrekorder",
+ "general": {
+ "section": {
+ "label": "Allgemeine Einstellungen",
+ "description": "Bildschirmaufnahme-Ausgabe und -Inhalt 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-Aufnahme-Optionen konfigurieren."
+ },
+ "video-source": {
+ "label": "Video-Quelle",
+ "description": "Portal wird empfohlen, bei Artefakten versuchen Sie Bildschirm."
+ },
+ "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 Dateigrößen."
+ },
+ "video-codec": {
+ "label": "Video-Codec",
+ "description": "h264 ist der gebräuchlichste Codec."
+ },
+ "color-range": {
+ "label": "Farbbereich",
+ "description": "Begrenzt wird für bessere Kompatibilität empfohlen."
+ }
+ },
+ "audio": {
+ "section": {
+ "label": "Audio-Einstellungen",
+ "description": "Audio-Aufnahme-Optionen konfigurieren."
+ },
+ "audio-source": {
+ "label": "Audio-Quelle",
+ "description": "Audio-Quelle für die Aufnahme."
+ },
+ "audio-codec": {
+ "label": "Audio-Codec",
+ "description": "Opus wird für beste Leistung und kleinste Audio-Größe empfohlen."
+ }
+ }
+ },
+ "about": {
+ "title": "Über",
+ "noctalia": {
+ "section": {
+ "label": "Noctalia Shell",
+ "description": "Eine elegante und minimalistische Desktop-Shell, sorgfältig 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": "Ein Dankeschön an unseren {count} großartigen Mitwirkenden!",
+ "description_plural": "Ein Dankeschön 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 sich das Hintergrundbild ändert.",
+ "placeholder": "z.B. notify-send \"Hintergrundbild\" \"Geändert\""
+ },
+ "theme-changed": {
+ "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 (getrennt)\n• Test-Buttons führen mit aktuellen Werten aus"
+ },
+ "parameters": {
+ "label": "Verfügbare Parameter",
+ "description": "• Hintergrundbild-Hook: $1 = Hintergrundbild-Pfad, $2 = Bildschirmname\n• Theme-Wechsel-Hook: $1 = true/false (Dunkelmodus-Status)"
+ }
+ }
+ }
+ },
+ "widgets": {
+ "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",
+ "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"
+ }
+ },
+ "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 Statusleiste",
+ "description": "Tipp: Verwenden Sie \\n, um einen Zeilenumbruch zu erstellen."
+ },
+ "vertical-bar": {
+ "label": "Vertikale Statusleiste",
+ "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:"
+ },
+ "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": {
+ "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ü",
+ "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\"",
+
+ "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": {
+ "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",
+ "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"
+ },
+
+ "screen-recording": {
+ "sources": {
+ "portal": "Portal",
+ "screen": "Bildschirm"
+ },
+ "quality": {
+ "medium": "Mittel",
+ "high": "Hoch",
+ "very-high": "Sehr hoch",
+ "ultra": "Ultra"
+ },
+ "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": {
+ "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",
+ "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"
+ },
+ "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",
+ "password": "Passwort:",
+ "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
new file mode 100644
index 00000000..c7770354
--- /dev/null
+++ b/Assets/Translations/en.json
@@ -0,0 +1,1248 @@
+{
+ "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."
+ },
+ "select-avatar": "Select avatar image"
+ },
+
+ "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."
+ },
+ "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."
+ },
+ "radius": {
+ "label": "Screen corners radius",
+ "description": "Adjust the rounded corners of the screen."
+ }
+ },
+ "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": "Monitors 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."
+ },
+ "always-on-top": {
+ "label": "Always on top",
+ "description": "Display notifications above fullscreen windows and other layers."
+ }
+ },
+ "duration": {
+ "section": {
+ "label": "Notification duration",
+ "description": "Configure how long notifications stay visible based on their urgency level."
+ },
+ "respect-expire": {
+ "label": "Respect expire timeout",
+ "description": "Use the expire timeout set in the notification."
+ },
+ "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": {
+ "section": {
+ "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": {
+ "description": "Write {filepath}"
+ },
+ "gtk3": {
+ "description": "Write {filepath}"
+ },
+ "qt6": {
+ "description": "Write {filepath}"
+ },
+ "qt5": {
+ "description": "Write {filepath}"
+ }
+ },
+ "terminal": {
+ "label": "Terminal",
+ "description": "Terminal emulator theming.",
+ "kitty": {
+ "description": "Write {filepath} and reload",
+ "description-missing": "Requires {app} to be installed"
+ },
+ "ghostty": {
+ "description": "Write {filepath} and reload",
+ "description-missing": "Requires {app} to be installed"
+ },
+ "foot": {
+ "description": "Write {filepath} and reload",
+ "description-missing": "Requires {app} to be installed"
+ }
+ },
+ "programs": {
+ "label": "Programs",
+ "description": "Application-specific theming.",
+ "fuzzel": {
+ "description": "Write {filepath} and reload",
+ "description-missing": "Requires {app} to be installed"
+ },
+ "vesktop": {
+ "description": "Write {filepath}",
+ "description-missing": "Requires {app} to be installed"
+ },
+ "pywalfox": {
+ "description": "Write {filepath} and run pywalfox update",
+ "description-missing": "Requires {app} 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)"
+ }
+ }
+ }
+ },
+ "widgets": {
+ "tooltip": {
+ "placeholder": "Placeholder"
+ },
+ "file-picker": {
+ "select-folder": "Select Folder",
+ "select-file": "Select File"
+ },
+ "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:"
+ },
+ "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": {
+ "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"
+ }
+ },
+ "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",
+ "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",
+ "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",
+ "power-profile": "'{profile}' power profile",
+ "keyboard-layout": "{layout} keyboard layout"
+ },
+ "clock": {
+ "tooltip": "Open calendar"
+ },
+ "dock": {
+ "menu": {
+ "focus": "Focus",
+ "pin": "Pin",
+ "unpin": "Unpin",
+ "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\"",
+
+ "search-wallpapers": "Type to filter wallpapers...",
+ "search-launcher": "Search entries... or use > for commands",
+ "search": "Search...",
+ "select": "Select",
+ "cancel": "Cancel",
+ "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",
+ "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"
+ },
+
+ "screen-recording": {
+ "sources": {
+ "portal": "Portal",
+ "screen": "Screen"
+ },
+ "quality": {
+ "medium": "Medium",
+ "high": "High",
+ "very-high": "Very high",
+ "ultra": "Ultra"
+ },
+ "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"
+ }
+ }
+ },
+ "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",
+ "logout": "Logout",
+ "shutdown": "Shutdown"
+ },
+ "plugins": {
+ "applications": "Applications",
+ "clipboard": "Clipboard history",
+ "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}",
+ "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",
+ "password": "Password:",
+ "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/Assets/Translations/fr.json b/Assets/Translations/fr.json
new file mode 100644
index 00000000..a0a704d4
--- /dev/null
+++ b/Assets/Translations/fr.json
@@ -0,0 +1,1259 @@
+{
+ "settings": {
+ "general": {
+ "title": "Général",
+ "profile": {
+ "section": {
+ "label": "Profil",
+ "description": "Modifiez vos informations utilisateur et votre avatar."
+ },
+ "picture": {
+ "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 les 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 les moniteur",
+ "description": "Choisissez sur quels moniteurs 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."
+ }
+ },
+ "duration":{
+ "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": {
+ "section": {
+ "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/Bin/i18n-check.sh b/Bin/i18n-check.sh
new file mode 100755
index 00000000..e86abd7b
--- /dev/null
+++ b/Bin/i18n-check.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+
+# Comprehensive i18n checker for QML files
+# Finds hardcoded strings in various QML properties
+
+find . -name "*.qml" -type f | while read -r file; do
+ # Skip if file doesn't exist or is not readable
+ [[ ! -r "$file" ]] && continue
+
+ # 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')
+
+ # 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/Commons/I18n.qml b/Commons/I18n.qml
new file mode 100644
index 00000000..20e59297
--- /dev/null
+++ b/Commons/I18n.qml
@@ -0,0 +1,351 @@
+pragma Singleton
+
+import QtQuick
+import Quickshell
+import Quickshell.Io
+import qs.Commons
+
+Singleton {
+ id: root
+
+ property bool debug: false
+ property string debugForceLanguage: ""
+
+ property bool isLoaded: false
+ property string langCode: ""
+ property var availableLanguages: []
+ property var translations: ({})
+ property var fallbackTranslations: ({})
+
+ // Signals for reactive updates
+ 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
+ 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 fallback 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}`)
+ }
+ }
+
+ Component.onCompleted: {
+ Logger.log("I18n", "Service started")
+ 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 !== "") {
+ 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
+ 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 first available language (preferably "en" if available)
+ const fallbackLang = availableLanguages.includes("en") ? "en" : availableLanguages[0]
+ setLanguage(fallbackLang)
+ }
+
+ // -------------------------------------------
+ function setLanguage(newLangCode) {
+ if (newLangCode !== langCode && availableLanguages.includes(newLangCode)) {
+ langCode = newLangCode
+ Logger.log("I18n", `Language set to "${langCode}"`)
+ languageChanged(langCode)
+ loadTranslations()
+ } else if (!availableLanguages.includes(newLangCode)) {
+ Logger.warn("I18n", `Language "${newLangCode}" is not available`)
+ }
+ }
+
+ // -------------------------------------------
+ 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 english and english is available
+ if (langCode !== "en" && availableLanguages.includes("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) {
+ // if (debug) {
+ // 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 && availableLanguages.includes("en") && langCode !== "en") {
+ 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}`
+ } else if (notFound) {
+ // No fallback available
+ return `## ${key} ##`
+ }
+
+ 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 tr(pluralKey, finalInterpolations)
+ }
+}
diff --git a/Commons/Settings.qml b/Commons/Settings.qml
index 7ba3be04..7f378ed9 100644
--- a/Commons/Settings.qml
+++ b/Commons/Settings.qml
@@ -497,22 +497,13 @@ Singleton {
// -----------------------------------------------------
// Kickoff essential services
function kickOffServices() {
- // 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()
}
}
diff --git a/Modules/Bar/Bluetooth/BluetoothPanel.qml b/Modules/Bar/Bluetooth/BluetoothPanel.qml
index ce9fafc6..3f4773ab 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
@@ -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()
@@ -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,8 +138,8 @@ NPanel {
// Known devices
BluetoothDevicesList {
- label: "Known devices"
- tooltipText: "Left click to connect. Right click to forget."
+ label: I18n.tr("bluetooth.panel.known-devices")
+ tooltipText: I18n.tr("tooltips.connect-disconnect-devices")
property var items: {
if (!BluetoothService.adapter || !Bluetooth.devices)
return []
@@ -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..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()
@@ -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..ebb8a0b7 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
@@ -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()
}
@@ -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
@@ -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
}
@@ -295,7 +297,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 +313,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 +329,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 +347,7 @@ NPanel {
NText {
id: savedText
anchors.centerIn: parent
- text: "Saved"
+ text: I18n.tr("wifi.panel.saved")
font.pointSize: Style.fontSizeXXS * scaling
color: Color.mOnSurfaceVariant
}
@@ -367,7 +369,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
}
@@ -376,10 +378,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 +399,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 +459,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 +467,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 +513,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 +522,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 +563,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/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/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/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/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/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 26f06240..3d92106c 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: "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/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/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/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 e1fa678a..775a31d6 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: "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..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
// }
@@ -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..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: `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 +38,9 @@ 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 +50,9 @@ 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..9b619edf 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
}
@@ -56,7 +58,7 @@ NBox {
}
NIconButton {
icon: "settings"
- tooltipText: "Open settings"
+ tooltipText: I18n.tr("tooltips.open-settings")
onClicked: {
settingsPanel.requestedTab = SettingsPanel.Tab.General
settingsPanel.open()
@@ -66,7 +68,7 @@ NBox {
NIconButton {
id: powerButton
icon: "power"
- tooltipText: "Session Menu"
+ tooltipText: I18n.tr("tooltips.session-menu")
onClicked: {
sessionMenuPanel.open()
controlCenterPanel.close()
@@ -76,7 +78,7 @@ NBox {
NIconButton {
id: closeButton
icon: "close"
- tooltipText: "Close side panel"
+ tooltipText: I18n.tr("tooltips.close")
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/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/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..e33152a1 100644
--- a/Modules/Launcher/Plugins/CalculatorPlugin.qml
+++ b/Modules/Launcher/Plugins/CalculatorPlugin.qml
@@ -1,10 +1,11 @@
import QtQuick
import qs.Services
+import qs.Commons
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 >
@@ -14,7 +15,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 +37,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 +60,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 9de69903..1969606c 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
@@ -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/LockScreen/LockScreen.qml b/Modules/LockScreen/LockScreen.qml
index 16219f92..a1b0622c 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
@@ -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
@@ -486,7 +488,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 +500,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 +904,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 +955,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 +1007,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/Notification.qml b/Modules/Notification/Notification.qml
index 244073ae..c00d9829 100644
--- a/Modules/Notification/Notification.qml
+++ b/Modules/Notification/Notification.qml
@@ -307,7 +307,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
}
@@ -318,7 +318,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
@@ -399,7 +399,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 35f92d0a..f5bd43d7 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
@@ -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()
}
@@ -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
@@ -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
@@ -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..0a9c2271 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",
- "subtitle": "Lock your session"
+ "title": I18n.tr("session-menu.lock"),
+ "subtitle": I18n.tr("session-menu.lock-subtitle")
}, {
"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",
- "subtitle": "End your session"
+ "title": I18n.tr("session-menu.logout"),
+ "subtitle": I18n.tr("session-menu.end-subtitle")
}, {
"action": "shutdown",
"icon": "shutdown",
- "title": "Shutdown",
+ "title": I18n.tr("session-menu.shutdown"),
"subtitle": "Turn off the system",
"isShutdown": true
}]
@@ -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
@@ -277,7 +280,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
@@ -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/Bar/BarSectionEditor.qml b/Modules/Settings/Bar/BarSectionEditor.qml
index 39dc62e3..6e1fb69a 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
@@ -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: {
@@ -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"
@@ -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/BarWidgetSettingsDialog.qml b/Modules/Settings/Bar/BarWidgetSettingsDialog.qml
index 86344997..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 {
@@ -63,7 +62,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
@@ -101,13 +102,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..addf7ff8 100644
--- a/Modules/Settings/Bar/WidgetSettings/BatterySettings.qml
+++ b/Modules/Settings/Bar/WidgetSettings/BatterySettings.qml
@@ -25,30 +25,26 @@ 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 {
- key: "onhover"
- name: "On hover"
- }
- ListElement {
- key: "alwaysShow"
- name: "Always show"
- }
- ListElement {
- key: "alwaysHide"
- name: "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
}
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..c21d7aae 100644
--- a/Modules/Settings/Bar/WidgetSettings/BrightnessSettings.qml
+++ b/Modules/Settings/Bar/WidgetSettings/BrightnessSettings.qml
@@ -23,23 +23,19 @@ 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 {
- key: "onhover"
- name: "On hover"
- }
- ListElement {
- key: "alwaysShow"
- name: "Always show"
- }
- ListElement {
- key: "alwaysHide"
- name: "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/ClockSettings.qml b/Modules/Settings/Bar/WidgetSettings/ClockSettings.qml
index 60e2794c..6214590a 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,9 @@ 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")
+ // Tokens are Qt format tokens and must not be localized
placeholderText: "HH mm dd MM"
text: valueFormatVertical
onTextChanged: valueFormatVertical = text
@@ -151,7 +152,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..0733091a 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,24 +58,24 @@ ColumnLayout {
NTextInput {
id: leftClickExecInput
Layout.fillWidth: true
- label: "Left click"
- placeholderText: "Enter command to execute (app or custom script)"
+ label: I18n.tr("bar.widget-settings.custom-button.left-click")
+ placeholderText: I18n.tr("placeholders.enter-command")
text: widgetData?.leftClickExec || widgetMetadata.leftClickExec
}
NTextInput {
id: rightClickExecInput
Layout.fillWidth: true
- label: "Right click"
- placeholderText: "Enter command to execute (app or custom script)"
+ label: I18n.tr("bar.widget-settings.custom-button.right-click")
+ placeholderText: I18n.tr("placeholders.enter-command")
text: widgetData?.rightClickExec || widgetMetadata.rightClickExec
}
NTextInput {
id: middleClickExecInput
Layout.fillWidth: true
- label: "Middle click"
- placeholderText: "Enter command to execute (app or custom script)"
+ label: I18n.tr("bar.widget-settings.custom-button.middle-click")
+ placeholderText: I18n.tr("placeholders.enter-command")
text: widgetData.middleClickExec || widgetMetadata.middleClickExec
}
@@ -84,23 +84,23 @@ 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."
- placeholderText: "echo \"Hello World\""
+ 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: I18n.tr("placeholders.command-example")
text: widgetData?.textCommand || widgetMetadata.textCommand
}
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..d3551044 100644
--- a/Modules/Settings/Bar/WidgetSettings/KeyboardLayoutSettings.qml
+++ b/Modules/Settings/Bar/WidgetSettings/KeyboardLayoutSettings.qml
@@ -23,23 +23,19 @@ 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 {
- key: "onhover"
- name: "On hover"
- }
- ListElement {
- key: "forceOpen"
- name: "Force Open"
- }
- ListElement {
- key: "alwaysHide"
- name: "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 fb70f9da..b357fa12 100644
--- a/Modules/Settings/Bar/WidgetSettings/MediaMiniSettings.qml
+++ b/Modules/Settings/Bar/WidgetSettings/MediaMiniSettings.qml
@@ -27,34 +27,30 @@ 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"
- model: ListModel {
- ListElement {
- key: "linear"
- name: "Linear"
- }
- ListElement {
- key: "mirrored"
- name: "Mirrored"
- }
- ListElement {
- key: "wave"
- name: "Wave"
- }
- }
+ 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")
+ }]
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 e8e0465d..5091474d 100644
--- a/Modules/Settings/Bar/WidgetSettings/MicrophoneSettings.qml
+++ b/Modules/Settings/Bar/WidgetSettings/MicrophoneSettings.qml
@@ -23,23 +23,19 @@ 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 {
- key: "onhover"
- name: "On hover"
- }
- ListElement {
- key: "alwaysShow"
- name: "Always show"
- }
- ListElement {
- key: "alwaysHide"
- name: "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/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..7c6b8b17 100644
--- a/Modules/Settings/Bar/WidgetSettings/SpacerSettings.qml
+++ b/Modules/Settings/Bar/WidgetSettings/SpacerSettings.qml
@@ -22,9 +22,9 @@ 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"
+ placeholderText: I18n.tr("placeholders.enter-width-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..2781f4a6 100644
--- a/Modules/Settings/Bar/WidgetSettings/VolumeSettings.qml
+++ b/Modules/Settings/Bar/WidgetSettings/VolumeSettings.qml
@@ -23,23 +23,19 @@ 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 {
- key: "onhover"
- name: "On hover"
- }
- ListElement {
- key: "alwaysShow"
- name: "Always show"
- }
- ListElement {
- key: "alwaysHide"
- name: "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 a72c91cf..27c4b057 100644
--- a/Modules/Settings/Bar/WidgetSettings/WorkspaceSettings.qml
+++ b/Modules/Settings/Bar/WidgetSettings/WorkspaceSettings.qml
@@ -23,21 +23,17 @@ ColumnLayout {
NComboBox {
id: labelModeCombo
- label: "Label Mode"
- model: ListModel {
- ListElement {
- key: "none"
- name: "None"
- }
- ListElement {
- key: "index"
- name: "Index"
- }
- ListElement {
- key: "name"
- name: "Name"
- }
- }
+ 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")
+ }]
currentKey: widgetData.labelMode || widgetMetadata.labelMode
onSelected: key => labelModeCombo.currentKey = key
minimumWidth: 200 * scaling
@@ -45,8 +41,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/SettingsPanel.qml b/Modules/Settings/SettingsPanel.qml
index 418f4223..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,131 +52,131 @@ 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
function updateTabsModel() {
let newTabs = [{
"id": SettingsPanel.Tab.General,
- "label": "General",
+ "label": "settings.general.title",
"icon": "settings-general",
"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
}]
@@ -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
@@ -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/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 f9cc598c..64919045 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
@@ -65,8 +65,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) {
@@ -82,8 +82,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 {
@@ -103,8 +103,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)
}
@@ -117,8 +117,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
@@ -152,8 +152,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")
}
// -------------------------------
@@ -168,8 +168,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 {
@@ -198,8 +198,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 {
@@ -227,15 +227,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
@@ -254,9 +254,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
@@ -335,90 +335,58 @@ 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"
- model: ListModel {
- ListElement {
- key: "none"
- name: "None"
- }
- ListElement {
- key: "linear"
- name: "Linear"
- }
- ListElement {
- key: "mirrored"
- name: "Mirrored"
- }
- ListElement {
- key: "wave"
- name: "Wave"
- }
- }
+ 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")
+ }]
currentKey: Settings.data.audio.visualizerType
onSelected: key => Settings.data.audio.visualizerType = key
}
NComboBox {
- label: "Frame rate"
- description: "Higher rates are smoother but use more resources."
- 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"
- }
- }
+ 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")
+ }]
currentKey: Settings.data.audio.cavaFrameRate
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 2049959c..88715105 100644
--- a/Modules/Settings/Tabs/BarTab.qml
+++ b/Modules/Settings/Tabs/BarTab.qml
@@ -41,54 +41,45 @@ ColumnLayout {
}
NHeader {
- label: "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."
- model: ListModel {
- ListElement {
- key: "top"
- name: "Top"
- }
- ListElement {
- key: "bottom"
- name: "Bottom"
- }
- ListElement {
- key: "left"
- name: "Left"
- }
- ListElement {
- key: "right"
- name: "Right"
- }
- }
+ label: I18n.tr("settings.bar.appearance.position.label")
+ description: I18n.tr("settings.bar.appearance.position.description")
+ 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
}
NComboBox {
Layout.fillWidth: true
- label: "Bar density"
- description: "Adjust the bar's padding for a compact or spacious look."
- model: ListModel {
- ListElement {
- key: "compact"
- name: "Compact"
- }
- ListElement {
- key: "default"
- name: "Default"
- }
- ListElement {
- key: "comfortable"
- name: "Comfortable"
- }
- }
+ label: I18n.tr("settings.bar.appearance.density.label")
+ description: I18n.tr("settings.bar.appearance.density.description")
+ 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
}
@@ -98,8 +89,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 +106,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 +127,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 +139,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 +159,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 +189,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 +259,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 {
@@ -277,7 +268,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/ColorSchemeTab.qml b/Modules/Settings/Tabs/ColorSchemeTab.qml
index 09a30bb8..713c7037 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"))
}
}
@@ -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) {
@@ -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) {
@@ -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,23 @@ 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"
+ 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
@@ -344,7 +351,9 @@ ColumnLayout {
NCheckbox {
label: "GTK 3"
- description: "Write ~/.config/gtk-3.0/gtk.css"
+ 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
@@ -355,7 +364,9 @@ ColumnLayout {
NCheckbox {
label: "Qt6ct"
- description: "Write ~/.config/qt6ct/colors/noctalia.conf"
+ 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
@@ -366,7 +377,9 @@ ColumnLayout {
NCheckbox {
label: "Qt5ct"
- description: "Write ~/.config/qt5ct/colors/noctalia.conf"
+ 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
@@ -379,13 +392,15 @@ 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"
+ 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", {"app": "kitty"})
checked: Settings.data.matugen.kitty
enabled: ProgramCheckerService.kittyAvailable
opacity: ProgramCheckerService.kittyAvailable ? 1.0 : 0.6
@@ -400,7 +415,9 @@ ColumnLayout {
NCheckbox {
label: "Ghostty"
- description: ProgramCheckerService.ghosttyAvailable ? "Write ~/.config/ghostty/themes/noctalia and reload" : "Requires ghostty terminal to be installed"
+ 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", {"app": "ghostty"})
checked: Settings.data.matugen.ghostty
enabled: ProgramCheckerService.ghosttyAvailable
opacity: ProgramCheckerService.ghosttyAvailable ? 1.0 : 0.6
@@ -415,7 +432,9 @@ ColumnLayout {
NCheckbox {
label: "Foot"
- description: ProgramCheckerService.footAvailable ? "Write ~/.config/foot/themes/noctalia and reload" : "Requires foot terminal to be installed"
+ 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", {"app": "foot"})
checked: Settings.data.matugen.foot
enabled: ProgramCheckerService.footAvailable
opacity: ProgramCheckerService.footAvailable ? 1.0 : 0.6
@@ -432,13 +451,15 @@ 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"
+ 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", {"app": "fuzzel"})
checked: Settings.data.matugen.fuzzel
enabled: ProgramCheckerService.fuzzelAvailable
opacity: ProgramCheckerService.fuzzelAvailable ? 1.0 : 0.6
@@ -453,7 +474,9 @@ ColumnLayout {
NCheckbox {
label: "Vesktop"
- description: ProgramCheckerService.vesktopAvailable ? "Write ~/.config/vesktop/themes/noctalia.theme.css" : "Requires vesktop Discord client to be installed"
+ 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", {"app": "vesktop"})
checked: Settings.data.matugen.vesktop
enabled: ProgramCheckerService.vesktopAvailable
opacity: ProgramCheckerService.vesktopAvailable ? 1.0 : 0.6
@@ -467,8 +490,10 @@ ColumnLayout {
}
NCheckbox {
- label: "Pywalfox (Firefox)"
- description: ProgramCheckerService.pywalfoxAvailable ? "Write ~/.cache/wal/colors.json and run pywalfox update" : "Requires pywalfox package to be installed"
+ 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", {"app": "pywalfox"})
checked: Settings.data.matugen.pywalfox
enabled: ProgramCheckerService.pywalfoxAvailable
opacity: ProgramCheckerService.pywalfoxAvailable ? 1.0 : 0.6
@@ -485,13 +510,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..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"))
}
}
@@ -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 {
@@ -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
@@ -103,7 +107,7 @@ ColumnLayout {
Layout.fillWidth: true
NText {
- text: "Scale"
+ text: I18n.tr("settings.display.monitors.scale")
Layout.preferredWidth: 80 * scaling
}
@@ -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
}
@@ -126,7 +132,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 +152,7 @@ ColumnLayout {
spacing: Style.marginL * scaling
NText {
- text: "Brightness"
+ text: I18n.tr("settings.display.monitors.brightness")
Layout.preferredWidth: 80 * scaling
}
@@ -180,24 +186,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 +193,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 +217,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) {
@@ -246,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"))
}
}
}
@@ -257,8 +245,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 +257,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 +279,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 +302,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 +317,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 +326,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 +334,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 +344,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 +352,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 +361,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..c3b1d559 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 {
@@ -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/GeneralTab.qml b/Modules/Settings/Tabs/GeneralTab.qml
index 0e0d8932..edd0fc67 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,10 +31,12 @@ 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"
+ placeholderText: I18n.tr("placeholders.profile-picture-path")
buttonIcon: "photo"
buttonTooltip: "Browse for avatar image"
onInputEditingFinished: Settings.data.general.avatarImage = text
@@ -47,7 +49,7 @@ ColumnLayout {
NFilePicker {
id: filePicker
pickerType: "file"
- title: "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]
@@ -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 {
@@ -102,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 {
@@ -130,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
}
@@ -153,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 {
@@ -180,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
@@ -190,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) {
@@ -204,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) {
@@ -218,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..1a77f880 100644
--- a/Modules/Settings/Tabs/LauncherTab.qml
+++ b/Modules/Settings/Tabs/LauncherTab.qml
@@ -10,45 +10,37 @@ 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 {
- 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
@@ -60,14 +52,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 +79,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..eafa3902 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()
@@ -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
@@ -64,13 +67,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 +85,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 4f017951..1399067c 100644
--- a/Modules/Settings/Tabs/NotificationsTab.qml
+++ b/Modules/Settings/Tabs/NotificationsTab.qml
@@ -28,63 +28,56 @@ 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."
- checked: Settings.data.notifications.enableOSD
- onToggled: checked => Settings.data.notifications.enableOSD = checked
- }
-
NComboBox {
- label: "Location"
- description: "Where notifications appear on screen."
- 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"
- }
- }
+ label: I18n.tr("settings.notifications.settings.location.label")
+ description: I18n.tr("settings.notifications.settings.location.description")
+ 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
}
NToggle {
- label: "Always on top"
- description: "Display notifications above fullscreen windows and other layers."
+ label: I18n.tr("settings.notifications.settings.always-on-top.label")
+ description: I18n.tr("settings.notifications.settings.always-on-top.description")
checked: Settings.data.notifications.alwaysOnTop
onToggled: checked => Settings.data.notifications.alwaysOnTop = checked
}
+
+ NToggle {
+ 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
+ }
}
NDivider {
@@ -93,20 +86,20 @@ ColumnLayout {
Layout.bottomMargin: Style.marginXL * scaling
}
- // Notification Duration Settings
+ // Duration
ColumnLayout {
spacing: Style.marginL * scaling
Layout.fillWidth: true
NHeader {
- label: "Notification duration"
- description: "Configure how long notifications stay visible based on their urgency level."
+ label: I18n.tr("settings.notifications.duration.section.label")
+ description: I18n.tr("settings.notifications.duration.section.description")
}
// Respect Expire Timeout (eg. --expire-time flag in notify-send)
NToggle {
- label: "Respect expire timeout"
- description: "Use the expire timeout set in the notification."
+ label: I18n.tr("settings.notifications.duration.respect-expire.label")
+ description: I18n.tr("settings.notifications.duration.respect-expire.description")
checked: Settings.data.notifications.respectExpireTimeout
onToggled: checked => Settings.data.notifications.respectExpireTimeout = checked
}
@@ -117,8 +110,8 @@ ColumnLayout {
Layout.fillWidth: true
NLabel {
- label: "Low urgency"
- description: "How long low priority notifications stay visible."
+ label: I18n.tr("settings.notifications.duration.low-urgency.label")
+ description: I18n.tr("settings.notifications.duration.low-urgency.description")
}
NValueSlider {
@@ -138,8 +131,8 @@ ColumnLayout {
Layout.fillWidth: true
NLabel {
- label: "Normal urgency"
- description: "How long normal priority notifications stay visible."
+ label: I18n.tr("settings.notifications.duration.normal-urgency.label")
+ description: I18n.tr("settings.notifications.duration.normal-urgency.description")
}
NValueSlider {
@@ -159,8 +152,8 @@ ColumnLayout {
Layout.fillWidth: true
NLabel {
- label: "Critical urgency"
- description: "How long critical priority notifications stay visible."
+ label: I18n.tr("settings.notifications.duration.critical-urgency.label")
+ description: I18n.tr("settings.notifications.duration.critical-urgency.description")
}
NValueSlider {
@@ -173,22 +166,17 @@ 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
+ NDivider {
+ Layout.fillWidth: true
+ Layout.topMargin: Style.marginXL * scaling
+ Layout.bottomMargin: Style.marginXL * scaling
+ }
+ // Monitor Configuration
NHeader {
- label: "Monitors display"
- description: "Show notification on specific monitors. Defaults to all if none are chosen."
+ label: I18n.tr("settings.notifications.monitors.section.label")
+ description: I18n.tr("settings.notifications.monitors.section.description")
}
Repeater {
@@ -196,7 +184,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 f05e8dc7..8c129117 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,206 +53,157 @@ 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."
- model: ListModel {
- ListElement {
- key: "portal"
- name: "Portal"
- }
- ListElement {
- key: "screen"
- name: "Screen"
- }
- }
+ 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")
+ }]
currentKey: Settings.data.screenRecorder.videoSource
onSelected: key => Settings.data.screenRecorder.videoSource = key
}
// Frame Rate
NComboBox {
- label: "Frame rate"
- description: "Target frame rate for screen recordings."
- 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"
- }
- }
+ label: I18n.tr("settings.screen-recorder.video.frame-rate.label")
+ description: I18n.tr("settings.screen-recorder.video.frame-rate.description")
+ 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
}
// Video Quality
NComboBox {
- label: "Video quality"
- description: "Higher quality results in larger file sizes."
- model: ListModel {
- ListElement {
- key: "medium"
- name: "Medium"
- }
- ListElement {
- key: "high"
- name: "High"
- }
- ListElement {
- key: "very_high"
- name: "Very high"
- }
- ListElement {
- key: "ultra"
- name: "Ultra"
- }
- }
+ label: I18n.tr("settings.screen-recorder.video.video-quality.label")
+ description: I18n.tr("settings.screen-recorder.video.video-quality.description")
+ 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
}
// Video Codec
NComboBox {
- label: "Video codec"
- description: "h264 is the most common codec."
- 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"
- }
- }
+ label: I18n.tr("settings.screen-recorder.video.video-codec.label")
+ description: I18n.tr("settings.screen-recorder.video.video-codec.description")
+ model: [{
+ "key": "h264",
+ "name": "H264"
+ }, {
+ "key": "hevc",
+ "name": "HEVC"
+ }, {
+ "key": "av1",
+ "name": "AV1"
+ }, {
+ "key": "vp8",
+ "name": "VP8"
+ }, {
+ "key": "vp9",
+ "name": "VP9"
+ }]
currentKey: Settings.data.screenRecorder.videoCodec
onSelected: key => Settings.data.screenRecorder.videoCodec = key
}
// Color Range
NComboBox {
- label: "Color range"
- description: "Limited is recommended for better compatibility."
- model: ListModel {
- ListElement {
- key: "limited"
- name: "Limited"
- }
- ListElement {
- key: "full"
- name: "Full"
- }
- }
+ label: I18n.tr("settings.screen-recorder.video.color-range.label")
+ description: I18n.tr("settings.screen-recorder.video.color-range.description")
+ 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
}
}
- NDivider {
- Layout.fillWidth: true
- Layout.topMargin: Style.marginL * 2 * scaling
- Layout.bottomMargin: Style.marginL * scaling
- }
-
- // Audio Settings
- ColumnLayout {
- spacing: Style.marginL * scaling
- Layout.fillWidth: true
-
- NHeader {
- label: "Audio settings"
- }
-
- // Audio Source
- NComboBox {
- label: "Audio source"
- description: "Audio source to capture during recording."
- model: ListModel {
- ListElement {
- key: "default_output"
- name: "System output"
- }
- ListElement {
- key: "default_input"
- name: "Microphone input"
- }
- ListElement {
- key: "both"
- name: "System output + microphone input"
- }
- }
- currentKey: Settings.data.screenRecorder.audioSource
- onSelected: key => Settings.data.screenRecorder.audioSource = key
- }
-
- // Audio Codec
- NComboBox {
- label: "Audio codec"
- description: "Opus is recommended for best performance and smallest audio size."
- model: ListModel {
- ListElement {
- key: "opus"
- name: "Opus"
- }
- ListElement {
- key: "aac"
- name: "AAC"
- }
- }
- currentKey: Settings.data.screenRecorder.audioCodec
- onSelected: key => Settings.data.screenRecorder.audioCodec = key
- }
- }
-
NDivider {
Layout.fillWidth: true
Layout.topMargin: Style.marginXL * scaling
Layout.bottomMargin: Style.marginXL * scaling
}
+ // Audio Settings
+ ColumnLayout {
+ spacing: Style.marginL * scaling
+ Layout.fillWidth: true
+
+ NHeader {
+ label: I18n.tr("settings.screen-recorder.audio.section.label")
+ description: I18n.tr("settings.screen-recorder.audio.section.description")
+ }
+
+ // Audio Source
+ NComboBox {
+ label: I18n.tr("settings.screen-recorder.audio.audio-source.label")
+ description: I18n.tr("settings.screen-recorder.audio.audio-source.description")
+ 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
+ }
+
+ // Audio Codec
+ NComboBox {
+ label: I18n.tr("settings.screen-recorder.audio.audio-codec.label")
+ description: I18n.tr("settings.screen-recorder.audio.audio-codec.description")
+ 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
+ }
+ }
+
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])
}
}
diff --git a/Modules/Wallpaper/WallpaperPanel.qml b/Modules/Wallpaper/WallpaperPanel.qml
index 7c0bad58..6266aa2b 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
@@ -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()
}
@@ -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
@@ -183,7 +183,7 @@ NPanel {
NTextInput {
id: searchInput
- placeholderText: "Type to filter wallpapers..."
+ placeholderText: I18n.tr("placeholders.search-wallpapers")
Layout.fillWidth: true
onTextChanged: {
@@ -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 b1260131..f600f9d9 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/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/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 3f5e3c4c..9a2504a6 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
@@ -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/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/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 ddcfd609..1624ca50 100644
--- a/Services/NotificationService.qml
+++ b/Services/NotificationService.qml
@@ -399,7 +399,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/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/NComboBox.qml b/Widgets/NComboBox.qml
index 635876a0..6035b620 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: {
+ 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
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/NFilePicker.qml b/Widgets/NFilePicker.qml
index f5fb2336..54072943 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 {
@@ -14,9 +15,9 @@ 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 acceptLabel: "Select"
- property string rejectLabel: "Cancel"
+ 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")
// State properties
property bool isOpen: false
diff --git a/Widgets/NIconPicker.qml b/Widgets/NIconPicker.qml
index c0ffaa49..86ea50a4 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,8 +85,8 @@ Popup {
NTextInput {
id: searchInput
Layout.fillWidth: true
- label: "Search"
- placeholderText: "e.g., noctalia, niri, battery, cloud"
+ label: I18n.tr("widgets.icon-picker.search.label")
+ placeholderText: I18n.tr("placeholders.search-icons")
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/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
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
}
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