feat: add translation files and i18n loader

Create TOML-based localisation resources under app/lang and introduce a Translator/I18nMixin that reads them. Update config handling to recognise available languages, switch UI strings to translation lookups, and bundle language files with the package.
This commit is contained in:
lm
2025-10-17 16:43:25 +02:00
parent 76073ab0b5
commit 91fad62808
13 changed files with 442 additions and 100 deletions
+58
View File
@@ -0,0 +1,58 @@
[translations]
"app.title" = "Interactive Color Range Analyzer"
"toolbar.open_image" = "Bild laden"
"toolbar.open_folder" = "Ordner laden"
"toolbar.choose_color" = "Farbe wählen"
"toolbar.pick_from_image" = "Farbe aus Bild klicken"
"toolbar.save_overlay" = "Overlay speichern"
"toolbar.clear_excludes" = "Ausschlüsse löschen"
"toolbar.undo_exclude" = "Letzten Ausschluss entfernen"
"toolbar.reset_sliders" = "Slider zurücksetzen"
"toolbar.toggle_theme" = "Theme umschalten"
"status.no_file" = "Keine Datei geladen."
"status.defaults_restored" = "Standardwerte aktiv."
"status.loaded" = "Geladen: {name} — {dimensions}{position}"
"status.filename_label" = "{name} — {dimensions}{position}"
"status.color_selected" = "Farbe gewählt: {label} — Hue {hue:.1f}°, S {saturation:.0f}%, V {value:.0f}%"
"status.sample_colour" = "Beispielfarbe gewählt: {label} ({hex_code}) — Hue {hue:.1f}°, S {saturation:.0f}%, V {value:.0f}%"
"status.pick_mode_ready" = "Pick-Modus: Klicke links ins Bild, um Farbe zu wählen (Esc beendet)"
"status.pick_mode_ended" = "Pick-Modus beendet."
"status.pick_mode_from_image" = "Farbe vom Bild gewählt: Hue {hue:.1f}°, S {saturation:.0f}%, V {value:.0f}%"
"palette.current" = "Farbe:"
"palette.more" = "Weitere Farben:"
"palette.swatch.red" = "Rot"
"palette.swatch.orange" = "Orange"
"palette.swatch.yellow" = "Gelb"
"palette.swatch.green" = "Grün"
"palette.swatch.teal" = "Türkis"
"palette.swatch.blue" = "Blau"
"palette.swatch.violet" = "Violett"
"palette.swatch.magenta" = "Magenta"
"palette.swatch.white" = "Weiß"
"palette.swatch.grey" = "Grau"
"palette.swatch.black" = "Schwarz"
"sliders.hue_min" = "Hue Min (°)"
"sliders.hue_max" = "Hue Max (°)"
"sliders.sat_min" = "Sättigung Min (%)"
"sliders.val_min" = "Helligkeit Min (%)"
"sliders.val_max" = "Helligkeit Max (%)"
"sliders.alpha" = "Overlay Alpha"
"stats.placeholder" = "Markierungen (mit Ausschlüssen): —"
"stats.summary" = "Markierungen (mit Ausschlüssen): {with_pct:.2f}% | Markierungen (ohne Ausschlüsse): {without_pct:.2f}% | Ausgeschlossen: {excluded_pct:.2f}% der Pixel, davon {excluded_match_pct:.2f}% markiert"
"menu.copy" = "Kopieren"
"dialog.info_title" = "Info"
"dialog.error_title" = "Fehler"
"dialog.saved_title" = "Gespeichert"
"dialog.open_image_title" = "Bild wählen"
"dialog.open_folder_title" = "Ordner mit Bildern wählen"
"dialog.save_overlay_title" = "Overlay speichern als"
"dialog.choose_colour_title" = "Farbe wählen"
"dialog.images_filter" = "Bilder"
"dialog.folder_not_found" = "Der Ordner wurde nicht gefunden."
"dialog.folder_empty" = "Keine unterstützten Bilder im Ordner gefunden."
"dialog.file_missing" = "Datei nicht gefunden: {path}"
"dialog.image_open_failed" = "Bild konnte nicht geladen werden: {error}"
"dialog.load_image_first" = "Bitte zuerst ein Bild laden."
"dialog.no_image_loaded" = "Kein Bild geladen."
"dialog.no_preview_available" = "Keine Preview vorhanden."
"dialog.overlay_saved" = "Overlay gespeichert: {path}"
+58
View File
@@ -0,0 +1,58 @@
[translations]
"app.title" = "Interactive Color Range Analyzer"
"toolbar.open_image" = "Open image"
"toolbar.open_folder" = "Open folder"
"toolbar.choose_color" = "Choose colour"
"toolbar.pick_from_image" = "Pick from image"
"toolbar.save_overlay" = "Save overlay"
"toolbar.clear_excludes" = "Clear exclusions"
"toolbar.undo_exclude" = "Undo last exclusion"
"toolbar.reset_sliders" = "Reset sliders"
"toolbar.toggle_theme" = "Toggle theme"
"status.no_file" = "No file loaded."
"status.defaults_restored" = "Defaults restored."
"status.loaded" = "Loaded: {name} — {dimensions}{position}"
"status.filename_label" = "{name} — {dimensions}{position}"
"status.color_selected" = "Colour chosen: {label} — Hue {hue:.1f}°, S {saturation:.0f}%, V {value:.0f}%"
"status.sample_colour" = "Sample colour applied: {label} ({hex_code}) — Hue {hue:.1f}°, S {saturation:.0f}%, V {value:.0f}%"
"status.pick_mode_ready" = "Pick mode: Click the left image to choose a colour (Esc exits)"
"status.pick_mode_ended" = "Pick mode ended."
"status.pick_mode_from_image" = "Colour picked from image: Hue {hue:.1f}°, S {saturation:.0f}%, V {value:.0f}%"
"palette.current" = "Colour:"
"palette.more" = "More colours:"
"palette.swatch.red" = "Red"
"palette.swatch.orange" = "Orange"
"palette.swatch.yellow" = "Yellow"
"palette.swatch.green" = "Green"
"palette.swatch.teal" = "Teal"
"palette.swatch.blue" = "Blue"
"palette.swatch.violet" = "Violet"
"palette.swatch.magenta" = "Magenta"
"palette.swatch.white" = "White"
"palette.swatch.grey" = "Grey"
"palette.swatch.black" = "Black"
"sliders.hue_min" = "Hue min (°)"
"sliders.hue_max" = "Hue max (°)"
"sliders.sat_min" = "Saturation min (%)"
"sliders.val_min" = "Value min (%)"
"sliders.val_max" = "Value max (%)"
"sliders.alpha" = "Overlay alpha"
"stats.placeholder" = "Matches (with exclusions): —"
"stats.summary" = "Matches (with exclusions): {with_pct:.2f}% | Matches (without exclusions): {without_pct:.2f}% | Excluded: {excluded_pct:.2f}% of pixels, {excluded_match_pct:.2f}% marked"
"menu.copy" = "Copy"
"dialog.info_title" = "Info"
"dialog.error_title" = "Error"
"dialog.saved_title" = "Saved"
"dialog.open_image_title" = "Select image"
"dialog.open_folder_title" = "Select folder"
"dialog.save_overlay_title" = "Save overlay as"
"dialog.choose_colour_title" = "Choose colour"
"dialog.images_filter" = "Images"
"dialog.folder_not_found" = "The folder could not be found."
"dialog.folder_empty" = "No supported images were found in the folder."
"dialog.file_missing" = "File not found: {path}"
"dialog.image_open_failed" = "Image could not be loaded: {error}"
"dialog.load_image_first" = "Please load an image first."
"dialog.no_image_loaded" = "No image loaded."
"dialog.no_preview_available" = "No preview available."
"dialog.overlay_saved" = "Overlay saved: {path}"