i18n (cs): Effect > Pathfinder > Add reads "Sjednotit", keyed by the effect id

The key "Add" is shared by Effect > Pathfinder > Add (PathfinderOp::Unite),
the File Info button and a label in the raster effects dialog. One plain row
cannot fit all three: "Přidat" is right for the button, but the Pathfinder
effect unites shapes, so it reads "Sjednotit".

- cs.tsv: `@id pathfinder.add` = "Sjednotit"; the plain "Add" row stays
  "Přidat".
- menus.rs: Effect menu items all run effect.apply / effect.dialog, so the
  command id cannot tell them apart. effect_item_label() looks the effect's
  own id up first (an @id row), and "Last Effect: {name}" does the same.
- appearance.rs: the Appearance panel's effect labels use the same lookup.
- i18n/tests.rs: an @id row may now name an effect id as well as a command
  id; czech_reads_as_czech pins Add and pathfinder.add.

No other catalog has an @id row, so their behaviour is unchanged.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Losminek 2026-10-11 17:35:52 +02:00 committed by bflatastic
parent 5b9af8103a
commit 660fe22de8
4 changed files with 28 additions and 6 deletions

View File

@ -370,6 +370,7 @@
Zig Zag… Cikcak…
Pathfinder Operace s cestami
Add Přidat
@id pathfinder.add Sjednotit
Intersect Protnout
Exclude Vyloučit
Subtract Odečíst

Can't render this file because it contains an unexpected character in line 2 and column 73.

View File

@ -161,8 +161,11 @@ fn bundled_catalogs_are_consistent() {
assert_eq!(src.ends_with('…'), tr.ends_with('…'), "{}: ellipsis mismatch: {src:?}", l.code);
}
if ctx == "@id" {
let known =
crate::menus::UI_COMMANDS.iter().any(|c| c.0 == src) || vectorcraft_engine::cmd::command_specs().iter().any(|c| c.id == src);
// A command id, or an effect id: Effect menu items share `effect.apply` /
// `effect.dialog`, so the effect's own id is what tells them apart.
let known = crate::menus::UI_COMMANDS.iter().any(|c| c.0 == src)
|| vectorcraft_engine::cmd::command_specs().iter().any(|c| c.id == src)
|| vectorcraft_effects::effect_catalog().iter().any(|e| e.id == src);
assert!(known, "{}: unknown command id {src:?}", l.code);
}
}
@ -839,6 +842,10 @@ fn czech_reads_as_czech() {
assert_eq!(trn(cs(), n, "{n} Layer", "{n} Layers"), format!("{n} {word}"));
}
assert_eq!(tr_ctx(cs(), "axis", "Both"), "Obě");
// "Add" is Unite in Effect › Pathfinder (an `@id` row for the effect id); "Přidat" elsewhere.
assert_eq!(tr(cs(), "Add"), "Přidat");
assert_eq!(tr_id(cs(), "pathfinder.add", "Add"), "Sjednotit");
assert_eq!(tr_id(cs(), "pathfinder.intersect", "Intersect"), "Protnout");
let nested = "command `object.group` is not available right now: nothing selected";
assert_eq!(message(cs(), nested), "příkaz `object.group` nyní není k dispozici: nic není vybráno");
}

View File

@ -1650,7 +1650,7 @@ pub fn display_label(app: &VectorcraftApp, id: &str, label: &str) -> String {
"effect.last" => match &app.last_effect {
Some((e, _)) => {
let name = vectorcraft_effects::effect_info(e).map(|i| i.label).unwrap_or(e.as_str());
fmt(tl!("Last Effect: {name}"), &[("name", tl!(name))])
fmt(tl!("Last Effect: {name}"), &[("name", crate::i18n::tr_id(lang, e, name))])
}
None => crate::i18n::tr_id(lang, id, label).to_string(),
},
@ -1661,6 +1661,19 @@ pub fn display_label(app: &VectorcraftApp, id: &str, label: &str) -> String {
}
}
/// The label of an Effect menu item in the UI language, by the effect's own id. Every effect item
/// runs `effect.apply` or `effect.dialog`, so the command id can't tell them apart; an `@id` row
/// for the effect id (for example `pathfinder.add`) wins over the plain row of the English label.
/// `None` when the catalog has no such row, and the plain translation applies.
fn effect_item_label(id: &str, p: &Value) -> Option<String> {
if !matches!(id, "effect.apply" | "effect.dialog") {
return None;
}
let effect = p.get("effect")?.as_str()?;
let shown = crate::i18n::tr_id(crate::i18n::current(), effect, "");
(!shown.is_empty()).then(|| shown.to_string())
}
/// Menu slots that are left out while they have nothing to show (unused saved views, recent files,
/// User Defined swatch and graphic style libraries).
fn hidden_when_disabled(id: &str) -> bool {
@ -1793,7 +1806,7 @@ pub fn entry<'a>(app: &VectorcraftApp, it: &'a Item) -> Option<Entry<'a>> {
Entry::Item(Row {
command: Some((id, p)),
source: label,
label: display_label(app, id, label).into(),
label: effect_item_label(id, p).unwrap_or_else(|| display_label(app, id, label)).into(),
shortcut: item_shortcut(id, p),
enabled,
checked,

View File

@ -160,10 +160,11 @@ fn built_in_effect(id: &str) -> bool {
catalog().iter().any(|c| c.0 == id)
}
/// [`effect_label`] as shown: a built-in effect's in the UI language, a plug-in's as it is.
/// [`effect_label`] as shown: a built-in effect's in the UI language (an `@id` row for the
/// effect's id wins over the plain row of its English label), a plug-in's as it is.
fn shown_effect_label(id: &str) -> String {
match catalog().iter().find(|c| c.0 == id) {
Some(c) => tl!(&c.1).to_string(),
Some(c) => crate::i18n::t_id(id, &c.1).to_string(),
None => effect_label(id),
}
}