From c9013e08c7752a12c14f228e2d45ebf452c96a5b Mon Sep 17 00:00:00 2001 From: aiongg Date: Wed, 21 Oct 2026 06:06:36 +0000 Subject: [PATCH] i18n: Hani and yue-Hant pick Han forms by region; usual scripts for kk, ky, tg, ku, ms, ug --- crates/i18n/src/lib.rs | 9 ++++++--- crates/i18n/src/scripts.rs | 15 +++++++++++---- 2 files changed, 17 insertions(+), 7 deletions(-) diff --git a/crates/i18n/src/lib.rs b/crates/i18n/src/lib.rs index 6c841d1e4..db13b6db1 100644 --- a/crates/i18n/src/lib.rs +++ b/crates/i18n/src/lib.rs @@ -358,10 +358,10 @@ fn marked(text: &str) -> String { // ponytail: the multi-script languages a Craft app could plausibly ship; add a row with the locale. fn usual_script(language: &str) -> Option<&'static str> { Some(match language { - "be" | "mn" | "sr" => "cyrl", + "be" | "kk" | "ky" | "mn" | "sr" | "tg" => "cyrl", "zh" => "hans", - "az" | "bs" | "ha" | "uz" => "latn", - "ks" | "sd" => "arab", + "az" | "bs" | "ha" | "ku" | "ms" | "uz" => "latn", + "ks" | "sd" | "ug" => "arab", "pa" => "guru", _ => return None, }) @@ -600,6 +600,9 @@ mod tests { assert_eq!(candidates("pa-Guru-PK"), ["pa-guru-pk", "pa-guru", "pa"]); assert_eq!(candidates("zh-US"), ["zh-us", "zh-hant", "zh"]); assert_eq!(candidates("zh-SG"), ["zh-sg", "zh-hans", "zh"]); + assert_eq!(candidates("kk-CN"), ["kk-cn", "kk-arab-cn", "kk-arab"]); + assert_eq!(candidates("kk-KZ"), ["kk-kz", "kk"]); + assert_eq!(candidates("ug-KZ"), ["ug-kz", "ug-cyrl-kz", "ug-cyrl"]); } #[test] diff --git a/crates/i18n/src/scripts.rs b/crates/i18n/src/scripts.rs index 56a1ba1fc..ebe324f54 100644 --- a/crates/i18n/src/scripts.rs +++ b/crates/i18n/src/scripts.rs @@ -163,18 +163,21 @@ pub fn direction(tag: &str) -> Direction { /// The forms a language tag's Han characters take: `zh-CN`, `zh-SG`, `zh-Hans` and plain `zh` → /// Simplified; `zh-TW`, `zh-Hant` and the other regions CLDR writes in Traditional characters -/// (`zh-US`, `zh-AU`) → Traditional; `zh-HK`, `zh-MO` and `zh-Hant-HK` → HongKong; `ja` → +/// (`zh-US`, `zh-AU`) → Traditional; `zh-HK`, `zh-MO`, `zh-Hant-HK` and `yue` → HongKong; `ja` → /// Japanese; `ko` → Korean. `None` for a language not written with Han, which leaves the choice /// to the font stack. pub fn han(tag: &str) -> Option { let tag = Subtags::parse(tag); let hong_kong = matches!(tag.region.as_deref(), Some("hk" | "mo")); - let script = tag.script.as_deref().or_else(|| region_script(&tag.language, tag.region.as_deref()?)); + // `Hani` names Han without saying which forms, so the region still decides. + let script = tag.script.as_deref().filter(|s| *s != "hani"); + let script = script.or_else(|| region_script(&tag.language, tag.region.as_deref()?)); match (tag.language.as_str(), script) { ("ja", _) => Some(Han::Japanese), ("ko", _) => Some(Han::Korean), ("zh" | "yue" | "wuu", Some("hans")) => Some(Han::Simplified), - ("zh" | "yue" | "wuu", Some("hant")) => Some(if hong_kong { Han::HongKong } else { Han::Traditional }), + ("yue", Some("hant")) => Some(if tag.region.as_deref() == Some("tw") { Han::Traditional } else { Han::HongKong }), + ("zh" | "wuu", Some("hant")) => Some(if hong_kong { Han::HongKong } else { Han::Traditional }), // Cantonese is written in Traditional characters with Hong Kong forms unless it says otherwise. ("yue", _) => Some(Han::HongKong), ("zh" | "wuu", _) => Some(Han::Simplified), @@ -348,6 +351,10 @@ mod tests { ("yue-HK", Han::HongKong), ("zh-Hans-SG", Han::Simplified), ("yue", Han::HongKong), + ("yue-Hant", Han::HongKong), + ("yue-Hant-TW", Han::Traditional), + ("zh-Hani-HK", Han::HongKong), + ("zh-Hani", Han::Simplified), ("yue-Hans", Han::Simplified), ("ja-JP", Han::Japanese), ("ko_KR.UTF-8", Han::Korean), @@ -414,7 +421,7 @@ mod tests { /// The usual scripts tag matching relies on agree with the table. #[test] fn agrees_with_usual_script() { - for language in ["be", "mn", "sr", "zh", "az", "bs", "ha", "uz", "ks", "sd", "pa"] { + for language in ["be", "kk", "ky", "mn", "sr", "tg", "zh", "az", "bs", "ha", "ku", "ms", "uz", "ks", "sd", "ug", "pa"] { let usual = crate::usual_script(language).and_then(subtag_scripts); assert_eq!(usual, Some(scripts(language)), "{language}"); }