i18n: even more things appeared

This commit is contained in:
Ly-sec
2025-09-24 15:31:11 +02:00
parent 24cb5823ee
commit 5de4330199
25 changed files with 402 additions and 298 deletions

View File

@@ -1064,6 +1064,9 @@
}
},
"session-menu": {
"title": "Sitzungsmenü",
"click-again": "Erneut klicken für sofortige Ausführung",
"action-in-seconds": "{action} in {seconds} Sekunden...",
"lock": "Sperren",
"suspend": "Ruhezustand",
"reboot": "Neu starten",
@@ -1111,5 +1114,69 @@
"shut-down": "Herunterfahren",
"restart": "Neu starten",
"suspend": "Ruhezustand"
},
"toast": {
"night-light": {
"enabled": "Aktiviert",
"disabled": "Deaktiviert",
"not-installed": "wlsunset nicht installiert",
"forced": "Aktivierung erzwungen",
"normal": "Normaler Modus"
},
"keep-awake": {
"enabled": "Aktiviert",
"disabled": "Deaktiviert"
},
"matugen": {
"enabled": "Aktiviert",
"disabled": "Deaktiviert",
"not-installed": "Nicht installiert"
},
"recording": {
"stopping": "Aufnahme wird gestoppt…",
"started": "Aufnahme gestartet",
"saved": "Aufnahme gespeichert",
"failed-start": "Aufnahme konnte nicht gestartet werden",
"failed-gpu": "gpu-screen-recorder unerwartet beendet.",
"failed-general": "Der Rekorder wurde mit einem Fehler beendet.",
"no-portals": "Desktop-Portale laufen nicht",
"no-portals-desc": "Starten Sie xdg-desktop-portal und ein Compositor-Portal (wlr/hyprland/gnome/kde)."
},
"clipboard": {
"unavailable": "Zwischenablage-Verlauf nicht verfügbar",
"unavailable-desc": "Die 'cliphist' Anwendung ist nicht installiert. Bitte installieren Sie sie, um Zwischenablage-Verlauf-Features zu nutzen."
},
"ipc": {
"powerpanel-deprecated": "PowerPanel wurde in SessionMenu umbenannt, dieser IPC-Aufruf wird bald veraltet sein. Bitte verwenden Sie stattdessen \"ipc call sessionMenu toggle\".",
"sidepanel-deprecated": "SidePanel wurde in ControlCenter umbenannt, dieser IPC-Aufruf wird bald veraltet sein. Bitte verwenden Sie stattdessen \"ipc call controlCenter toggle\"."
},
"wifi": {
"enabled": "Aktiviert",
"disabled": "Deaktiviert",
"connected": "Verbunden mit '{ssid}'",
"disconnected": "Getrennt von '{ssid}'"
},
"bluetooth": {
"enabled": "Aktiviert",
"disabled": "Deaktiviert"
},
"do-not-disturb": {
"enabled": "'Nicht stören' aktiviert",
"disabled": "'Nicht stören' deaktiviert",
"enabled-desc": "Sie finden diese Benachrichtigungen in Ihrem Verlauf.",
"disabled-desc": "Alle Benachrichtigungen werden angezeigt."
},
"power-profile": {
"changed": "Energieprofil geändert",
"profile-name": "\"{profile}\""
},
"audio": {
"muted": "Stummgeschaltet",
"unmuted": "Lautgeschaltet"
},
"battery": {
"low": "Niedriger Batteriestand",
"low-desc": "Batterie ist bei {percent}%. Bitte schließen Sie das Ladegerät an."
}
}
}

View File

