i18n(de): translate the labels that were still English (344 entries) and fix three display bugs (#4008)

* i18n(de): translate the labels that were still English

A walk through the German UI with a lookup recorder (every menu item, every
tool's options bar, every dialog it opens) found 344 texts that fell through
to English. They were invisible to the existing i18n test, which only scans
tl!("literal") calls: the labels of the schema-driven filter dialogs are built
from the engine's parameter names ("centerX" -> "Center X"), and status and
system-info templates are looked up at run time.

- de.tsv: 344 new entries. Filter, Render (Flame, Picture Frame, Tree, Lighting
  Effects), Blur Gallery, Lens Correction, Color Lookup, Shadows/Highlights,
  Apply Image / Calculations, Layer Style blending options, Find and Replace,
  Document Info, the keyboard shortcut editor's commands, system info and the
  tool names that were missing (Color Sampler, Vertical Type, Patch).
  Written from the plain meaning of each label, in the vocabulary the catalog
  already uses (see its header: no proprietary localisation resource consulted).
- "Light" was translated as "Light": the appearance mode in Preferences and the
  toolbar tooltip read "Light" next to "Dunkel". It is "Hell" now (Camera Raw's
  Light section and the font weight have their own contexts).
- Export As: the dialog title was built with format!() and could not be
  translated; it goes through the catalog now.
- Names such as "iPhone 14 Pro Max" (the artboard dialog's preset choices) were
  split like camelCase keys and read "I Phone 14  Pro  Max"; a name with a
  space is shown as it is. Test: display_names_are_not_split_like_camel_case_keys.

Left English on purpose: product and file-format names, units, document and
layer names the engine creates ("Untitled", "Background": other code compares
the latter), brush and swatch preset names (data), and words that are the same
in German (Filter, Info, Zoom, Median...).

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>

* i18n(de): drop the process note and give the new sections English headings

The first heading described how the entries were found (and when), which is not
catalog content, and the other headings were German while the rest of the file
uses short English section comments. Only comment lines change.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>

* i18n(de): US spelling in a section heading

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>

---------

Co-authored-by: Claude Sonnet 5.5 <[email protected]>
This commit is contained in:
DomiLuebbenandClaude Sonnet 5.5 authored and GitHub committed 2026-10-13 13:21:38 -04:00
1 parent be7a1f80fc
commit d35725200d
6 files changed
+376 -8

No files matched your search

+1 -1
View File
@@ -80,7 +80,7 @@ pub fn open_layer(app: &mut PhotocraftApp, layer: photocraft_doc::LayerId) -> Re
let id = open(app)?;
if let Some(d) = app.ui.dialogs.iter_mut().find(|d| d.id == id) {
d.fields.insert("__layer".into(), json!(layer.0));
d.fields.insert("__label".into(), json!(format!("Export As: {}", ldoc.name)));
d.fields.insert("__label".into(), json!(crate::i18n::fmt(crate::i18n::t("Export As: {name}"), &[("name", &ldoc.name)])));
d.fields.insert("__w".into(), json!(ldoc.size.width));
d.fields.insert("__h".into(), json!(ldoc.size.height));
}
+13
View File
@@ -556,6 +556,10 @@ pub(crate) fn source_label(key: &str) -> String {
if key == "localized" {
return "Localized Color Clusters".into();
}
// A name that already reads as text ("iPhone 14 Pro Max", "Web 1920") is not camelCase.
if key.contains(' ') {
return key.to_string();
}
// camelCase → "Camel Case"
let mut s = String::new();
for (i, ch) in key.chars().enumerate() {
@@ -975,6 +979,15 @@ pub struct FilterPreviewKey {
mod tests {
use super::*;
/// Preset names such as "iPhone 14 Pro Max" (the artboard dialog's choices) are text, not
/// camelCase keys: they used to read "I Phone 14 Pro Max".
#[test]
fn display_names_are_not_split_like_camel_case_keys() {
assert_eq!(source_label("iPhone 14 Pro Max"), "iPhone 14 Pro Max");
assert_eq!(source_label("Web 1920"), "Web 1920");
assert_eq!(source_label("centerX"), "Center X");
}
#[test]
fn only_direction_angles_get_the_dial() {
// Every listed command still has a degree `angle` range, so the list cannot go stale.
+355 -1
View File
@@ -1711,7 +1711,7 @@
Layer Knocks Out Drop Shadow Ebene stanzt den Schlagschatten aus
Legal Legal
Letter Letter
Light Light
Light Hell
Line Tool Linien-Werkzeug
Linear Linear
Linear Burn Linear nachbelichten
@@ -2748,6 +2748,360 @@ curves Smooth Glätten
Light Red Hellrot
Medium Blue Mittelblau
Light Gray Hellgrau
# Status messages, system info and tool names
Join the ArtCraft Discord ({url}) Dem ArtCraft-Discord beitreten ({url})
Nothing to paste: the clipboard holds no image Nichts einzufügen: Die Zwischenablage enthält kein Bild
Graphics adapter: {adapter} Grafikadapter: {adapter}
Backend: {backend} ({type}) Backend: {backend} ({type})
Driver: {driver} Treiber: {driver}
GPU backend preference: {backend} Bevorzugtes GPU-Backend: {backend}
Selected at launch: {backend} Beim Start gewählt: {backend}
Image compositor: {processor} Bildkompositor: {processor}
Window renderer: {renderer} Fensterdarstellung: {renderer}
Graphics adapter Grafikadapter
Platform: {os} {arch} Plattform: {os} {arch}
Monitor profile: {profile} Monitorprofil: {profile}
Opened {url} {url} geöffnet
{index} of {total} {index} von {total}
Export As: {name} Exportieren als: {name}
Color Sampler Tool Farbaufnahme-Werkzeug
Vertical Type Tool Vertikales Text-Werkzeug
Patch Tool Ausbessern-Werkzeug
Grid view Rasteransicht
List view Listenansicht
Proof Setup… Proof einrichten…
32-bit Preview Options 32-Bit-Vorschauoptionen
# Shortcut editor commands without a menu item
Toggle Layer Mask Overlay Ebenenmasken-Überlagerung umschalten
Increase Type Size Schriftgröße erhöhen
Decrease Type Size Schriftgröße verringern
Increase Type Size by 10 Schriftgröße um 10 erhöhen
Decrease Type Size by 10 Schriftgröße um 10 verringern
Make Selection from Path Auswahl aus Pfad erstellen
Target Composite Channel Gesamtkanal als Ziel festlegen
Target Channel 3 Kanal 3 als Ziel festlegen
Target Channel 4 Kanal 4 als Ziel festlegen
Target Channel 5 Kanal 5 als Ziel festlegen
Target Channel 6 Kanal 6 als Ziel festlegen
Target Channel 7 Kanal 7 als Ziel festlegen
Target Channel 8 Kanal 8 als Ziel festlegen
Target Channel 9 Kanal 9 als Ziel festlegen
Switch Foreground and Background Colors Vorder- und Hintergrundfarbe vertauschen
Default Foreground and Background Colors Standardfarben für Vorder- und Hintergrund
Fill with Foreground Color Mit Vordergrundfarbe füllen
Fill with Background Color Mit Hintergrundfarbe füllen
Fill with Foreground Color, Preserve Transparency Mit Vordergrundfarbe füllen, Transparenz erhalten
Fill with Background Color, Preserve Transparency Mit Hintergrundfarbe füllen, Transparenz erhalten
Decrease Brush Size Pinselgröße verringern
Increase Brush Size Pinselgröße erhöhen
Decrease Brush Hardness Pinselhärte verringern
Increase Brush Hardness Pinselhärte erhöhen
Temporary Vorübergehend
Space Leertaste
Hand Tool (hold) Hand-Werkzeug (gedrückt halten)
Zoom In (hold, drag to scrub) Vergrößern (gedrückt halten, zum Zoomen ziehen)
Zoom Out (hold) Verkleinern (gedrückt halten)
Erase with Brush or Pencil (hold) Mit Pinsel oder Buntstift radieren (gedrückt halten)
# Document Info and color profiles
Author Title Position des Urhebers
Copyright Status Urheberrechtsstatus
Unknown Unbekannt
Copyrighted Urheberrechtlich geschützt
Public Domain Gemeinfrei
Copyright Url Urheberrechts-URL
Keywords Stichwörter
Title Titel
Profile Profil
Working Arbeitsfarbraum
Working-cmyk Arbeits-CMYK
Coated-cmyk CMYK (gestrichen)
Linear-srgb Lineares sRGB
Gray-gamma-2.2 Grau (Gamma 2,2)
Adobe-rgb-compat Adobe-RGB-kompatibel
Prophoto-compat ProPhoto-kompatibel
Display-p3 Display P3
Intent Renderpriorität
Bpc Schwarzpunktkompensierung
Simulate Paper Papierfarbe simulieren
# Color Lookup, Shadows/Highlights, channels and Calculations
Warming Filter (85) Wärmefilter (85)
Lut LUT
Cool Kühl
Teal Orange Türkis-Orange
Faded Film Verblasster Film
Day For Night Tag für Nacht
Mono Contrast Mono-Kontrast
Cross Process Kreuzentwicklung
Shadow Amount Stärke der Tiefen
Shadow Tone Tonbreite der Tiefen
Shadow Radius Radius der Tiefen
Highlight Amount Stärke der Lichter
Highlight Tone Tonbreite der Lichter
Highlight Radius Radius der Lichter
Midtone Mitteltöne
Black Clip Schwarz beschneiden
White Clip Weiß beschneiden
Strength Stärke
Shadow Schatten
Highlight Lichter
Intensity Intensität
Neutralize Neutralisieren
Use Selection In Source Auswahl in der Quelle verwenden
Use Selection In Target Auswahl im Ziel verwenden
Cw Im Uhrzeigersinn
Ccw Gegen den Uhrzeigersinn
Nearest Nächster Nachbar
Linear Dodge Linear abwedeln
Mask Channel Maskenkanal
R G B RGB
Source Channel Quellkanal
Source Invert Quelle invertieren
Result Ergebnis
Source1 Channel Kanal der Quelle 1
Source1 Invert Quelle 1 invertieren
Source2 Channel Kanal der Quelle 2
Source2 Invert Quelle 2 invertieren
Channel1 Kanal 1
Channel2 Kanal 2
Channel3 Kanal 3
Channel4 Kanal 4
# Measurement log
Label Beschriftung
Date and Time Datum und Uhrzeit
Scale Units Maßstabseinheiten
Scale Factor Maßstabsfaktor
Area Fläche
Perimeter Umfang
Circularity Kreisförmigkeit
Gray Value (Minimum) Grauwert (Minimum)
Gray Value (Maximum) Grauwert (Maximum)
Gray Value (Mean) Grauwert (Mittelwert)
Gray Value (Median) Grauwert (Median)
Integrated Density Integrierte Dichte
Length Länge
W: B:
A: Wi:
# Lens Correction, Blur Gallery and distortion filters
Pattern Fill… Musterfüllung…
Generic Allgemein
Correct Distortion Verzerrung korrigieren
Correct Vignette Vignette korrigieren
Correct C A Chromatische Aberration korrigieren
Auto Scale Automatisch skalieren
Distortion Verzerrung
Red Cyan Rot/Cyan
Blue Yellow Blau/Gelb
Vignette Amount Stärke der Vignette
Vignette Midpoint Mittelpunkt der Vignette
Edge Extension Kantenerweiterung
Hexagon Sechseck
Pentagon Fünfeck
Heptagon Siebeneck
Octagon Achteck
Blade Curvature Krümmung der Blendenlamellen
Depth Map Tiefenkarte
Focal Distance Fokusabstand
Distribution Verteilung
Uniform Gleichmäßig
Monochromatic Monochrom
Seed Startwert
Spin Drehen
Draft Entwurf
Good Gut
Best Beste
Center X Mitte X
Center Y Mitte Y
Circle Kreis
Star Stern
Cross Kreuz
High Hoch
Low Niedrig
Edge Only Nur Kanten
Overlay Edge Kante überlagern
Focus Fokus
Transition Übergang
Speed Geschwindigkeit
Taper Verjüngung
End X Ende X
End Y Ende Y
Blur Angle Weichzeichnungswinkel
Rectangular To Polar Rechteckig zu Polar
Polar To Rectangular Polar zu Rechteckig
Undefined Areas Undefinierte Bereiche
Wrap Umbrechen
Repeat Wiederholen
Horizontal Only Nur horizontal
Vertical Only Nur vertikal
Generators Generatoren
Wavelength Min Wellenlänge min.
Wavelength Max Wellenlänge max.
Amplitude Min Amplitude min.
Amplitude Max Amplitude max.
Sine Sinus
Ridges Grate
Pond Ripples Teichwellen
Out From Center Von der Mitte nach außen
Around Center Um die Mitte
Reduce Color Noise Farbrauschen reduzieren
Sharpen Details Details schärfen
Remove Jpeg Artifact JPEG-Artefakte entfernen
Max Radius Maximaler Radius
Cell Size Zellengröße
Fine Dots Feine Punkte
Medium Dots Mittlere Punkte
Grainy Dots Körnige Punkte
Coarse Dots Grobe Punkte
Short Lines Kurze Linien
Medium Lines Mittlere Linien
Long Lines Lange Linien
Short Strokes Kurze Striche
Medium Strokes Mittlere Striche
Long Strokes Lange Striche
# Render filters: Flame, Picture Frame, Tree
Flame Type Flammentyp
One Flame Along Path Eine Flamme entlang des Pfads
Multiple Flames Along Path Mehrere Flammen entlang des Pfads
Multiple Flames Path Directions Mehrere Flammen, Pfadrichtungen
Multiple Flames Various Length Mehrere Flammen, unterschiedliche Längen
Candle Light Kerzenlicht
Multiple Flames One Direction Mehrere Flammen, eine Richtung
Randomize Length Länge zufällig variieren
Interval Abstand
Adjust Interval For Loops Abstand für Schleifen anpassen
Use Custom Color Eigene Farbe verwenden
Jag Zacken
Flame Lines Flammenlinien
Flame Bottom Alignment Ausrichtung des Flammenfußes
Flame Style Flammenstil
Violent Heftig
Flat Flach
Flame Shape Flammenform
To Center Zur Mitte
Pointed Spitz
Randomize Shapes Formen zufällig variieren
Fine Fein
Frame Rahmen
Vine With Flowers Ranke mit Blumen
Vine With Leaves Ranke mit Blättern
Ivy Efeu
Roses Rosen
Daisies Gänseblümchen
Berries Beeren
Bamboo Bambus
Waves Wellen
Zigzag Zickzack
Rope Seil
Scallops Muschelrand
Double Line Doppellinie
Snowflakes Schneeflocken
Stars Sterne
Hearts Herzen
Arrangement Anordnung
Thickness Dicke
Vine Color Rankenfarbe
Flower Color Blütenfarbe
Leaf Color Blattfarbe
Base Tree Type Baumtyp
Light Direction Lichtrichtung
Leaves Amount Blattmenge
Leaves Size Blattgröße
Branches Height Asthöhe
Branches Thickness Aststärke
Default Leaves Standardblätter
Leaves Color Blattfarbe
Custom Branch Color Eigene Astfarbe
Branches Color Astfarbe
Flat Shading Flächige Schattierung
# Lens, Lighting Effects, depth and mosaic filters
Lens Objektiv
Prime35 Festbrennweite 35
Prime105 Festbrennweite 105
Movie Prime Film-Festbrennweite
Light Type Lichttyp
Point Punkt
Infinite Unendlich
Light X Licht X
Light Y Licht Y
Light Z Licht Z
Target X Ziel X
Target Y Ziel Y
Elevation Höhe
Gloss Glanz
Metallic Metallisch
Ambience Umgebungslicht
White Is High Weiß ist hoch
Ambient Umgebung
Warmth Wärme
Softness Weichheit
Reduce Noise Rauschen reduzieren
Darken Only Nur abdunkeln
Lighten Only Nur aufhellen
Anisotropic Anisotrop
Blocks Blöcke
Pyramids Pyramiden
Depth Mode Tiefenmodus
Random Zufällig
Level Based Stufenbasiert
Solid Front Faces Einfarbige Vorderseiten
Mask Incomplete Blocks Unvollständige Blöcke maskieren
Stylization Stilisierung
Cleanliness Sauberkeit
Bristle Detail Borstendetail
Lighting Beleuchtung
Shine Glanz
Max Offset Maximaler Versatz
Unaltered Unverändert
Lower Untere
Upper Obere
Blast Böe
Stagger Versetzt
From Right Von rechts
From Left Von links
Eliminate Entfernen
Odd Fields Ungerade Halbbilder
Even Fields Gerade Halbbilder
Create By Erzeugen durch
Duplication Duplizieren
Kernel Kern
Input Mode Eingabemodus
Rgb RGB
Hsb HSB
Hsl HSL
Row Order Zeilenreihenfolge
Preserve Erhalten
Squareness Rechteckigkeit
# Find and Replace, image size, Warp and Layer Style blending options
Any Beliebig
Cmyk CMYK
To Nach
Dont Enlarge Nicht vergrößern
Find Suchen
Replace Ersetzen
Change Find Ersetzen und suchen
Case Sensitive Groß-/Kleinschreibung beachten
Whole Word Ganzes Wort
Forward Vorwärts
Based On Basierend auf
General Blending Allgemeine Füllmethode
Advanced Blending Erweiterte Füllmethode
Blend Interior Effects as Group Innere Effekte als Gruppe überblenden
Blend Clipped Layers as Group Ebenen der Schnittmaske als Gruppe überblenden
Transparency Shapes Layer Transparenz bestimmt die Ebenenform
Layer Mask Hides Effects Ebenenmaske blendet Effekte aus
Vector Mask Hides Effects Vektormaske blendet Effekte aus
This Layer: Diese Ebene:
Underlying Layer: Darunterliegende Ebene:
Up Nach oben
Checkerboard Schachbrett
Arc Lower Bogen unten
Arc Upper Bogen oben
Bend Biegen
Horizontal Distortion Horizontale Verzerrung
Vertical Distortion Vertikale Verzerrung
Stretch Strecken
Map Document Dokument zuordnen
Map Path Pfad zuordnen
Fuzziness Toleranz
Object Finder Objektsucher
No object found there — drag a rectangle around it Dort wurde kein Objekt gefunden — ziehen Sie ein Rechteck darum
Remove after each stroke Nach jedem Strich entfernen
Can't render this file because it contains an unexpected character in line 6 and column 47.
+1 -4
View File
@@ -322,10 +322,7 @@ mod tests {
let ctx = egui::Context::default();
let mut enabled = None;
let mut disabled = None;
let raw = egui::RawInput {
events: vec![Event::Rotate(std::f32::consts::FRAC_PI_6)],
..Default::default()
};
let raw = egui::RawInput { events: vec![Event::Rotate(std::f32::consts::FRAC_PI_6)], ..Default::default() };
let mut output = ctx.run_ui(raw, |ui| {
enabled = trackpad_delta(ui.ctx(), true);
disabled = trackpad_delta(ui.ctx(), false);
+5
View File
@@ -996,6 +996,10 @@ pub fn reset_form(f: &mut Map<String, Value>) {
}
fn label_of(key: &str) -> String {
// A name that already reads as text ("iPhone 14 Pro Max", "Web 1920") is not camelCase.
if key.contains(' ') {
return tl!(key).to_owned();
}
let mut out = String::new();
for (i, c) in key.chars().enumerate() {
if i == 0 {
@@ -1026,6 +1030,7 @@ mod label_tests {
crate::i18n::with_language(crate::i18n::Lang::EN, || {
assert_eq!(label_of("useAntialias"), "Use antialias");
assert_eq!(label_of("radius"), "Radius");
assert_eq!(label_of("iPhone 14 Pro Max"), "iPhone 14 Pro Max");
});
}
}
+1 -2
View File
@@ -381,8 +381,7 @@ mod tests {
assert!(matches!(legacy.events[0], Event::Zoom(_)));
// Native magnification takes over before the synthetic gesture times out.
let mut native =
RawInput { time: Some(1.1), events: vec![Event::Zoom(1.1), wheel(Vec2::new(0.0, 0.25), CTRL)], ..Default::default() };
let mut native = RawInput { time: Some(1.1), events: vec![Event::Zoom(1.1), wheel(Vec2::new(0.0, 0.25), CTRL)], ..Default::default() };
fold_legacy_pinch(&ctx, &mut native);
assert!(matches!(native.events[0], Event::Zoom(f) if (f - 1.1).abs() < 1e-5));
assert!(matches!(native.events[1], Event::MouseWheel { .. }));