i18n: cover Czech in the interface-language tests

- The catalog-completeness test requires a non-empty Czech label for
  every key of the reference (Japanese) table.
- Czech context keys: `Page Layout|Orientation` and `Orientation` get
  different labels; unknown text such as `Sheet1!A1` passes through.
- `cs-CZ` / `cs_CZ.UTF-8` system tags and `parse("cs")` resolve to Czech.
- The ribbon renders after switching to Czech, and the choice persists
  in UiState.
- Czech keeps canonical formula entry (`=SUM(1.5,2.25)`), and `=SUMA(1;2)`
  is not accepted.
- The UI font draws every Czech accented letter, upper and lower case,
  without tofu; Czech shares the default Han font order.

Czech spells "Data" as English does, so the Czech checks probe
"Formulas" -> "Vzorce", where an English fallback would be caught.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Losminek
2026-10-11 13:36:33 +02:00
co-authored by Claude Opus 5.5
parent c8ce333a74
commit f44b31e154
4 changed files with 37 additions and 2 deletions
+10
View File
@@ -440,6 +440,7 @@ mod tests {
assert!(ko::translate(english).is_some_and(|text| !text.is_empty()), "missing Korean: {english}");
assert!(ru::translate(english).is_some_and(|text| !text.is_empty()), "missing Russian: {english}");
assert!(pt::translate(english).is_some_and(|text| !text.is_empty()), "missing Portuguese: {english}");
assert!(cs::translate(english).is_some_and(|text| !text.is_empty()), "missing Czech: {english}");
}
assert_eq!(Language::Ja.tr("Data"), "データ");
assert_eq!(Language::Zh.tr("Data"), "数据");
@@ -452,10 +453,16 @@ mod tests {
assert_eq!(Language::Zh.tr("Sheet1!A1"), "Sheet1!A1");
assert_eq!(Language::Ko.tr("Sheet1!A1"), "Sheet1!A1");
assert_eq!(Language::Ru.tr("Sheet1!A1"), "Sheet1!A1");
// Czech "Data" is spelled as in English, so probe it with a label that differs.
assert_eq!(Language::Cs.tr("Data"), "Data");
assert_eq!(Language::Cs.tr("Formulas"), "Vzorce");
assert_eq!(Language::Cs.tr("Sheet1!A1"), "Sheet1!A1");
// A `context|label` key shows only its label in English and splits the translation.
assert_eq!(Language::En.tr("Page Layout|Orientation"), "Orientation");
assert_eq!(Language::Ja.tr("Page Layout|Orientation"), "印刷の向き");
assert_eq!(Language::Ja.tr("Orientation"), "方向");
assert_eq!(Language::Cs.tr("Page Layout|Orientation"), "Orientace");
assert_eq!(Language::Cs.tr("Orientation"), "Orientace textu");
assert_eq!(Language::parse("xx"), None);
}
@@ -486,6 +493,9 @@ mod tests {
assert_eq!(Language::from_tag("pt-BR"), Some(Language::PtBr));
assert_eq!(Language::parse("pt"), Some(Language::PtBr));
assert_eq!(Language::parse("pt-br"), Some(Language::PtBr));
assert_eq!(Language::from_tag("cs-CZ"), Some(Language::Cs));
assert_eq!(Language::from_tag("cs_CZ.UTF-8"), Some(Language::Cs));
assert_eq!(Language::parse("cs"), Some(Language::Cs));
}
#[test]
+4 -2
View File
@@ -587,7 +587,7 @@ mod tests {
assert_eq!(keys(HanOrder::Japanese), ["sys-cjk-han-ja", "sys-cjk-han-zh", "sys-cjk-hangul", "sys-thai", "sys-hebrew"]);
assert_eq!(keys(HanOrder::Chinese), ["sys-cjk-han-zh", "sys-cjk-han-ja", "sys-cjk-hangul", "sys-thai", "sys-hebrew"]);
assert_eq!(HanOrder::of(Language::Ja), HanOrder::Japanese);
for l in [Language::En, Language::Zh, Language::Ko, Language::Ru, Language::PtBr] {
for l in [Language::En, Language::Zh, Language::Ko, Language::Ru, Language::PtBr, Language::Cs] {
assert_eq!(HanOrder::of(l), HanOrder::Chinese, "{l:?} shares the default order (no font rebuild)");
}
}
@@ -613,13 +613,15 @@ mod tests {
// Real render check, per script: the proportional family (what cells and the UI use) must
// resolve a sample string to a real glyph, not the tofu replacement char. Skips a script
// whose face is absent (a minimal machine) and fails if a face is present but not wired in.
let cases: [(&str, Vec<(String, u32)>, &str); 6] = [
let cases: [(&str, Vec<(String, u32)>, &str); 7] = [
("sys-cjk-han-ja", cjk_han_japanese(), "カテゴリ"),
("sys-cjk-han-zh", cjk_han_simplified(), "页面布局 客户端配置"),
("sys-cjk-hangul", cjk_hangul(), "한글"),
("sys-thai", thai(), "ทดสอบ"),
("sys-hebrew", hebrew(), "עברית"),
("ui", candidates(UI), "Русский"),
// Czech interface labels: every Czech accented letter, in both cases.
("ui", candidates(UI), "Příliš žluťoučký kůň úpěl ďábelské ódy ŘŠČŽÝÁÍÉÚŮĚŤĎŇÓ"),
];
for language in [Language::En, Language::Ja] {
let ctx = egui::Context::default();
+16
View File
@@ -185,3 +185,19 @@ fn portuguese_interface_retains_its_canonical_formula_fallback() {
assert_eq!(restored.language, Language::PtBr);
assert_eq!(Language::Es.tr("Page Layout|Orientation"), "Orientation");
}
#[test]
fn czech_interface_retains_its_canonical_formula_fallback() {
// The Czech table translates interface labels only: formulas keep canonical English names,
// `,` separators and `.` decimals until a Czech formula locale exists.
let mut app = app();
app.run("app.language.set", json!({"code":"cs-CZ"})).unwrap();
assert_eq!(app.ui.language, Language::Cs);
assert_eq!(app.ui.language.tr("Formulas"), "Vzorce");
assert!(enter(&mut app, "=SUM(1.5,2.25)"));
app.begin_edit(None, true);
assert_eq!(app.editor.as_ref().unwrap().text, "=SUM(1.5,2.25)");
assert!(!enter(&mut app, "=SUMA(1;2)"));
let restored: UiState = serde_json::from_str(&serde_json::to_string(&app.ui).unwrap()).unwrap();
assert_eq!(restored.language, Language::Cs);
}
+7
View File
@@ -209,6 +209,13 @@ fn language_switch_translates_the_ribbon_and_persists() {
let restored: gridcraft_ui_egui::UiState = serde_json::from_str(&serde_json::to_string(&h.state().ui).unwrap()).unwrap();
assert_eq!(restored.language, language);
}
// Czech spells "Data" as English does, so the Czech table is checked on a label that differs.
h.state_mut().run("app.language.set", json!({"language": "cs"})).unwrap();
h.run_steps(2);
assert_eq!(h.state().ui.language, Language::Cs);
assert_eq!(Language::Cs.tr("Formulas"), "Vzorce");
let restored: gridcraft_ui_egui::UiState = serde_json::from_str(&serde_json::to_string(&h.state().ui).unwrap()).unwrap();
assert_eq!(restored.language, Language::Cs);
h.state_mut().run("app.language.set", json!({"language": "en"})).unwrap();
assert_eq!(h.state().ui.language, Language::En);
}