@@ -663,6 +663,10 @@
"tooltip": {
"placeholder": "Placeholder"
},
"file-picker": {
"select-folder": "Select Folder",
"select-file": "Select File"
},
"datetime-tokens": {
"common": {
"12hour-time-minutes": "12-hour time with minutes",
@@ -886,7 +890,25 @@
"description": "Apply selected wallpaper to all monitors at once."
},
"search": "Search:"
}
},
"transitions": {
"none": "None",
"random": "Random",
"fade": "Fade",
"disc": "Disc",
"stripes": "Stripes",
"wipe": "Wipe"
},
"fill-modes": {
"center": "Center",
"crop": "Crop (Fill)",
"fit": "Fit (Contain)",
"stretch": "Stretch"
},
"no-match": "No match found.",
"no-wallpaper": "No wallpaper found.",
"try-different-search": "Try a different search query.",
"configure-directory": "Configure your wallpaper directory with images."
},
"bluetooth": {
"panel": {
@@ -1004,6 +1026,30 @@
"test": "Test"
},
"options": {
"bar": {
"position": {
"top": "Top",
"bottom": "Bottom",
"left": "Left",
"right": "Right"
},
"density": {
"compact": "Compact",
"default": "Default",
"comfortable": "Comfortable"
}
},
"launcher": {
"position": {
"center": "Center (default)",
"top_left": "Top left",
"top_right": "Top right",
"bottom_left": "Bottom left",
"bottom_right": "Bottom right",
"bottom_center": "Bottom center",
"top_center": "Top center"
}
},
"display-mode": {
"on-hover": "On hover",
"always-show": "Always show",
@@ -1064,6 +1110,11 @@
}
},
"session-menu": {
"title": "Session Menu",
"click-again": "Click again to execute immediately",
"action-in-seconds": "{action} in {seconds} seconds...",
"lock-subtitle": "Lock your session",
"end-subtitle": "End your session",
"lock": "Lock",
"suspend": "Suspend",
"reboot": "Reboot",
@@ -1111,5 +1162,98 @@
"shut-down": "Shut down",
"restart": "Restart",
"suspend": "Suspend"
},
"toast": {
"night-light": {
"enabled": "Enabled",
"disabled": "Disabled",
"not-installed": "wlsunset not installed",
"forced": "Forced activation",
"normal": "Normal mode"
},
"keep-awake": {
"enabled": "Enabled",
"disabled": "Disabled"
},
"matugen": {
"enabled": "Enabled",
"disabled": "Disabled",
"not-installed": "Not installed"
},
"recording": {
"stopping": "Stopping recording…",
"started": "Recording started",
"saved": "Recording saved",
"failed-start": "Failed to start recording",
"failed-gpu": "gpu-screen-recorder exited unexpectedly.",
"failed-general": "The recorder exited with an error.",
"no-portals": "Desktop portals not running",
"no-portals-desc": "Start xdg-desktop-portal and a compositor portal (wlr/hyprland/gnome/kde)."
},
"clipboard": {
"unavailable": "Clipboard history unavailable",
"unavailable-desc": "The 'cliphist' application is not installed. Please install it to use clipboard history features."
},
"ipc": {
"powerpanel-deprecated": "PowerPanel has been renamed to SessionMenu, this IPC call will be deprecated soon. Please use \"ipc call sessionMenu toggle\" instead.",
"sidepanel-deprecated": "SidePanel has been renamed to ControlCenter, this IPC call will be deprecated soon. Please use \"ipc call controlCenter toggle\" instead."
},
"wifi": {
"enabled": "Enabled",
"disabled": "Disabled",
"connected": "Connected to '{ssid}'",
"disconnected": "Disconnected from '{ssid}'"
},
"bluetooth": {
"enabled": "Enabled",
"disabled": "Disabled"
},
"do-not-disturb": {
"enabled": "'Do not disturb' enabled",
"disabled": "'Do not disturb' disabled",
"enabled-desc": "You'll find these notifications in your history.",
"disabled-desc": "Showing all notifications."
},
"power-profile": {
"changed": "Power profile changed",
"profile-name": "\"{profile}\""
},
"audio": {
"muted": "Muted",
"unmuted": "Unmuted"
},
"battery": {
"low": "Low Battery",
"low-desc": "Battery is at {percent}%. Please connect the charger."
}
},
"weather": {
"clear-sky": "Clear sky",
"mainly-clear": "Mainly clear",
"partly-cloudy": "Partly cloudy",
"overcast": "Overcast",
"fog": "Fog",
"drizzle": "Drizzle",
"snow": "Snow",
"rain-showers": "Rain showers",
"thunderstorm": "Thunderstorm",
"unknown": "Unknown"
},
"authentication": {
"failed": "Authentication failed",
"error": "Authentication error"
},
"general": {
"no-results": "No results",
"no-summary": "No summary",
"unknown": "Unknown"
},
"battery": {
"no-battery-detected": "No battery detected.",
"charging-rate": "Charging rate: {rate} W.",
"discharging-rate": "Discharging rate: {rate} W.",
"charging": "Charging.",
"discharging": "Discharging."
}
}

