i18n: refine az/ro translations and address review findings

This commit is contained in:
Taxperia committed 2026-10-31 23:48:40 +03:00
1 parent 5d54be710c
commit 349977449b
8 files changed
+142 -63

No files matched your search

+18 -18
View File
@@ -203,7 +203,7 @@
Create Clipping Mask Kəsici maska yarat
Release Clipping Mask Kəsmə maskasını buraxın
New Shape Layer Yeni Forma Layeri
New Type Layer Yeni tip qat
New Type Layer Yeni mətn qatı
New Video Layer from File… Fayldan yeni video qatı…
New Blank Video Layer Yeni boş video qatı
Smart Filters Ağıllı filtrlər
@@ -1390,19 +1390,19 @@
Breeze dark Qaranlıq meh
Breeze Dark Theme Breeze Qaranlıq Mövzu
Breeze light Külək işığı
Breeze Light Theme Breeze Light Theme
Breeze Light Theme Breeze açıq mövzusu
Soft dark Yumşaq qaranlıq
Soft light Yumşaq işıq
Soft Dark Theme Soft Dark Theme
Soft Light Theme Yumşaq İşıq Mövzu
Soft Light Theme Soft açıq mövzusu
Studio Theme Studiya mövzusu
Studio Light Theme Studio Yüngül Mövzu
Adwaita Light Theme Adwaita Yüngül Mövzu
Studio Light Theme Studio açıq mövzusu
Adwaita Light Theme Adwaita açıq mövzusu
Adwaita Dark Theme Adwaita Qaranlıq Mövzu
Pro Theme Pro Mövzu
Pro Medium Gray Theme Pro Orta Boz Mövzu
Pro Light Gray Theme Pro Açıq Boz Mövzu
Pro Light Theme Pro Yüngül Mövzu
Pro Light Theme Pro açıq mövzusu
Workspace… İş sahəsi…
Essentials Əsaslar
New Workspace… Yeni İş Sahəsi…
@@ -1513,7 +1513,7 @@
No matching commands Uyğun əmrlər yoxdur
No document Sənəd yoxdur
Pixel Layer Piksel qatı
Type Layer Layer yazın
Type Layer Mətn qatı
Shape Layer Forma qatı
Group Layer Qrup qatı
Fill Layer Doldurma Layeri
@@ -2211,7 +2211,7 @@
CPU (no GPU acceleration) CPU (GPU sürətləndirilməsi yoxdur)
Cache levels Keş səviyyələri
Cache tile size Keş kafel ölçüsü
Camera Raw Defaults Kamera Raw Defoltları
Camera Raw Defaults Camera Raw ilkin ayarları
Canvas border Kətan haşiyəsi
Show canvas dots Kətan nöqtələrini göstərin
Clip thumbnails to layer bounds Miniatürləri qat sərhədlərinə kəsin
@@ -2228,7 +2228,7 @@
Cursors Kursorlar
Custom dark Fərdi qaranlıq
Custom light Fərdi işıq
Dark Qaranlıq
Dark Tünd
Dark gray Tünd boz
Dashed lines kəsik xətlər
Detailed Ətraflı
@@ -2237,7 +2237,7 @@
Display p3 Ekran p3
Dots Nöqtələr
Double click layer mask launches select and mask İki dəfə kliklənən qat maskası seçin və maskanı işə salır
Drop shadow Açılan kölgə
Drop shadow Düşən kölgə
Dynamic color sliders Dinamik rəng sürgüləri
East asian Şərqi Asiya
Effect cache mb Effekt önbelleği mb
@@ -2270,9 +2270,9 @@
Gridline every Gridline hər
Guide color Bələdçi rəngi
Guide style Bələdçi üslubu
Guides, Grid & Slices Bələdçilər, Torlar və Dilimlər
Guides, Grid & Slices Bələdçilər, tor və dilimlər
Gutter Oluk
History Log Tarix jurnalı
History Log Tarixçə jurnalı
History states Tarix dövlətləri
Ignore exif profile tag Exif profil etiketinə məhəl qoymayın
Image interpolation Şəkil interpolasiyası
@@ -2341,7 +2341,7 @@
Show menu colors Menyu rənglərini göstərin
Show only crosshair while painting Rəsm edərkən yalnız çarpaz işarəni göstərin
Show slice numbers Dilim nömrələrini göstərin
Show tooltips Alət göstərişlərini göstərin
Show tooltips Alət ipuclarını göstər
Enable animations Animasiyaları aktivləşdirin
Show highlight on rollover Köçürmə zamanı vurğunu göstərin
Show bounding box when dragging layer Qatı sürükləyərkən məhdudlaşdırıcı qutunu göstərin
@@ -2366,7 +2366,7 @@
Traditional (72.27 points/inch) Ənənəvi (72,27 bal/düym)
Transparency & Gamut Şəffaflıq və rəng əhatəsi
Type units Növ vahidləri
UI font size UI şrift ölçüsü
UI font size UI şriftinin ölçüsü
UI scale UI miqyası
Units & Rulers Vahidlər və xətkeşlər
Use additional plugins folder Əlavə plaginlər qovluğundan istifadə edin
@@ -2667,8 +2667,8 @@ fontWeight Italic Kursiv
Bundle Arrow-Key Nudges Ox düyməsi köçürmələrini qruplaşdır
Nudge Bundle Pause (ms) Köçürmə qruplaşdırma fasiləsi (ms)
Appearance Mode Görünüş rejimi
Dark Theme Qaranlıq Mövzu
Light Theme Yüngül Mövzu
Dark Theme Tünd mövzu
Light Theme Açıq mövzu
Pro Medium Pro Orta
Studio Light Studiya işığı
Next Appearance Mode Növbəti Görünüş Rejimi
@@ -2786,7 +2786,7 @@ fontWeight Italic Kursiv
How often fastening points are placed by themselves Bərkitmə nöqtələri özləri tərəfindən nə qədər tez-tez yerləşdirilir
Hue/Saturation Rəng/Doyma
Intersect with selection ({key}) Seçimlə kəsişir ( {key} )
Kind Xeyirxah
Kind Növ
Linear Gradient Xətti Gradient
Link layers Bağlantı qatları
Lock Kilid
@@ -2996,7 +2996,7 @@ curves Smooth Hamarlama
Delete Contour Konturu silin
Loaded contours from {file} {file} -dən yüklənmiş konturlar
Saved contours to {file} Saxlanılan konturlar {file}
Show home recent files Evdəki son faylları göstərin
Show home recent files Ana səhifədə son faylları göstər
Clear Brush Controls Fırça nəzarətlərini təmizləyin
Reset All Locked Settings Bütün Kilidli Parametrləri Sıfırlayın
Copy Texture to Other Tools Teksturanı Digər Alətlərə Kopyalayın
Can't render this file because it contains an unexpected character in line 1346 and column 18.
+53 -3
View File
@@ -15,6 +15,7 @@ fn lang(code: &str) -> Lang {
Lang::from_code(code).expect("registered language")
}
/// Regional preferences resolve to their registered base catalog across all requested languages.
#[test]
fn requested_languages_resolve_regional_preferences() {
for (tag, code) in [
@@ -39,21 +40,47 @@ fn requested_languages_resolve_regional_preferences() {
assert_eq!(lang_from_tag("ko"), Some(lang("ko")));
}
/// Switching redraws the menu and persists through the shell's save/load services on restart.
#[test]
fn azerbaijani_and_romanian_draw_after_switching_and_restore_after_restart() {
use std::{cell::RefCell, rc::Rc};
for (code, file) in [("az", "Fayl"), ("ro", "Fișier")] {
with_language(Lang::EN, || {
let mut h = harness();
let saved = Rc::new(RefCell::new(None::<String>));
let (load, store) = (saved.clone(), saved.clone());
let services = Services {
load_prefs: Some(Box::new(move || load.borrow().clone())),
save_prefs: Some(Box::new(move |text| {
*store.borrow_mut() = Some(text.to_owned());
Ok(())
})),
..Default::default()
};
let mut h = harness_with_services(services);
h.state_mut().run("prefs.set", json!({"path": "interface.language", "value": code})).expect("choose language");
h.run_steps(4);
assert_eq!(current(), lang(code));
assert_eq!(tr(current(), "File"), file);
assert!(drawn_text(&h).iter().any(|text| *text == file_title(lang(code))));
let saved = h.state().session.prefs_to_json();
let persisted = saved.borrow().clone().expect("shell saved preferences");
let value: serde_json::Value = serde_json::from_str(&persisted).expect("saved JSON");
assert_eq!(value["interface"]["language"], code);
h.state_mut().run("prefs.set", json!({"path": "interface.language", "value": "en"})).expect("switch back");
h.run_steps(4);
assert_eq!(current(), Lang::EN);
let services = Services { load_prefs: Some(Box::new(move || Some(saved.clone()))), ..Default::default() };
assert_eq!(
serde_json::from_str::<serde_json::Value>(&saved.borrow().clone().expect("saved English preferences")).expect("saved JSON")["interface"]["language"],
"en"
);
h.state_mut().run("prefs.set", json!({"path": "interface.language", "value": code})).expect("choose language again");
h.run_steps(4);
assert_eq!(
serde_json::from_str::<serde_json::Value>(&saved.borrow().clone().expect("saved language preferences")).expect("saved JSON")["interface"]["language"],
code
);
drop(h);
let services = Services { load_prefs: Some(Box::new(move || saved.borrow().clone())), ..Default::default() };
let restarted = harness_with_services(services);
assert_eq!(restarted.state().session.prefs().interface.language, code);
assert_eq!(current(), lang(code));
@@ -62,6 +89,28 @@ fn azerbaijani_and_romanian_draw_after_switching_and_restore_after_restart() {
}
}
/// Preferences draw the catalog terms verbatim and the bundled UI font covers their letters.
#[test]
fn azerbaijani_and_romanian_preferences_draw_terms_and_glyphs() {
for (code, interface, light) in [("az", "İnterfeys", "Açıq mövzu"), ("ro", "Interfață", "Temă deschisă")] {
with_language(Lang::EN, || {
let mut h = harness();
h.state_mut().run("prefs.set", json!({"path": "interface.language", "value": code})).expect("choose language");
crate::prefs_ui::open_preferences(h.state_mut(), "interface");
h.run_steps(4);
let text = drawn_text(&h);
for expected in [interface, light, tr(lang(code), "UI font size"), tr(lang(code), "UI scale")] {
assert!(text.iter().any(|text| text == expected), "{code}: missing {expected:?}");
h.ctx.fonts_mut(|fonts| {
for c in expected.chars().filter(|c| c.is_alphabetic()) {
assert!(fonts.has_glyph(&egui::FontId::proportional(12.0), c), "{code}: missing glyph {c}");
}
});
}
});
}
}
#[test]
fn ukrainian_native_app_menu_keeps_product_and_language_names() {
with_language(Lang::EN, || {
@@ -254,6 +303,7 @@ fn harness_with_services(services: Services) -> egui_kittest::Harness<'static, P
harness
}
/// Auto draws the detected system language on first launch while keeping the Auto preference.
#[test]
fn first_launch_renders_the_system_language_without_overwriting_auto() {
for (tag, code) in [
+20 -20
View File
@@ -203,7 +203,7 @@
Create Clipping Mask Creează o mască de decupare
Release Clipping Mask Eliberați masca de tăiere
New Shape Layer Strat de formă nou
New Type Layer Strat de tip nou
New Type Layer Strat de text nou
New Video Layer from File… Strat video nou din fișier…
New Blank Video Layer Strat video gol nou
Smart Filters Filtre inteligente
@@ -1390,19 +1390,19 @@
Breeze dark Briză întunecată
Breeze Dark Theme Breeze Dark Theme
Breeze light Briză lumină
Breeze Light Theme Tema Brizei Lumină
Breeze Light Theme Temă deschisă Breeze
Soft dark Întuneric moale
Soft light Lumină moale
Soft Dark Theme Tema Soft Dark
Soft Light Theme Tema Lumină moale
Soft Light Theme Temă deschisă Soft
Studio Theme Tema Studio
Studio Light Theme Studio Light Theme
Adwaita Light Theme Tema luminii Adwaita
Studio Light Theme Temă deschisă Studio
Adwaita Light Theme Temă deschisă Adwaita
Adwaita Dark Theme Tema întunecată Adwaita
Pro Theme Tema Pro
Pro Medium Gray Theme Tema Pro Medium Gri
Pro Light Gray Theme Temă Pro Gri deschis
Pro Light Theme Tema Pro Light
Pro Light Theme Temă deschisă Pro
Workspace… Spațiu de lucru…
Essentials Esențiale
New Workspace… Nou spațiu de lucru…
@@ -1513,7 +1513,7 @@
No matching commands Nu există comenzi care se potrivesc
No document Niciun document
Pixel Layer Strat de pixeli
Type Layer Tip strat
Type Layer Strat de text
Shape Layer Strat de formă
Group Layer Strat de grup
Fill Layer Strat de umplere
@@ -2211,7 +2211,7 @@
CPU (no GPU acceleration) CPU (fără accelerare GPU)
Cache levels Niveluri cache
Cache tile size Dimensiunea piesei cache
Camera Raw Defaults Camera Raw implicite
Camera Raw Defaults Setări implicite Camera Raw
Canvas border Chenar pânză
Show canvas dots Afișați puncte de pânză
Clip thumbnails to layer bounds Decupați miniaturile la limitele stratului
@@ -2228,7 +2228,7 @@
Cursors Cursore
Custom dark Întuneric personalizat
Custom light Lumină personalizată
Dark Întuneric
Dark Întunecat
Dark gray Gri închis
Dashed lines linii întrerupte
Detailed Detaliat
@@ -2238,7 +2238,7 @@
Dots puncte
Double click layer mask launches select and mask Faceți dublu clic pe masca de strat lansează selectarea și masca
Drop shadow Umbră
Dynamic color sliders glisoare de culoare dinamice
Dynamic color sliders Glisoare dinamice de culoare
East asian Asia de Est
Effect cache mb Cache efect mb
Enable flick panning Activați flick panning
@@ -2270,9 +2270,9 @@
Gridline every Gridline fiecare
Guide color Culoare ghid
Guide style Stilul ghid
Guides, Grid & Slices Ghiduri, grilă și felii
Guides, Grid & Slices Ghidaje, grilă și secțiuni
Gutter Jgheab
History Log Jurnal istoric
History Log Jurnalul istoricului
History states Istoria afirmă
Ignore exif profile tag Ignorați eticheta de profil exif
Image interpolation Interpolare imagine
@@ -2341,7 +2341,7 @@
Show menu colors Afișați culorile meniului
Show only crosshair while painting Afișați numai încrucișarea în timp ce pictați
Show slice numbers Afișați numerele secțiunilor
Show tooltips Afișați sfaturi cu instrumente
Show tooltips Afișați indicii
Enable animations Activați animațiile
Show highlight on rollover Afișați evidențierea la trecere
Show bounding box when dragging layer Afișează caseta de delimitare când trageți stratul
@@ -2366,8 +2366,8 @@
Traditional (72.27 points/inch) Tradițional (72,27 puncte/inch)
Transparency & Gamut Transparență și gamă
Type units Tip unități
UI font size dimensiunea fontului UI
UI scale scară UI
UI font size Dimensiunea fontului UI
UI scale Scalare UI
Units & Rulers Unități și rigle
Use additional plugins folder Folosiți folderul de pluginuri suplimentare
Use esc to commit Folosiți esc pentru a comite
@@ -2666,9 +2666,9 @@ fontWeight Italic Cursiv
Notification Duration (seconds) Durata notificării (secunde)
Bundle Arrow-Key Nudges Grupează deplasările cu săgețile
Nudge Bundle Pause (ms) Pauză de grupare a deplasărilor (ms)
Appearance Mode Modul aspect
Dark Theme Tema întunecată
Light Theme Tema ușoară
Appearance Mode Mod de afișare
Dark Theme Temă întunecată
Light Theme Temă deschisă
Pro Medium Mediu Pro
Studio Light Studio Light
Next Appearance Mode Următorul mod de apariție
@@ -2786,7 +2786,7 @@ fontWeight Italic Cursiv
How often fastening points are placed by themselves Cât de des punctele de fixare sunt amplasate singure
Hue/Saturation Nuanță/Saturație
Intersect with selection ({key}) Se intersectează cu selecția ( {key} )
Kind Amabil
Kind Tip
Linear Gradient Gradient liniar
Link layers Straturi de legătură
Lock Blocare
@@ -2996,7 +2996,7 @@ curves Smooth Netezire
Delete Contour Șterge contur
Loaded contours from {file} Contururi încărcate de la {file}
Saved contours to {file} Contururi salvate în {file}
Show home recent files Afișați fișierele recente de acasă
Show home recent files Afișați fișierele recente pe pagina principală
Clear Brush Controls Ștergeți comenzile pensulei
Reset All Locked Settings Resetați toate setările blocate
Copy Texture to Other Tools Copiați textura în alte instrumente
Can't render this file because it contains an unexpected character in line 1346 and column 18.
+7
View File
@@ -292,6 +292,7 @@ fn serbian_plural_rule_handles_teens_and_compound_counts() {
assert_eq!(forms, [2, 0, 1, 1, 2, 2, 2, 2, 0, 1, 2, 0, 2, 2, 1]);
}
/// Both catalogs resolve regional tags, expose their native names and fall back to English.
#[test]
fn azerbaijani_and_romanian_resolve_locales_and_preferences() {
for (code, name, tags) in [
@@ -310,6 +311,7 @@ fn azerbaijani_and_romanian_resolve_locales_and_preferences() {
}
}
/// Integer plural boundaries select the correct catalog form, including at `u64::MAX`.
#[test]
fn azerbaijani_and_romanian_plural_counts_include_hundreds_and_large_values() {
let az = Lang::from_code("az").expect("az registered");
@@ -324,12 +326,16 @@ fn azerbaijani_and_romanian_plural_counts_include_hundreds_and_large_values() {
assert_eq!(trn(az, 20, "{n} layer", "{n} layers"), "20 qat");
}
/// Context and command lookups retain distinct meanings while preserving product placeholders.
#[test]
fn azerbaijani_and_romanian_keep_context_placeholders_and_command_names() {
for (code, file, layer, light, font_light) in [("az", "Fayl", "Qat", "İşıq", "İncə"), ("ro", "Fișier", "Strat", "Lumină", "Subțire")] {
let lang = Lang::from_code(code).expect("registered language");
assert_eq!(tr(lang, "File"), file);
assert_eq!(tr(lang, "Layer"), layer);
assert_eq!(tr(lang, "Kind"), if code == "az" { "Növ" } else { "Tip" });
assert_eq!(tr(lang, "Type Layer"), if code == "az" { "Mətn qatı" } else { "Strat de text" });
assert_eq!(tr(lang, "Light Theme"), if code == "az" { "Açıq mövzu" } else { "Temă deschisă" });
assert_eq!(tr_ctx(lang, "cameraRaw", "Light"), light);
assert_eq!(tr_ctx(lang, "fontWeight", "Light"), font_light);
assert_ne!(tr_id(lang, "edit.clear", "Clear"), "Clear");
@@ -337,6 +343,7 @@ fn azerbaijani_and_romanian_keep_context_placeholders_and_command_names() {
}
}
/// Every menu label and submenu segment has a lookup entry in both new catalogs.
#[test]
fn azerbaijani_and_romanian_cover_every_menu_label_and_path() {
for code in ["az", "ro"] {
+4 -3
View File
@@ -1,6 +1,6 @@
# Where PhotoCraft falls short of Photoshop
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-31 · **Change:** minor (Azerbaijani and Romanian UI catalogs; native review and Rust/offscreen verification pending; selected colour sets edit drawing, tone and supported filters; geometry remains open; G11: `.atn` document offsets preserve opening order after tab reordering, #7103; embedded AI/PDF/EPS save-back retains native format with a source-bound SVG display preview; Smooth and Feather command masks cropped to selection bounds plus blur reach; G1: Halftone Pattern Filter Gallery settings survive PSD/PSB saves (#8940); cropped selection morphology and command mask conversion performance evidence added; G9: 12 of 181 preferences do nothing, as the scorecard prefs audit counts them; G6: Art History Brush landed as partial, TOOL-213-20, #1610, so no toolbar tool is missing; G4: five hard-round built-in presets use 5% spacing to remove stacked-tip outlines and reduce pressure-opacity bands, #8842; G9: Crop tool canvas menu, #6561; G2: Content-Aware Scale seam carving 1.65–3.6× faster with unchanged output, P28 row 3.3 → 1.6 s on a 4-core VM, #5236; G9: UI scale presets done, 105–120% steps, #3222; G14: lossy DNG, raw sidecars, Camera Raw Defaults live, Calibration and Auto, CR3 assessed as not clean-room feasible; G8: PSD type on a path opens on its path and saves back into the file's `Txt2`, #7962; G11: a recorded Save As imports with its format and file (`file.saveAs`, `file.saveACopy` for As a Copy) instead of as a plain Save that wrote over the played file, #7102; folder destinations stop playback until #5430; adjustment clipping stays visible in compact Properties, #5231; G9: Color panel modes, ramp and copy commands, the same in every theme, UI-217-17, #6000; G17: Help › Check for Updates and an opt-out check once per launch, DIST-220-1 partial, #5485; G10: `.asl` style libraries landed, #1051; G8: area type (TYPE-218-10); G1: smart objects keep Photoshop's Cylinder warp, #4112; G8: paragraph direction buttons in the Paragraph panel and options bar, TYPE-218-2 partial; G1: 32-bit Hue/Saturation and Colorize as Photoshop does them, Photoshop-oracle floor 190/258, #5781; G11: compound layer properties export as separate Photoshop Set events, rename last, #8304; G11: Batch and droplets take the result at the action's Save step, so actions ending in Save As and Close work; G11: `.atn` steps that switch to another open document import, play and save back, #7103; G14: the Nikon D4 white level follows the sample depth, so 12-bit D4 NEFs no longer open 2.6 stops dark, #5978; G14: a Nikon NEF's Adobe RGB preview is read as Adobe RGB (maker-note ColorSpace 0x001E), #5987; Apply Layer Comp action mapping, #7101; G10: JPEG Options dialog landed, FILE-215-19 partial (no Matte, progressive Scans or size preview); G10: Cineon write; G10: DPX read and write, #1049, Cineon and Amiga IFF read; Classical Object Finder improvement; learned segmentation remains open; G4: named, stateful section locks and visible keyboard focus in Brush Settings; G4: independent Brush Pose tilt-axis overrides, #3825 partial; G4: Transfer Mixer-only controls, #3825 partial; G9: Preferences › File Handling › Save in Background takes effect, #6207, 24 of 169 preferences do nothing; G7: Content-Aware Move previews every selection the command takes, coarse then exact, TOOL-213-4 done, #6680; G4: Pattern Stamp and Background Eraser draw live, TOOL-213-7; G9: Animated Zoom pref read: holding the Zoom tool zooms continuously, #6210, prefs that do nothing 25 of 166; G2: a cancelled 24 MP Gaussian Blur job stops in at most 44 ms, P25 under its 200 ms budget in local runs, baseline not re-run, #6205; G1: generated large-file fixtures, a 4.38 GB PSB opens on Windows through io, FILE-216-2 done, #5107; G9: fill and adjustment layers copy and paste whole, #2344; G1: smart filter masks show on PSD open, Photoshop-oracle floor 188/258; G10: DPX read and write, #1049, Cineon read; G1: CMYK Hue/Saturation and Color Balance keep the black ink; G1: CMYK Posterize on the stored values, psd-tools oracle floor 242/309; G1: CMYK adjustment layers composite on the document's inks, Photoshop-oracle floor 165/258; G1: CMYK Brightness/Contrast on the inks, CMYK Threshold's luma; G1: modern Brightness/Contrast's brightness curve matches Photoshop, Photoshop-oracle floor 151/258; G1: Lab documents composite on their stored L, a, b, Photoshop-oracle floor 152/258; G1: Levels on whole levels at every step, Photoshop-oracle floor 146/258, psd-tools 238/309; G1: 32-bit Brightness/Contrast legacy, Channel Mixer, Photo Filter and Black & White tint unclipped as in Photoshop, Photoshop-oracle floor 149/258; G1: mask feathers blur with their exact variance, psd-tools oracle floor 240/309; G1: Threshold splits on Photoshop's luminosity, psd-tools oracle floor 241/309; G1: pass-through clipping base with an adjustment renders isolated, psd-tools oracle floor 240/309; G1: 16-bit Posterize as Photoshop bLine truncated
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-31 · **Change:** minor (Azerbaijani and Romanian UI catalogs; native review pending; local build and focused checks verified; selected colour sets edit drawing, tone and supported filters; geometry remains open; G11: `.atn` document offsets preserve opening order after tab reordering, #7103; embedded AI/PDF/EPS save-back retains native format with a source-bound SVG display preview; Smooth and Feather command masks cropped to selection bounds plus blur reach; G1: Halftone Pattern Filter Gallery settings survive PSD/PSB saves (#8940); cropped selection morphology and command mask conversion performance evidence added; G9: 12 of 181 preferences do nothing, as the scorecard prefs audit counts them; G6: Art History Brush landed as partial, TOOL-213-20, #1610, so no toolbar tool is missing; G4: five hard-round built-in presets use 5% spacing to remove stacked-tip outlines and reduce pressure-opacity bands, #8842; G9: Crop tool canvas menu, #6561; G2: Content-Aware Scale seam carving 1.65–3.6× faster with unchanged output, P28 row 3.3 → 1.6 s on a 4-core VM, #5236; G9: UI scale presets done, 105–120% steps, #3222; G14: lossy DNG, raw sidecars, Camera Raw Defaults live, Calibration and Auto, CR3 assessed as not clean-room feasible; G8: PSD type on a path opens on its path and saves back into the file's `Txt2`, #7962; G11: a recorded Save As imports with its format and file (`file.saveAs`, `file.saveACopy` for As a Copy) instead of as a plain Save that wrote over the played file, #7102; folder destinations stop playback until #5430; adjustment clipping stays visible in compact Properties, #5231; G9: Color panel modes, ramp and copy commands, the same in every theme, UI-217-17, #6000; G17: Help › Check for Updates and an opt-out check once per launch, DIST-220-1 partial, #5485; G10: `.asl` style libraries landed, #1051; G8: area type (TYPE-218-10); G1: smart objects keep Photoshop's Cylinder warp, #4112; G8: paragraph direction buttons in the Paragraph panel and options bar, TYPE-218-2 partial; G1: 32-bit Hue/Saturation and Colorize as Photoshop does them, Photoshop-oracle floor 190/258, #5781; G11: compound layer properties export as separate Photoshop Set events, rename last, #8304; G11: Batch and droplets take the result at the action's Save step, so actions ending in Save As and Close work; G11: `.atn` steps that switch to another open document import, play and save back, #7103; G14: the Nikon D4 white level follows the sample depth, so 12-bit D4 NEFs no longer open 2.6 stops dark, #5978; G14: a Nikon NEF's Adobe RGB preview is read as Adobe RGB (maker-note ColorSpace 0x001E), #5987; Apply Layer Comp action mapping, #7101; G10: JPEG Options dialog landed, FILE-215-19 partial (no Matte, progressive Scans or size preview); G10: Cineon write; G10: DPX read and write, #1049, Cineon and Amiga IFF read; Classical Object Finder improvement; learned segmentation remains open; G4: named, stateful section locks and visible keyboard focus in Brush Settings; G4: independent Brush Pose tilt-axis overrides, #3825 partial; G4: Transfer Mixer-only controls, #3825 partial; G9: Preferences › File Handling › Save in Background takes effect, #6207, 24 of 169 preferences do nothing; G7: Content-Aware Move previews every selection the command takes, coarse then exact, TOOL-213-4 done, #6680; G4: Pattern Stamp and Background Eraser draw live, TOOL-213-7; G9: Animated Zoom pref read: holding the Zoom tool zooms continuously, #6210, prefs that do nothing 25 of 166; G2: a cancelled 24 MP Gaussian Blur job stops in at most 44 ms, P25 under its 200 ms budget in local runs, baseline not re-run, #6205; G1: generated large-file fixtures, a 4.38 GB PSB opens on Windows through io, FILE-216-2 done, #5107; G9: fill and adjustment layers copy and paste whole, #2344; G1: smart filter masks show on PSD open, Photoshop-oracle floor 188/258; G10: DPX read and write, #1049, Cineon read; G1: CMYK Hue/Saturation and Color Balance keep the black ink; G1: CMYK Posterize on the stored values, psd-tools oracle floor 242/309; G1: CMYK adjustment layers composite on the document's inks, Photoshop-oracle floor 165/258; G1: CMYK Brightness/Contrast on the inks, CMYK Threshold's luma; G1: modern Brightness/Contrast's brightness curve matches Photoshop, Photoshop-oracle floor 151/258; G1: Lab documents composite on their stored L, a, b, Photoshop-oracle floor 152/258; G1: Levels on whole levels at every step, Photoshop-oracle floor 146/258, psd-tools 238/309; G1: 32-bit Brightness/Contrast legacy, Channel Mixer, Photo Filter and Black & White tint unclipped as in Photoshop, Photoshop-oracle floor 149/258; G1: mask feathers blur with their exact variance, psd-tools oracle floor 240/309; G1: Threshold splits on Photoshop's luminosity, psd-tools oracle floor 241/309; G1: pass-through clipping base with an adjustment renders isolated, psd-tools oracle floor 240/309; G1: 16-bit Posterize as PhLine truncated
Every known shortfall against Photoshop 2026 (27.11.0), one entry each, ranked by user impact
on the way to beta. This is the work list agents pick from: take the highest-ranked entry that
@@ -398,7 +398,8 @@ what an agent can't finish alone.
### G13. Hindi, Arabic, Vietnamese, RTL and engine messages
- **Progress (2026-10-31):** Azerbaijani (`az`, Latin script) and Romanian (`ro`) catalogs add
4,566 entries each, regional locale matching and plural messages (Romanian one/few/other).
Native-speaker review and Rust/offscreen verification remain pending; engine messages,
Native-speaker review remains pending. Local build and focused checks passed; the
localization notes record full-suite limits. Engine messages,
estimated readiness and the remaining G13 scope are unchanged. See [notes](localization-az-ro.md).
- **Missing:** catalogs for Hindi, Arabic and Vietnamese (3 of the 12 key languages); right-to-
left UI layout; Devanagari fallback fonts (Thai #1909 and Khmer, Lao and Myanmar #3259 landed); engine error and status messages in
@@ -428,7 +429,7 @@ what an agent can't finish alone.
| Date | Change | Summary |
|---|---|---|
| 2026-10-31 | minor | G13: Azerbaijani and Romanian catalogs, 4,566 entries each; regional tags and plural rules; native review and Rust/offscreen verification pending; estimates unchanged |
| 2026-10-31 | minor | G13: Azerbaijani and Romanian catalogs, 4,566 entries each; regional tags and plural rules; native review pending; local build and focused checks verified; estimates unchanged |
| 2026-10-27 | minor | Smooth/Feather command reads and replacement use selection bounds plus blur reach; full-canvas reference and release comparisons extended; percentages and scorecard budgets unchanged |
| 2026-10-27 | minor | G9: 12 of 181 preferences do nothing, the scorecard's count with integration batch 9 (#9775) on main; no estimate changed |
| 2026-10-26 | minor | Expand/Contract/Border distance work, mask reads and replacement cropped to nonzero bounds; bounded distances for radii ≤5; 36 MP exact-output comparisons improve 1.54–37.82× across eight cases; percentages, estimates and scorecard budgets unchanged |
+24 -7
View File
@@ -59,11 +59,28 @@ fallback behavior, contextual terms, placeholders, menu coverage and plural coun
19/20, 100/101, 119/120 and `u64::MAX`. Shell tests cover language switching, English restoration,
persisted preferences, restart and first-launch Auto detection for the new languages.
Static catalog checks inspect duplicate keys, TSV structure, placeholders in every plural form,
trailing ellipses, the complete menu tree and source-derived localization keys. Rust tests,
Clippy, wasm checks and offscreen app rendering require a Rust-equipped environment; the
implementation environment had neither `cargo` nor `rustc`, so those checks were not run here.
Local verification on 2026-10-31 used Rust 1.99.1 and MSVC on Windows x64:
Before merging, run `cargo test -p photocraft-ui-egui`,
`cargo clippy -p photocraft-ui-egui --all-targets -- -D warnings`, `cargo xtask layers`,
`cargo xtask wasm`, `cargo xtask i18n-coverage` and the offscreen snapshot example.
- The native `photocraft` binary and `snapshot` example built successfully with the locked
dependencies. These were unoptimized debug builds, not performance measurements.
- All six Azerbaijani/Romanian unit and shell tests passed, including saving through
`Services.save_prefs`, loading after restart, preference labels and UI glyph coverage.
- `cargo fmt --all -- --check`, `cargo clippy -p photocraft-ui-egui --all-targets -- -D warnings`,
`cargo xtask layers` and `cargo xtask wasm` passed. The wasm check covered 24 crates and
the optional HEIF feature.
- `cargo xtask i18n-coverage` reported 2,204 / 2,204 source keys for each new language.
Static TSV, duplicate, placeholder and ellipsis checks passed; the Rust test comparing
packed catalogs with their source files also passed.
- Editor and Interface Preferences screenshots for both languages were rendered offscreen
at 1440 × 900 logical pixels and 1.5× scale, using `--safe-gpu`, and visually inspected.
This caught incorrect translations of Kind, Type Layer, Light Theme and preference labels,
which were corrected and covered by regressions. These captures verify the CPU canvas
path, not hardware-GPU rendering or native window/input behavior.
**The full test gate is not green.** The i18n subset finished with 59 passed and eight failed:
the existing Chinese/Japanese/Korean/Arabic shell checks reported missing glyphs in this
build without the optional `CRAFT_FONTS_DIR` input. All six new-language tests passed.
The full `cargo test -p photocraft-ui-egui --no-fail-fast` run terminated both its unit and
integration test processes with `0xc0000005` (`STATUS_ACCESS_VIOLATION`) during graphics tests;
it did not complete. These broader checks need a successful rerun before claiming full
validation. Native-speaker review also remains pending.
+11 -8
View File
@@ -1,6 +1,6 @@
# Localization parity
> **Last reviewed:** 2026-10-12 · **Last updated:** 2026-10-31 · **Change:** minor (Azerbaijani and Romanian UI catalogs; native review and Rust/offscreen verification pending; Swedish, Finnish, Danish and Norwegian Bokmål UI catalogs; previously minor: Arabic UI catalog) · **Target:** Adobe Photoshop 2026
> **Last reviewed:** 2026-10-12 · **Last updated:** 2026-10-31 · **Change:** minor (Azerbaijani and Romanian UI catalogs; native review pending; local build and focused checks verified; Swedish, Finnish, Danish and Norwegian Bokmål UI catalogs; previously minor: Arabic UI catalog) · **Target:** Adobe Photoshop 2026
Per-language status of PhotoCraft's UI. How catalogs work and how to add one:
[`localization.md`](localization.md). Language notes: [Korean](localization-ko.md), [Spanish](localization-es.md),
@@ -24,7 +24,7 @@ Vietnamese UI; Arabic and Hebrew users get English "Middle East" builds with the
composer, and its text engine handles RTL, Devanagari and Indic scripts.
**Summary.** 7 of the 12 key languages at 100% of measured keys (status `partial` because of the
engine messages), 2 absent (Hindi, Vietnamese), plus 8 other languages. Weighted by
engine messages), 2 absent (Hindi, Vietnamese), plus 17 other registered languages. Weighted by
speakers, ~55% ready. Remaining: 80–140 h, plus native-speaker review (recorded only for Italian,
2026-10-12).
@@ -47,11 +47,13 @@ speakers, ~55% ready. Remaining: 80–140 h, plus native-speaker review (recorde
## Other shipped languages
8 more, each at 1,608 / 1,608 measured keys, status `partial` for the same reason: Traditional
17 registered languages are outside the twelve-language table. The following eight have
1,608 / 1,608 measured keys, status `partial` for the same reason: Traditional
Chinese `zh-hant` (2,329 rows), Russian `ru` (4,227 keys; also every dynamic label the
other catalogs translate, [notes](localization-ru.md)), Ukrainian `uk` (3,375), Czech `cs` (3,522),
Polish `pl` (3,366), Greek `el` (3,481), Dutch `nl` (3,568), Italian `it` (4,164; also every dynamic label the
other catalogs translate; reviewed by a native speaker, [notes](localization-it.md)). Turkish `tr`
other catalogs translate; reviewed by a native speaker, [notes](localization-it.md)). Hungarian
`hu` (4,347 rows) is also registered. Turkish `tr`
(3,731 rows) also covers every measured key. Serbian `sr` (4,022 rows, Latin script, Ekavian, added 2026-10-12) covers every
measured key and the union of the other catalogs' dynamic labels; its one/few/many plurals reuse
the Russian rule. Swedish `sv` (4,552 rows, added 2026-10-28) covers every measured key and the
@@ -66,9 +68,10 @@ Azerbaijani `az` (Latin script) and Romanian `ro` were added 2026-10-31, bringin
registry to 29 languages including English. Each catalog has 4,566 entries, including the
existing dynamic-label key union and 32 plural messages. Romanian uses one/few/other integer
forms, including `20 de straturi`; Azerbaijani uses one/other. Both have complete menu keys,
regional locale matching and English fallback. Native-speaker review and Rust/offscreen
verification remain pending; this does not raise the estimated readiness percentage or close
G13. [Terminology, provenance and validation limits](localization-az-ro.md).
regional locale matching and English fallback. Native-speaker review remains pending. Local
build, six language tests, Clippy, wasm and CPU offscreen checks passed; broader-test limits
are documented in the language notes. This does not raise the estimated readiness percentage
or close G13. [Terminology, provenance and validation limits](localization-az-ro.md).
Czech UI follow-up (2026-10-11): status and notice wrappers, hardware labels, brush and
transform accessibility names, rasterization prompts, profile mismatch messages and preset
@@ -94,7 +97,7 @@ engine localization or native review is complete.
| Date | Change | Summary |
|---|---|---|
| 2026-10-31 | minor | Azerbaijani and Romanian UI catalogs, 4,566 entries each; regional tags and plural rules; native review and Rust/offscreen verification pending; readiness estimates unchanged |
| 2026-10-31 | minor | Azerbaijani and Romanian UI catalogs, 4,566 entries each; regional tags and plural rules; registry summary corrected to 17 languages outside the table, including Hungarian; native review pending; local build and focused checks verified; readiness estimates unchanged |
| 2026-10-10 | major | First version, measured from the catalogs with the `i18n-coverage` rules |
| 2026-10-10 | minor | Right-to-left shell layout (menu bar, title, options and status bars, toolbox and dock sides) |
| 2026-10-11 | minor | Czech dynamic status/notice and hardware text, render labels and Navigator zoom context; engine messages remain English |
+5 -4
View File
@@ -1,6 +1,6 @@
# PhotoCraft vs Adobe Photoshop: target-app parity
> **Last reviewed:** 2026-10-12 · **Last updated:** 2026-10-31 · **Change:** minor (Azerbaijani and Romanian UI catalogs; native review and Rust/offscreen verification pending; selected colour sets edit drawing, tone and supported filters; geometry remains open; Smooth and Feather command masks cropped to selection bounds plus blur reach; cropped selection morphology and command mask conversion performance evidence added; 12 of 178 preferences do nothing, from the scorecard; the Camera Raw row names per-camera colour for non-DNG cameras as missing, not the Calibration panel, which landed 2026-10-13; Content-Aware Scale measurements added, #5236; Help › Check for Updates and an opt-out check once per launch, DIST-220-1 partial, #5485; area type, TYPE-218-10 partial, Type scorecard 5 / 5 / 0; compound layer properties export as separate Photoshop Set events, #8304; JPEG Options dialog landed, FILE-215-19 partial; Print › Functions › Bleed through `file.print`; Content-Aware Move live preview for every selection size, TOOL-213-4 done, #6680; retouching evidence: Pattern Stamp and Background Eraser draw live, only the Mixer Brush is left of TOOL-213-7; fill and adjustment layers copy and paste whole, UI-217-23 partial, #2344; shape layers take Density and Feather, TOOL-214-12 done, #5846; on-canvas corner radius widgets, TOOL-214-12; `.atn` import maps 112 events; Free Transform H/V skew fields; stale rows corrected against `main` and the scorecard, estimates unchanged; Photoshop Actions `.atn` load and save; 2026-10-10: Tilt-Shift measurements added; earlier the same day: major, full re-measure against Photoshop 2026 27.11.0; merged `parity-estimate.md` and the roadmap's honest assessment; stale missing-tool rows corrected: Color Replacement and Red Eye are live toolbar tools, Frame landed; percentages unchanged; PSD spot plates in Photoshop's polarity, #7415 split; TIFF spot plates, FILE-215-17's TIFF part, #7415) · **Target:** Adobe Photoshop 2026
> **Last reviewed:** 2026-10-12 · **Last updated:** 2026-10-31 · **Change:** minor (Azerbaijani and Romanian UI catalogs; native review pending; local build and focused checks verified; selected colour sets edit drawing, tone and supported filters; geometry remains open; Smooth and Feather command masks cropped to selection bounds plus blur reach; cropped selection morphology and command mask conversion performance evidence added; 12 of 178 preferences do nothing, from the scorecard; the Camera Raw row names per-camera colour for non-DNG cameras as missing, not the Calibration panel, which landed 2026-10-13; Content-Aware Scale measurements added, #5236; Help › Check for Updates and an opt-out check once per launch, DIST-220-1 partial, #5485; area type, TYPE-218-10 partial, Type scorecard 5 / 5 / 0; compound layer properties export as separate Photoshop Set events, #8304; JPEG Options dialog landed, FILE-215-19 partial; Print › Functions › Bleed through `file.print`; Content-Aware Move live preview for every selection size, TOOL-213-4 done, #6680; retouching evidence: Pattern Stamp and Background Eraser draw live, only the Mixer Brush is left of TOOL-213-7; fill and adjustment layers copy and paste whole, UI-217-23 partial, #2344; shape layers take Density and Feather, TOOL-214-12 done, #5846; on-canvas corner radius widgets, TOOL-214-12; `.atn` import maps 112 events; Free Transform H/V skew fields; stale rows corrected against `main` and the scorecard, estimates unchanged; Photoshop Actions `.atn` load and save; 2026-10-10: Tilt-Shift measurements added; earlier the same day: major, full re-measure against Photoshop 2026 27.11.0; merged `parity-estimate.md` and the roadmap's honest assessment; stale missing-tool rows corrected: Color Replacement and Red Eye are live toolbar tools, Frame landed; percentages unchanged; PSD spot plates in Photoshop's polarity, #7415 split; TIFF spot plates, FILE-215-17's TIFF part, #7415) · **Target:** Adobe Photoshop 2026
The authoritative answer to "how close is PhotoCraft to Photoshop, and how much work is left". The
one-page summary is [`ROADMAP.md`](../ROADMAP.md); the ranked work list is [`gaps.md`](gaps.md);
@@ -584,14 +584,15 @@ See [method, raw measurements and reproduction](five-algorithm-performance.md).
Azerbaijani (az, Latin script) and Romanian (ro) UI catalogs were added 2026-10-31,
with 4,566 entries each and regional locale matching. Romanian has one/few/other integer
plurals. Native-speaker review and Rust/offscreen verification remain pending; readiness
estimates are unchanged. See [localization notes](localization-az-ro.md).
plurals. Native-speaker review remains pending. Local build and focused checks passed;
readiness estimates are unchanged. See [localization notes](localization-az-ro.md) for
the broader-test failures and verification limits.
## Revision history
| Date | Change | Summary |
|---|---|---|
| 2026-10-31 | minor | Azerbaijani and Romanian UI catalogs, 4,566 entries each; regional tags and plural rules; native review and Rust/offscreen verification pending; readiness estimates unchanged |
| 2026-10-31 | minor | Azerbaijani and Romanian UI catalogs, 4,566 entries each; regional tags and plural rules; native review pending; local build and focused checks verified; readiness estimates unchanged |
| 2026-10-27 | minor | Smooth/Feather command reads and replacement use selection bounds plus blur reach; full-canvas reference and release comparisons extended; percentages and scorecard budgets unchanged |
| 2026-10-26 | minor | Expand/Contract/Border distance work, mask reads and replacement cropped to nonzero bounds; bounded distances for radii ≤5; 36 MP exact-output comparisons improve 1.54–37.82× across eight cases; percentages, estimates and scorecard budgets unchanged |
| 2026-10-25 | minor | Selected colour channel sets: drawing, combined and per-component Levels/Curves, adjustments and supported filters; [scope, evidence and benchmarks](multi-channel-editing.md). Move/transform remains open; percentages unchanged |