mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-26 02:37:01 -06:00
Menus: leave installed plug-ins' names out of the strings to translate
menu_strings() lists the strings a complete language catalog has to cover, and it leaves out names that are user data: fonts, recent files, saved views and libraries. An installed plug-in's name stayed in. Plug-ins are installed for the whole process, and a test that installs one before complete_languages_translate_every_menu_string runs made that test fail with the plug-in's name as an untranslated menu string. lists_plugin() tells an Object › Plug-ins filter or an Effect › Plug-ins effect by its command and params. Those are part of the menu item itself and stay right while another test installs or removes plug-ins. menu_strings() uses it, and so does menu_catalogs_translate_every_menu_label in place of its own copy of the rule. plugins_are_listed_in_the_object_and_effect_menus checks it. Before the change it failed with "Desaturate… is a menu string to translate". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01HhvnnnD5fTFupK8WWq35un
This commit is contained in:
committed by
bflatastic
co-authored by
Claude Opus 5.5
parent
df1bf3fe32
commit
dbb6b470b3
@@ -954,8 +954,11 @@ fn menu_catalogs_translate_every_menu_label() {
|
||||
let language_name = |l: &str| Lang::all().any(|lang| lang.name() == l);
|
||||
// Font names and sizes, and installed plug-ins' own names, are not interface text.
|
||||
let interface = |(label, id, p): &(&str, &str, serde_json::Value)| {
|
||||
let plugin = *id == "plugin.dialog" || p.get("effect").and_then(serde_json::Value::as_str).is_some_and(|e| e.starts_with("plugin."));
|
||||
*id != "text.setStyle" && !plugin && shown.contains(*label) && !MENU_KEEP_AS_IS.contains(label) && !language_name(label)
|
||||
*id != "text.setStyle"
|
||||
&& !crate::menus::lists_plugin(id, p)
|
||||
&& shown.contains(*label)
|
||||
&& !MENU_KEEP_AS_IS.contains(label)
|
||||
&& !language_name(label)
|
||||
};
|
||||
let mut all: Vec<String> = labels.iter().filter(|l| interface(l)).map(|(l, ..)| l.to_string()).collect();
|
||||
all.extend(toggled_labels());
|
||||
|
||||
@@ -1917,6 +1917,13 @@ fn shows_a_name(id: &str, label: &str) -> bool {
|
||||
|| (matches!(id, "effect.apply" | "effect.dialog") && vectorcraft_effects::plugin_effects().iter().any(|e| e.label == label))
|
||||
}
|
||||
|
||||
/// Does the menu item `id` with `params` list an installed plug-in (an Object › Plug-ins filter or
|
||||
/// an Effect › Plug-ins effect), by the plug-in's own name? Told by the item itself, so it holds
|
||||
/// while another thread installs or removes plug-ins.
|
||||
pub(crate) fn lists_plugin(id: &str, params: &Value) -> bool {
|
||||
id == "plugin.dialog" || params.get("effect").and_then(Value::as_str).and_then(vectorcraft_plugins::effect::plugin_id).is_some()
|
||||
}
|
||||
|
||||
/// The label of a menu item as drawn: [`dynamic_label`] in the UI language. Labels assembled
|
||||
/// around a name (Undo *Move*, Reset *Essentials*, Last Effect: *Drop Shadow*) are translated as
|
||||
/// templates so the name can move; names that are user data (files, views, fonts, custom
|
||||
@@ -3952,17 +3959,17 @@ pub const DYNAMIC_LABELS: &[&str] = &[
|
||||
|
||||
/// Every English string the menus, the command palette, the panel registry, the toolbar and the
|
||||
/// Preferences dialog can show: what a complete language catalog has to cover. Names that are user
|
||||
/// data (fonts, recent files, saved views, libraries), the point sizes and the view angles are
|
||||
/// left out.
|
||||
/// data (fonts, recent files, saved views, libraries, installed plug-ins), the point sizes and the
|
||||
/// view angles are left out.
|
||||
pub fn menu_strings() -> std::collections::BTreeSet<String> {
|
||||
use std::collections::BTreeSet;
|
||||
fn user_data(id: &str) -> bool {
|
||||
hidden_when_disabled(id) || id.starts_with("type.recentFont")
|
||||
fn user_data(id: &str, params: &Value) -> bool {
|
||||
hidden_when_disabled(id) || id.starts_with("type.recentFont") || lists_plugin(id, params)
|
||||
}
|
||||
fn walk(items: &[Item], under: &str, out: &mut BTreeSet<String>) {
|
||||
for it in items {
|
||||
match it {
|
||||
Item::Cmd(l, id, _) => {
|
||||
Item::Cmd(l, id, params) => {
|
||||
let size = l.strip_suffix(" pt").is_some_and(|n| n.chars().all(|c| c.is_ascii_digit()));
|
||||
// View › Rotate View lists angles: an optional minus sign, digits and a degree sign.
|
||||
let angle = l
|
||||
@@ -3971,7 +3978,7 @@ pub fn menu_strings() -> std::collections::BTreeSet<String> {
|
||||
.is_some_and(|n| !n.is_empty() && n.chars().all(|c| c.is_ascii_digit()));
|
||||
// VectorCraft › Language lists each language by its own name.
|
||||
let language_name = *id == "app.language" && crate::i18n::Lang::all().any(|lang| lang.name() == *l);
|
||||
if !user_data(id) && !size && !angle && !language_name && *l != "—" {
|
||||
if !user_data(id, params) && !size && !angle && !language_name && *l != "—" {
|
||||
out.insert(l.to_string());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -58,6 +58,12 @@ fn plugins_are_listed_in_the_object_and_effect_menus() {
|
||||
assert_eq!((fx.command.as_deref(), &fx.params), (Some("effect.dialog"), &json!({"effect": "plugin.test.ui.echo"})));
|
||||
// Menu clicks on items with params don't turn into the generic parameter dialog.
|
||||
assert_eq!(menus::click_target("Desaturate…", "plugin.dialog", &filter.params).0, "plugin.dialog");
|
||||
// Their names are the plug-ins' own, not interface text a language catalog has to cover (they
|
||||
// are installed for the whole test run, while the catalog tests run).
|
||||
let strings = menus::menu_strings();
|
||||
for name in ["Desaturate…", "Test test.ui.echo…"] {
|
||||
assert!(!strings.contains(name), "{name} is a menu string to translate");
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in New Issue
Block a user