View File

@@ -1,65 +0,0 @@
#!/bin/bash
# Comprehensive i18n checker for Noctalia Shell
# Finds hardcoded strings that should be internationalized
check_file() {
local file="$1"
# Check for hardcoded strings in common properties
# Includes: label, text, title, description, tooltip, tooltipText, placeholder, placeholderText
local property_issues=$(grep -n -E '(label|text|title|description|tooltip|tooltipText|placeholder|placeholderText):\s*"[^"]{3,}"' "$file" | grep -v 'I18n.tr')
# Check for hardcoded strings in dialog titles and button texts
local dialog_issues=$(grep -n -E '(dialog\.|Dialog\.|title:|buttonText:)\s*"[^"]{3,}"' "$file" | grep -v 'I18n.tr')
# Check for hardcoded strings in model name properties (for combo boxes)
local model_issues=$(grep -n -E 'name:\s*"[^"]{3,}"' "$file" | grep -v 'I18n.tr')
# Check for hardcoded strings in common UI text patterns
local ui_issues=$(grep -n -E '"[^"]*\b(click|open|close|enable|disable|show|hide|settings|cancel|apply|ok|save|load|start|stop|play|pause|next|previous|volume|brightness|wifi|bluetooth|notification|wallpaper|profile|power|session|menu|panel|dialog|button|toggle|slider|checkbox|radio|combo|input|search|filter|sort|refresh|update|delete|remove|add|create|edit|modify|copy|paste|cut|undo|redo|help|about|info|warning|error|success|failed|loading|connecting|connected|disconnected|scanning|pairing|recording|playing|paused|stopped|muted|unmuted|enabled|disabled|on|off|yes|no|true|false)\b[^"]*"' "$file" | grep -v 'I18n.tr' | grep -v '//' | grep -v '/*')
# Combine all issues
local all_issues="$property_issues"
if [[ -n "$dialog_issues" ]]; then
all_issues="$all_issues"$'\n'"$dialog_issues"
fi
if [[ -n "$model_issues" ]]; then
all_issues="$all_issues"$'\n'"$model_issues"
fi
if [[ -n "$ui_issues" ]]; then
all_issues="$all_issues"$'\n'"$ui_issues"
fi
# Remove empty lines and duplicates
all_issues=$(echo "$all_issues" | grep -v '^$' | sort -u)
if [[ -n "$all_issues" ]]; then
echo "$file"
echo "$all_issues" | while IFS= read -r line; do
echo " $line"
done
echo
fi
}
echo "Comprehensive i18n Checker"
echo "========================="
echo "Scanning QML files for hardcoded strings..."
echo
found_issues=false
while IFS= read -r -d '' file; do
if check_file "$file" | grep -q .; then
check_file "$file"
found_issues=true
fi
done < <(find . -name "*.qml" -not -path "./Assets/*" -print0)
if [[ "$found_issues" == false ]]; then
echo "No hardcoded strings found! All strings appear to be internationalized."
else
echo "Note: Review each match manually - some may be false positives"
echo "(property names, IDs, technical values, comments shouldn't be translated)"
fi

View File

@@ -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

View File

