From 4a1323ad072b3b9f7206b61836bc4b13dc2b9248 Mon Sep 17 00:00:00 2001 From: dotCooCoo Date: Thu, 15 Oct 2026 11:13:00 -0700 Subject: [PATCH] i18n: Russian Isolate and Sublayer rows use Cyrillic letters only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Russian catalog's Isolate row began with a Latin "A" (U+0041), "Aизолировать", and the Create New Sublayer and New Sublayer… rows spelled "подслой" with a Latin "c" (U+0063). The rows now read "Изолировать", "Создать новый подслой" and "Новый подслой…". A new test fails when a word in any catalog's translation holds letters from more than one of the Latin, Cyrillic and Greek scripts. --- crates/ui-egui/src/i18n/ru.tsv | 6 +++--- crates/ui-egui/src/i18n/tests.rs | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 3 deletions(-) diff --git a/crates/ui-egui/src/i18n/ru.tsv b/crates/ui-egui/src/i18n/ru.tsv index 68150d69a..b1eba501c 100644 --- a/crates/ui-egui/src/i18n/ru.tsv +++ b/crates/ui-egui/src/i18n/ru.tsv @@ -614,7 +614,7 @@ Create Gradient Mesh… Создать градиентную сетку… Create Graph Создать диаграмму Create New Layer Создать новый слой - Create New Sublayer Создать новый подcлой + Create New Sublayer Создать новый подслой Create New Swatch… Создать новый образец… Create New {kind} Style Создать новый стиль {kind} Create Object Mosaic… Создать мозаику объектов… @@ -1370,7 +1370,7 @@ Invert Инвертировать Invert Colors Инвертировать цвета Invert Mask Инвертировать маску - Isolate Aизолировать + Isolate Изолировать Isolate Blending Изолировать наложение Isolate Group Изолировать группу Italian Итальянский @@ -1792,7 +1792,7 @@ New PDF Preset Новый набор PDF New Print Preset Новый набор печати New Scatter Brush from Selection Новая кисть-распыление из выделенного - New Sublayer… Новый подcлой… + New Sublayer… Новый подслой… New Swatch Новый образец New Swatch… Новый образец… New Symbol Новый символ diff --git a/crates/ui-egui/src/i18n/tests.rs b/crates/ui-egui/src/i18n/tests.rs index fc8faae99..7a1b9d197 100644 --- a/crates/ui-egui/src/i18n/tests.rs +++ b/crates/ui-egui/src/i18n/tests.rs @@ -373,6 +373,32 @@ fn zh_hans_is_simplified_and_mainland() { assert!(bad.is_empty(), "in zh-hans.tsv:\n{}", bad.join("\n")); } +/// No translated word mixes Latin, Cyrillic and Greek letters, such as a Latin "A" typed in place +/// of a Cyrillic "А". A word written in one script, such as "PDF" or "X" in a Russian row, is +/// allowed. +#[test] +fn no_translated_word_mixes_latin_cyrillic_and_greek_letters() { + let script = |c: char| match c as u32 { + 0x41..=0x5A | 0x61..=0x7A | 0xC0..=0x24F | 0x1E00..=0x1EFF => Some("Latin"), + 0x370..=0x3FF | 0x1F00..=0x1FFF => Some("Greek"), + 0x400..=0x52F => Some("Cyrillic"), + _ => None, + }; + let mut bad = Vec::new(); + for l in LANGUAGES.iter().filter(|l| !l.source.is_empty()) { + let (entries, _) = parse_entries(l.source); + for (ctx, src, tr) in entries { + for word in tr.split(|c: char| !c.is_alphabetic()) { + let scripts: std::collections::BTreeSet<_> = word.chars().filter_map(script).collect(); + if scripts.len() > 1 { + bad.push(format!("{}: {ctx} {src:?} → {tr:?} has {word:?} ({scripts:?})", l.code)); + } + } + } + } + assert!(bad.is_empty(), "words that mix scripts:\n{}", bad.join("\n")); +} + /// Every menu string (top-level titles, submenu names, item labels, section headers, UI and /// engine command labels and menu paths) has an entry in each language that claims complete menus. #[test]