diff --git a/crates/ui-egui/src/export_dialog.rs b/crates/ui-egui/src/export_dialog.rs index 6cb0e310d..a322ee108 100644 --- a/crates/ui-egui/src/export_dialog.rs +++ b/crates/ui-egui/src/export_dialog.rs @@ -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)); } diff --git a/crates/ui-egui/src/filter_dialog.rs b/crates/ui-egui/src/filter_dialog.rs index 89fcd3ef9..f4dacbc57 100644 --- a/crates/ui-egui/src/filter_dialog.rs +++ b/crates/ui-egui/src/filter_dialog.rs @@ -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. diff --git a/crates/ui-egui/src/i18n/de.tsv b/crates/ui-egui/src/i18n/de.tsv index cccbfbb35..88ef95767 100644 --- a/crates/ui-egui/src/i18n/de.tsv +++ b/crates/ui-egui/src/i18n/de.tsv @@ -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 diff --git a/crates/ui-egui/src/rotate_view.rs b/crates/ui-egui/src/rotate_view.rs index fa22ac986..5e173da5d 100644 --- a/crates/ui-egui/src/rotate_view.rs +++ b/crates/ui-egui/src/rotate_view.rs @@ -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); diff --git a/crates/ui-egui/src/view_cmds.rs b/crates/ui-egui/src/view_cmds.rs index 5e6d25233..793257be8 100644 --- a/crates/ui-egui/src/view_cmds.rs +++ b/crates/ui-egui/src/view_cmds.rs @@ -996,6 +996,10 @@ pub fn reset_form(f: &mut Map) { } 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"); }); } } diff --git a/crates/ui-egui/src/wheel_nav.rs b/crates/ui-egui/src/wheel_nav.rs index 4523fbc64..c65ad1fe2 100644 --- a/crates/ui-egui/src/wheel_nav.rs +++ b/crates/ui-egui/src/wheel_nav.rs @@ -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 { .. }));