@@ -293,7 +293,7 @@ Variants {
}
NText {
text: model.summary || "No summary"
text: model.summary || I18n.tr("general.no-summary")
font.pointSize: Style.fontSizeL * scaling
font.weight: Style.fontWeightMedium
color: Color.mOnSurface

View File

@@ -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

View File

@@ -31,7 +31,7 @@ NPanel {
"action": "lock",
"icon": "lock",
"title": I18n.tr("session-menu.lock"),
"subtitle": "Lock your session"
"subtitle": I18n.tr("session-menu.lock-subtitle")
}, {
"action": "suspend",
"icon": "suspend",
@@ -46,7 +46,7 @@ NPanel {
"action": "logout",
"icon": "logout",
"title": I18n.tr("session-menu.logout"),
"subtitle": "End your session"
"subtitle": I18n.tr("session-menu.end-subtitle")
}, {
"action": "shutdown",
"icon": "shutdown",
@@ -263,7 +263,10 @@ NPanel {
Layout.preferredHeight: Style.baseWidgetSize * 0.8 * scaling
NText {
text: timerActive ? `${pendingAction.charAt(0).toUpperCase() + pendingAction.slice(1)} in ${Math.ceil(timeRemaining / 1000)} seconds...` : "Session Menu"
text: timerActive ? I18n.tr("session-menu.action-in-seconds", {
"action": pendingAction.charAt(0).toUpperCase() + pendingAction.slice(1),
"seconds": Math.ceil(timeRemaining / 1000)
}) : I18n.tr("session-menu.title")
font.weight: Style.fontWeightBold
font.pointSize: Style.fontSizeL * scaling
color: timerActive ? Color.mPrimary : Color.mOnSurface
@@ -419,7 +422,7 @@ NPanel {
NText {
text: {
if (buttonRoot.pending) {
return "Click again to execute immediately"
return I18n.tr("session-menu.click-again")
}
return buttonRoot.subtitle
}

View File

@@ -49,24 +49,19 @@ ColumnLayout {
Layout.fillWidth: true
label: I18n.tr("settings.bar.appearance.position.label")
description: I18n.tr("settings.bar.appearance.position.description")
model: ListModel {
ListElement {
key: "top"
name: "Top"
}
ListElement {
key: "bottom"
name: "Bottom"
}
ListElement {
key: "left"
name: "Left"
}
ListElement {
key: "right"
name: "Right"
}
}
model: [{
"key": "top",
"name": I18n.tr("options.bar.position.top")
}, {
"key": "bottom",
"name": I18n.tr("options.bar.position.bottom")
}, {
"key": "left",
"name": I18n.tr("options.bar.position.left")
}, {
"key": "right",
"name": I18n.tr("options.bar.position.right")
}]
currentKey: Settings.data.bar.position
onSelected: key => Settings.data.bar.position = key
}
@@ -75,20 +70,16 @@ ColumnLayout {
Layout.fillWidth: true
label: I18n.tr("settings.bar.appearance.density.label")
description: I18n.tr("settings.bar.appearance.density.description")
model: ListModel {
ListElement {
key: "compact"
name: "Compact"
}
ListElement {
key: "default"
name: "Default"
}
ListElement {
key: "comfortable"
name: "Comfortable"
}
}
model: [{
"key": "compact",
"name": I18n.tr("options.bar.density.compact")
}, {
"key": "default",
"name": I18n.tr("options.bar.density.default")
}, {
"key": "comfortable",
"name": I18n.tr("options.bar.density.comfortable")
}]
currentKey: Settings.data.bar.density
onSelected: key => Settings.data.bar.density = key
}

View File

@@ -65,10 +65,10 @@ ColumnLayout {
// Matugen exists, enable it
Settings.data.colorSchemes.useWallpaperColors = true
MatugenService.generateFromWallpaper()
ToastService.showNotice("Matugen", "Enabled")
ToastService.showNotice(I18n.tr("settings.color-scheme.color-source.enable-matugen.label"), I18n.tr("toast.matugen.enabled"))
} else {
// Matugen not found
ToastService.showWarning("Matugen", "Not installed")
ToastService.showWarning(I18n.tr("settings.color-scheme.color-source.enable-matugen.label"), I18n.tr("toast.matugen.not-installed"))
}
}
@@ -130,7 +130,7 @@ ColumnLayout {
matugenCheck.running = true
} else {
Settings.data.colorSchemes.useWallpaperColors = false
ToastService.showNotice("Matugen", "Disabled")
ToastService.showNotice(I18n.tr("settings.color-scheme.color-source.enable-matugen.label"), I18n.tr("toast.matugen.disabled"))
if (Settings.data.colorSchemes.predefinedScheme) {

View File

@@ -38,10 +38,10 @@ ColumnLayout {
if (exitCode === 0) {
Settings.data.nightLight.enabled = true
NightLightService.apply()
ToastService.showNotice("Night light", "Enabled")
ToastService.showNotice(I18n.tr("settings.display.night-light.section.label"), I18n.tr("toast.night-light.enabled"))
} else {
Settings.data.nightLight.enabled = false
ToastService.showWarning("Night light", "wlsunset not installed")
ToastService.showWarning(I18n.tr("settings.display.night-light.section.label"), I18n.tr("toast.night-light.not-installed"))
}
}
@@ -234,7 +234,7 @@ ColumnLayout {
Settings.data.nightLight.enabled = false
Settings.data.nightLight.forced = false
NightLightService.apply()
ToastService.showNotice("Night light", "Disabled")
ToastService.showNotice(I18n.tr("settings.display.night-light.section.label"), I18n.tr("toast.night-light.disabled"))
}
}
}

View File

@@ -19,36 +19,28 @@ ColumnLayout {
label: I18n.tr("settings.launcher.settings.position.label")
description: I18n.tr("settings.launcher.settings.position.description")
Layout.fillWidth: true
model: ListModel {
ListElement {
key: "center"
name: "Center (default)"
}
ListElement {
key: "top_left"
name: "Top left"
}
ListElement {
key: "top_right"
name: "Top right"
}
ListElement {
key: "bottom_left"
name: "Bottom left"
}
ListElement {
key: "bottom_right"
name: "Bottom right"
}
ListElement {
key: "bottom_center"
name: "Bottom center"
}
ListElement {
key: "top_center"
name: "Top center"
}
}
model: [{
"key": "center",
"name": I18n.tr("options.launcher.position.center")
}, {
"key": "top_left",
"name": I18n.tr("options.launcher.position.top_left")
}, {
"key": "top_right",
"name": I18n.tr("options.launcher.position.top_right")
}, {
"key": "bottom_left",
"name": I18n.tr("options.launcher.position.bottom_left")
}, {
"key": "bottom_right",
"name": I18n.tr("options.launcher.position.bottom_right")
}, {
"key": "bottom_center",
"name": I18n.tr("options.launcher.position.bottom_center")
}, {
"key": "top_center",
"name": I18n.tr("options.launcher.position.top_center")
}]
currentKey: Settings.data.appLauncher.position
onSelected: function (key) {
Settings.data.appLauncher.position = key

View File

@@ -49,32 +49,25 @@ ColumnLayout {
NComboBox {
label: I18n.tr("settings.notifications.settings.location.label")
description: I18n.tr("settings.notifications.settings.location.description")
model: ListModel {
ListElement {
key: "top"
name: "Top"
}
ListElement {
key: "top_left"
name: "Top left"
}
ListElement {
key: "top_right"
name: "Top right"
}
ListElement {
key: "bottom"
name: "Bottom"
}
ListElement {
key: "bottom_left"
name: "Bottom left"
}
ListElement {
key: "bottom_right"
name: "Bottom right"
}
}
model: [{
"key": "top",
"name": I18n.tr("options.launcher.position.top_center")
}, {
"key": "top_left",
"name": I18n.tr("options.launcher.position.top_left")
}, {
"key": "top_right",
"name": I18n.tr("options.launcher.position.top_right")
}, {
"key": "bottom",
"name": I18n.tr("options.launcher.position.bottom_center")
}, {
"key": "bottom_left",
"name": I18n.tr("options.launcher.position.bottom_left")
}, {
"key": "bottom_right",
"name": I18n.tr("options.launcher.position.bottom_right")
}]
currentKey: Settings.data.notifications.location || "top_right"
onSelected: key => Settings.data.notifications.location = key
}

View File

@@ -76,36 +76,28 @@ ColumnLayout {
NComboBox {
label: I18n.tr("settings.screen-recorder.video.frame-rate.label")
description: I18n.tr("settings.screen-recorder.video.frame-rate.description")
model: ListModel {
ListElement {
key: "30"
name: "30 FPS"
}
ListElement {
key: "60"
name: "60 FPS"
}
ListElement {
key: "100"
name: "100 FPS"
}
ListElement {
key: "120"
name: "120 FPS"
}
ListElement {
key: "144"
name: "144 FPS"
}
ListElement {
key: "165"
name: "165 FPS"
}
ListElement {
key: "240"
name: "240 FPS"
}
}
model: [{
"key": "30",
"name": I18n.tr("options.frame-rates.30-fps")
}, {
"key": "60",
"name": I18n.tr("options.frame-rates.60-fps")
}, {
"key": "100",
"name": I18n.tr("options.frame-rates.100-fps")
}, {
"key": "120",
"name": I18n.tr("options.frame-rates.120-fps")
}, {
"key": "144",
"name": I18n.tr("options.frame-rates.144-fps")
}, {
"key": "165",
"name": I18n.tr("options.frame-rates.165-fps")
}, {
"key": "240",
"name": I18n.tr("options.frame-rates.240-fps")
}]
currentKey: Settings.data.screenRecorder.frameRate
onSelected: key => Settings.data.screenRecorder.frameRate = key
}
@@ -114,24 +106,19 @@ ColumnLayout {
NComboBox {
label: I18n.tr("settings.screen-recorder.video.video-quality.label")
description: I18n.tr("settings.screen-recorder.video.video-quality.description")
model: ListModel {
ListElement {
key: "medium"
name: "Medium"
}
ListElement {
key: "high"
name: "High"
}
ListElement {
key: "very_high"
name: "Very high"
}
ListElement {
key: "ultra"
name: "Ultra"
}
}
model: [{
"key": "medium",
"name": I18n.tr("options.screen-recording.quality.medium")
}, {
"key": "high",
"name": I18n.tr("options.screen-recording.quality.high")
}, {
"key": "very_high",
"name": I18n.tr("options.screen-recording.quality.very-high")
}, {
"key": "ultra",
"name": I18n.tr("options.screen-recording.quality.ultra")
}]
currentKey: Settings.data.screenRecorder.quality
onSelected: key => Settings.data.screenRecorder.quality = key
}
@@ -140,28 +127,22 @@ ColumnLayout {
NComboBox {
label: I18n.tr("settings.screen-recorder.video.video-codec.label")
description: I18n.tr("settings.screen-recorder.video.video-codec.description")
model: ListModel {
ListElement {
key: "h264"
name: "H264"
}
ListElement {
key: "hevc"
name: "HEVC"
}
ListElement {
key: "av1"
name: "AV1"
}
ListElement {
key: "vp8"
name: "VP8"
}
ListElement {
key: "vp9"
name: "VP9"
}
}
model: [{
"key": "h264",
"name": I18n.tr("options.screen-recording.codecs.h264")
}, {
"key": "hevc",
"name": I18n.tr("options.screen-recording.codecs.hevc")
}, {
"key": "av1",
"name": I18n.tr("options.screen-recording.codecs.av1")
}, {
"key": "vp8",
"name": I18n.tr("options.screen-recording.codecs.vp8")
}, {
"key": "vp9",
"name": I18n.tr("options.screen-recording.codecs.vp9")
}]
currentKey: Settings.data.screenRecorder.videoCodec
onSelected: key => Settings.data.screenRecorder.videoCodec = key
}
@@ -170,16 +151,13 @@ ColumnLayout {
NComboBox {
label: I18n.tr("settings.screen-recorder.video.color-range.label")
description: I18n.tr("settings.screen-recorder.video.color-range.description")
model: ListModel {
ListElement {
key: "limited"
name: "Limited"
}
ListElement {
key: "full"
name: "Full"
}
}
model: [{
"key": "limited",
"name": I18n.tr("options.screen-recording.color-range.limited")
}, {
"key": "full",
"name": I18n.tr("options.screen-recording.color-range.full")
}]
currentKey: Settings.data.screenRecorder.colorRange
onSelected: key => Settings.data.screenRecorder.colorRange = key
}
@@ -205,20 +183,16 @@ ColumnLayout {
NComboBox {
label: I18n.tr("settings.screen-recorder.audio.audio-source.label")
description: I18n.tr("settings.screen-recorder.audio.audio-source.description")
model: ListModel {
ListElement {
key: "default_output"
name: "System output"
}
ListElement {
key: "default_input"
name: "Microphone input"
}
ListElement {
key: "both"
name: "System output + microphone input"
}
}
model: [{
"key": "default_output",
"name": I18n.tr("options.screen-recording.audio-sources.system-output")
}, {
"key": "default_input",
"name": I18n.tr("options.screen-recording.audio-sources.microphone-input")
}, {
"key": "both",
"name": I18n.tr("options.screen-recording.audio-sources.both")
}]
currentKey: Settings.data.screenRecorder.audioSource
onSelected: key => Settings.data.screenRecorder.audioSource = key
}
@@ -227,16 +201,13 @@ ColumnLayout {
NComboBox {
label: I18n.tr("settings.screen-recorder.audio.audio-codec.label")
description: I18n.tr("settings.screen-recorder.audio.audio-codec.description")
model: ListModel {
ListElement {
key: "opus"
name: "Opus"
}
ListElement {
key: "aac"
name: "AAC"
}
}
model: [{
"key": "opus",
"name": I18n.tr("options.screen-recording.audio-codecs.opus")
}, {
"key": "aac",
"name": I18n.tr("options.screen-recording.audio-codecs.aac")
}]
currentKey: Settings.data.screenRecorder.audioCodec
onSelected: key => Settings.data.screenRecorder.audioCodec = key
}

View File

@@ -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

View File

@@ -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"))
}
}

View File

@@ -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"))
}
}
}

View File

@@ -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)
}
}
}

View File

@@ -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 {

View File

@@ -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
}

View File

@@ -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)

View File

@@ -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() {

View File

@@ -386,7 +386,7 @@ Singleton {
target: Settings.data.notifications
function onDoNotDisturbChanged() {
const enabled = Settings.data.notifications.doNotDisturb
ToastService.showNotice(enabled ? "'Do not disturb' enabled" : "'Do not disturb' disabled", enabled ? "You'll find these notifications in your history." : "Showing all notifications.")
ToastService.showNotice(enabled ? I18n.tr("toast.do-not-disturb.enabled") : I18n.tr("toast.do-not-disturb.disabled"), enabled ? I18n.tr("toast.do-not-disturb.enabled-desc") : I18n.tr("toast.do-not-disturb.disabled-desc"))
}
}
}

View File

@@ -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
}))
}
}
}

View File

@@ -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)
}
}
}

View File

@@ -15,7 +15,7 @@ Item {
property bool multipleSelection: false
property string pickerType: "file" // "file" or "folder"
property var nameFilters: ["All files (*)"] // e.g., ["Image files (*.png *.jpg)", "Text files (*.txt)"]
property string title: pickerType === "folder" ? "Select Folder" : "Select File"
property string title: pickerType === "folder" ? I18n.tr("widgets.file-picker.select-folder") : I18n.tr("widgets.file-picker.select-file")
property string acceptLabel: I18n.tr("placeholders.select")
property string rejectLabel: I18n.tr("placeholders.cancel")