From 35d70f5531d219603f8623a3f98803e6672f49ff Mon Sep 17 00:00:00 2001 From: dotCooCoo Date: Sat, 17 Oct 2026 10:01:45 -0700 Subject: [PATCH 1/2] =?UTF-8?q?i18n:=20Edit=20=E2=80=BA=20Undo=20and=20Red?= =?UTF-8?q?o=20name=20the=20step=20as=20the=20History=20panel=20does?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Edit › Undo and Edit › Redo translated the step's name with its plain catalog row only. Nine of the 22 catalogs have no plain row for Feather, only the effect's menu row with an ellipsis, so in Japanese Edit › Undo read "Featherを取り消す" after Feather while the History panel listed the step as ぼかし. The menu now names the step with panels::history::step_name, as the History panel does, and keeps the name as recorded when the catalog has no row for it. The in-window and native menus both show the new label. Docs: docs/target-app-parity.md. --- crates/ui-egui/src/menus.rs | 31 +++++++++++++++++++++++++++++-- docs/target-app-parity.md | 1 + 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/crates/ui-egui/src/menus.rs b/crates/ui-egui/src/menus.rs index 747b7b12a..88759a2b4 100644 --- a/crates/ui-egui/src/menus.rs +++ b/crates/ui-egui/src/menus.rs @@ -1906,9 +1906,11 @@ pub fn display_label(app: &VectorcraftApp, id: &str, label: &str) -> String { match id { "edit.undo" | "edit.redo" => { let last = app.session.active().and_then(|d| if id == "edit.undo" { d.history.undo.last() } else { d.history.redo.last() }); + // The step's name as the History panel lists it. + let name = |label: &str| crate::panels::history::step_name(lang, label).unwrap_or_else(|| label.to_string()); match last { - Some(h) if id == "edit.undo" => fmt(tl!("Undo {name}"), &[("name", tl!(&h.label))]), - Some(h) => fmt(tl!("Redo {name}"), &[("name", tl!(&h.label))]), + Some(h) if id == "edit.undo" => fmt(tl!("Undo {name}"), &[("name", &name(&h.label))]), + Some(h) => fmt(tl!("Redo {name}"), &[("name", &name(&h.label))]), None => tl!(if id == "edit.undo" { "Undo" } else { "Redo" }).to_string(), } } @@ -4176,6 +4178,31 @@ mod tests { } } + /// Edit › Undo and Edit › Redo name the step in the UI language as the History panel lists it + /// (`panels::history::step_name`), including a step named after an effect whose catalog holds + /// only the effect's menu row with an ellipsis, as Japanese does for Feather. + #[test] + fn undo_and_redo_name_the_step_as_the_history_panel_does() { + let ja = crate::i18n::Lang::from_code("ja").expect("ja registered"); + crate::i18n::set_current(ja); + let mut app = app_with_a_rectangle(); + app.run("effect.apply", json!({"effect": "stylize.feather"})).unwrap(); + assert_eq!(app.session.active().unwrap().history.undo.last().map(|h| h.label.as_str()), Some("Feather")); + let shown = |app: &VectorcraftApp, id: &'static str| { + let item = c(if id == "edit.undo" { "Undo" } else { "Redo" }, id); + match entry(app, &item) { + Some(Entry::Item(row)) => row.label.to_string(), + _ => panic!("{id} is not a menu item"), + } + }; + assert_eq!(shown(&app, "edit.undo"), "ぼかしを取り消す"); + app.run("edit.undo", json!({})).unwrap(); + assert_eq!(shown(&app, "edit.redo"), "ぼかしをやり直す"); + assert_eq!(shown(&app, "edit.undo"), "長方形を取り消す", "a step with a plain row"); + crate::i18n::set_current(crate::i18n::Lang::EN); + assert_eq!(shown(&app, "edit.redo"), "Redo Feather"); + } + /// Type › Optical Margin Alignment runs `type.opticalMarginAlignment`, needs a selection, and /// is checked while the selected type has it on. Its check, and Type Orientation's, read the /// type inside a selected group too. diff --git a/docs/target-app-parity.md b/docs/target-app-parity.md index bc5110ff5..60f8ef1dd 100644 --- a/docs/target-app-parity.md +++ b/docs/target-app-parity.md @@ -459,6 +459,7 @@ Moved from the ROADMAP's "Shipped so far" on 2026-10-10. Update it when a featur - The dock's double arrow collapses Properties, Layers and Libraries to icons at the top of the icon column, popping out like the other icon panels, and expands them again (`window.collapseDock`, kept with the preferences and in saved workspaces). The icon column's own arrow (expanding the icon panels into a full column) is not done. - Czech render-site labels: desktop/web file filters, diagnostics, suggested preset names and contributor tooltips/plurals now use catalog lookups; gradients have Czech adjective agreement and printer marks have a separate context (PDF/Print and Summary). Search, Home, toolbar/panel tooltips and Preferences already look up their labels. Every complete catalog has rows for these labels and for the Roman and Japanese printer mark styles. Evidence: `i18n::tests::czech_render_site_follow_up`, `i18n::tests::complete_catalogs_translate_render_site_labels`, `dialogs::tests_modal::printer_mark_labels_are_distinct_from_language_names`; see [localization-parity.md](localization-parity.md). - Localised UI: menus (in-window and native), panels, dialogs, toolbar and Preferences read from per-language catalogs (`crates/ui-egui/src/i18n`, see `docs/development.md`); Traditional Chinese (Taiwan), Simplified Chinese (mainland), Japanese, Korean, Vietnamese, German, Spanish, French, Italian, Polish, Brazilian Portuguese, Russian and Ukrainian ship complete, and Czech covers every menu label (and more), with system-locale detection on macOS, Windows, Linux and the web (the browser's languages, or `?lang=`), a Language preference and, on macOS, a VectorCraft ▸ Language menu. Names are never translated (fonts and their styles, layers, artboards, saved presets, user libraries, custom workspaces, recent files, plug-ins). + - Edit › Undo and Edit › Redo, in the in-window and native menus, name the step in the interface language as the History panel lists it (`panels::history::step_name`), so when the catalog has no plain row for a step named after an effect, such as Feather, the menu shows the translation of the effect's menu row without its ellipsis (`undo_and_redo_name_the_step_as_the_history_panel_does`). - The History panel translates the undo step names the engine, the tools and the shell write as literals: each has a row in every complete catalog (`every_undo_label_is_translated`), and a step whose catalog row exists only with an ellipsis (such as an effect's menu name) shows that row without the ellipsis. - The History panel menu has Step Backward and Step Forward, which run Edit › Undo and Edit › Redo and are disabled when there is no step to undo or redo, and Set History Limit…, which opens Preferences at Performance, where History States is set. Not done: Clear History and a new document from the selected state. - Native macOS menu bar, vector tool cursors, a ⌘K command palette, middle-button panning with any tool. Native menus explicitly end tracking on command selection, outside window presses and Escape; menu updates wait until tracking ends, and a dismissing press never starts a canvas gesture (M14.8). From 015bab68a1a4e6d31d094abba7aec9ae005e1c9b Mon Sep 17 00:00:00 2001 From: bflatastic Date: Sun, 18 Oct 2026 01:24:26 +0700 Subject: [PATCH 2/2] Undo/Redo: the menu names the step with the History panel's own function --- crates/ui-egui/src/menus.rs | 2 +- crates/ui-egui/src/panels/history.rs | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/crates/ui-egui/src/menus.rs b/crates/ui-egui/src/menus.rs index 88759a2b4..f89f53537 100644 --- a/crates/ui-egui/src/menus.rs +++ b/crates/ui-egui/src/menus.rs @@ -1907,7 +1907,7 @@ pub fn display_label(app: &VectorcraftApp, id: &str, label: &str) -> String { "edit.undo" | "edit.redo" => { let last = app.session.active().and_then(|d| if id == "edit.undo" { d.history.undo.last() } else { d.history.redo.last() }); // The step's name as the History panel lists it. - let name = |label: &str| crate::panels::history::step_name(lang, label).unwrap_or_else(|| label.to_string()); + let name = crate::panels::history::shown; match last { Some(h) if id == "edit.undo" => fmt(tl!("Undo {name}"), &[("name", &name(&h.label))]), Some(h) => fmt(tl!("Redo {name}"), &[("name", &name(&h.label))]), diff --git a/crates/ui-egui/src/panels/history.rs b/crates/ui-egui/src/panels/history.rs index 13ca7fab3..adc1d6f44 100644 --- a/crates/ui-egui/src/panels/history.rs +++ b/crates/ui-egui/src/panels/history.rs @@ -24,8 +24,9 @@ pub fn step_name(lang: crate::i18n::Lang, label: &str) -> Option { has(lang, &dotted).then(|| tr(lang, &dotted).trim_end_matches('…').to_string()) } -/// A step's name as the panel lists it: in the UI language, else as recorded. -fn shown(label: &str) -> String { +/// A step's name as the panel lists it: in the UI language, else as recorded. Edit › Undo and Redo +/// name the step the same way. +pub(crate) fn shown(label: &str) -> String { step_name(crate::i18n::current(), label).unwrap_or_else(|| label.to_string()) }