diff --git a/crates/ui-egui/src/header.rs b/crates/ui-egui/src/header.rs index acbd2fdcb..c1272c41d 100644 --- a/crates/ui-egui/src/header.rs +++ b/crates/ui-egui/src/header.rs @@ -639,9 +639,15 @@ fn puppet_options(app: &mut EffectcraftApp, ui: &mut egui::Ui, p: &egui::Painter r.max.x + 16.0 } +/// A workspace's drawn name: built-ins read the menu bar's Window ▸ Workspace row; names the user +/// saved stay verbatim, even when one matches a catalog source such as "Composition". +fn workspace_label(name: &str) -> &str { + if crate::dock::WORKSPACES.contains(&name) { crate::i18n::command_label("window.workspace", name) } else { name } +} + fn ws_menu(app: &mut EffectcraftApp, ui: &mut egui::Ui) { for w in app.workspace_names() { - if ui.selectable_label(app.ui.workspace == w, crate::i18n::command_label("window.workspace", &w)).clicked() { + if ui.selectable_label(app.ui.workspace == w, workspace_label(&w)).clicked() { app.set_workspace(&w); ui.close(); } @@ -692,6 +698,15 @@ mod tests { out.textures_delta.clear(); } + #[test] + fn saved_workspace_names_stay_verbatim() { + crate::i18n::set_current("zh-hans"); + assert_ne!(workspace_label("Default"), "Default"); + assert_ne!(crate::i18n::tr("Composition"), "Composition"); + assert_eq!(workspace_label("Composition"), "Composition"); + crate::i18n::set_current("en"); + } + #[test] fn long_press_type_keeps_the_tool_until_vertical_is_selected() { let mut app = EffectcraftApp::new(effectcraft_engine::Session::default()); diff --git a/crates/ui-egui/src/i18n.rs b/crates/ui-egui/src/i18n.rs index cb3de6e51..ab046881c 100644 --- a/crates/ui-egui/src/i18n.rs +++ b/crates/ui-egui/src/i18n.rs @@ -188,6 +188,14 @@ pub(crate) fn command_label<'a>(command: &str, source: &'a str) -> &'a str { row(source).or_else(|| row(dotted.as_deref()?)).unwrap_or_else(|| tr(source)) } +/// A Settings page's title as the menu bar's Settings submenu draws it, without the ellipsis; the +/// panel catalog's row for pages that have no menu row. The panel catalog's "Type" is the kind +/// (Camera Settings, the Project panel's column), while the Type page is about text. +pub(crate) fn settings_page_title(title: &str) -> &str { + let menu = menu_catalog(ui::current()).and_then(|c| c.iter().find(|(id, en, _)| *id == "app.settings" && en.strip_suffix("...") == Some(title))); + menu.and_then(|(_, _, translated)| translated.strip_suffix("...")).unwrap_or_else(|| tr(title)) +} + /// `source` looked up in `catalog` by (command, English label); the source itself when the pair is /// absent, so computed labels and user names stay verbatim. fn lookup<'a>(catalog: &[(&str, &str, &'a str)], command: &str, source: &'a str) -> &'a str { @@ -7354,6 +7362,16 @@ mod tests { assert_eq!(command_label("window.panel", "Project"), "Project"); } + #[test] + fn settings_page_titles_read_the_menu_row() { + set_current("zh-hans"); + assert_eq!(settings_page_title("Type"), "文字"); + assert_eq!(tr("Type"), "类型"); + assert_eq!(settings_page_title("Roto Brush"), tr("Roto Brush")); + set_current("en"); + assert_eq!(settings_page_title("Type"), "Type"); + } + #[test] fn match_system_takes_the_first_browser_language_with_a_catalog() { let tags = |t: &[&str]| t.iter().map(|s| s.to_string()).collect::>(); diff --git a/crates/ui-egui/src/panels/settings.rs b/crates/ui-egui/src/panels/settings.rs index 28a7c0142..6954e1377 100644 --- a/crates/ui-egui/src/panels/settings.rs +++ b/crates/ui-egui/src/panels/settings.rs @@ -677,7 +677,7 @@ pub fn show(app: &mut EffectcraftApp, ctx: &egui::Context, t: &Tokens) { ui.painter().text( r.left_center() + vec2(10.0, 0.0), egui::Align2::LEFT_CENTER, - tr(p.title), + crate::i18n::settings_page_title(p.title), Tokens::ui(12.5), if sel { Color32::WHITE } else { t.text }, ); @@ -694,7 +694,7 @@ pub fn show(app: &mut EffectcraftApp, ctx: &egui::Context, t: &Tokens) { // dialog scrolled sideways a little (#284). ui.set_width(ui.available_width()); let p = &all[idx]; - ui.label(RichText::new(tr(p.title)).font(Tokens::semibold(14.0)).color(t.tab_text_active)); + ui.label(RichText::new(crate::i18n::settings_page_title(p.title)).font(Tokens::semibold(14.0)).color(t.tab_text_active)); ui.add_space(6.0); egui::ScrollArea::vertical().max_height((body_h - 30.0).max(0.0)).auto_shrink([false, false]).show(ui, |ui| { page_ui(app, ui, p, &cur, t, &mut acts);