diff --git a/crates/ui-egui/src/theme.rs b/crates/ui-egui/src/theme.rs index 3eaaca4d1..04b2f90ea 100644 --- a/crates/ui-egui/src/theme.rs +++ b/crates/ui-egui/src/theme.rs @@ -531,6 +531,7 @@ fn fallback_faces(han: HanOrder) -> Vec<(&'static str, Vec<(String, u32)>)> { second, ("sys-cjk-hangul", cjk_hangul()), ("sys-thai", thai()), + ("sys-lao", lao()), ("sys-hebrew", hebrew()), ("sys-symbols", symbols()), ("sys-symbols-2", symbols_more()), @@ -659,6 +660,26 @@ fn thai() -> Vec<(String, u32)> { v } +/// Lao faces. Windows ships Leelawadee UI (and DokChampa on older versions); macOS has Lao Sangam +/// MN and Lao MN; Linux usually has Noto Sans Lao or Phetsarath OT. +#[cfg(not(target_arch = "wasm32"))] +fn lao() -> Vec<(String, u32)> { + let mac_sup = "/System/Library/Fonts/Supplemental"; + let win = std::env::var("WINDIR").map(|w| format!("{w}\\Fonts")).unwrap_or_else(|_| "C:\\Windows\\Fonts".into()); + let lin = ["/usr/share/fonts/truetype/noto", "/usr/share/fonts/opentype/noto", "/usr/share/fonts/truetype", "/usr/share/fonts"]; + let mut v: Vec<(String, u32)> = Vec::new(); + v.push((format!("{win}\\LeelawUI.ttf"), 0)); // Leelawadee UI + v.push((format!("{win}\\dokchamp.ttf"), 0)); // DokChampa + v.push((format!("{mac_sup}/Lao Sangam MN.ttf"), 0)); + v.push((format!("{mac_sup}/Lao MN.ttc"), 0)); + for d in lin { + v.push((format!("{d}/NotoSansLao-Regular.ttf"), 0)); + v.push((format!("{d}/lao/Phetsarath_OT.ttf"), 0)); + v.push((format!("{d}/Phetsarath_OT.ttf"), 0)); + } + v +} + /// Hebrew faces. Windows has David and FrankRuehl (and Tahoma/Courier New carry Hebrew); macOS has /// Arial Hebrew and David; Linux usually has Noto Sans Hebrew or DejaVu Sans. #[cfg(not(target_arch = "wasm32"))] @@ -886,11 +907,11 @@ mod tests { let keys = |han| fallback_faces(han).into_iter().map(|(k, _)| k).collect::>(); assert_eq!( keys(HanOrder::Japanese), - ["sys-cjk-han-ja", "sys-cjk-han-zh", "sys-cjk-hangul", "sys-thai", "sys-hebrew", "sys-symbols", "sys-symbols-2"] + ["sys-cjk-han-ja", "sys-cjk-han-zh", "sys-cjk-hangul", "sys-thai", "sys-lao", "sys-hebrew", "sys-symbols", "sys-symbols-2"] ); assert_eq!( keys(HanOrder::Chinese), - ["sys-cjk-han-zh", "sys-cjk-han-ja", "sys-cjk-hangul", "sys-thai", "sys-hebrew", "sys-symbols", "sys-symbols-2"] + ["sys-cjk-han-zh", "sys-cjk-han-ja", "sys-cjk-hangul", "sys-thai", "sys-lao", "sys-hebrew", "sys-symbols", "sys-symbols-2"] ); assert_eq!(HanOrder::of(Language::Ja), HanOrder::Japanese); for l in [Language::En, Language::Zh, Language::Ko, Language::Ru, Language::PtBr, Language::De, Language::Cs] { @@ -946,11 +967,12 @@ 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); 7] = [ + let cases: [(&str, Vec<(String, u32)>, &str); 8] = [ ("sys-cjk-han-ja", cjk_han_japanese(), "カテゴリ"), ("sys-cjk-han-zh", cjk_han_simplified(), "页面布局 客户端配置"), ("sys-cjk-hangul", cjk_hangul(), "한글"), ("sys-thai", thai(), "ทดสอบ"), + ("sys-lao", lao(), "ພາສາລາວ"), ("sys-hebrew", hebrew(), "עברית"), ("ui", candidates(UI), "Русский"), // Czech interface labels: every Czech accented letter, in both cases. diff --git a/docs/localization-parity.md b/docs/localization-parity.md index d143d100f..5c4769dd7 100644 --- a/docs/localization-parity.md +++ b/docs/localization-parity.md @@ -1,6 +1,6 @@ # Localization parity -> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-19 · **Change:** minor (defined-name length limit counts characters, so long Arabic names are accepted; Table names are limited to 255 characters; right-to-left sheets in `.xls` files open right-to-left; text boxes and shapes keep right-to-left paragraph direction through XLSX save; Save as Web Page and copied HTML keep right-to-left; CJK fallback probes Flatpak host font mounts; French and Serbian `context|label` translations no longer show the context) · **Target:** Microsoft Excel (Microsoft 365), Excel for Mac 16.113.4 +> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-19 · **Change:** minor (defined-name length limit counts characters, so long Arabic names are accepted; Table names are limited to 255 characters; right-to-left sheets in `.xls` files open right-to-left; text boxes and shapes keep right-to-left paragraph direction through XLSX save; Save as Web Page and copied HTML keep right-to-left; CJK fallback probes Flatpak host font mounts; Lao system-font fallback; French and Serbian `context|label` translations no longer show the context) · **Target:** Microsoft Excel (Microsoft 365), Excel for Mac 16.113.4 Per-language status against Excel, which ships its UI in dozens of languages (Windows language packs cover 100+), with localized function names, argument separators, number and date formats, @@ -29,7 +29,8 @@ right-to-left sheets and full complex-script support. Part of #142 is still open pending confirmation). Native CJK fallback also probes Flatpak's read-only `/run/host/fonts`, `/run/host/local-fonts` and `/run/host/user-fonts` layouts, so installed Noto CJK and WenQuanYi faces can render Chinese without a broad filesystem grant. This does - not change the installed-font catalogue or add bundled fonts. There is no complex-text shaping: Arabic and + not change the installed-font catalogue or add bundled fonts. Lao falls back to Lao Sangam MN / Lao MN (macOS), + Leelawadee UI / DokChampa (Windows) or Noto Sans Lao / Phetsarath OT (Linux). There is no complex-text shaping: Arabic and Devanagari don't join or reorder, and there is no bidirectional layout. **Sheet Right-to-Left** (`view.rightToLeft`, Page Layout › Sheet Options, XLSX `rightToLeft`, `.xls` WINDOW2 fRightToLeft) mirrors the grid (#146): column A and the row headers on the right, the vertical scrollbar on the left; hit-testing, @@ -92,6 +93,7 @@ language (none so far) and of localized function names. | 2026-10-19 | trivial | Text boxes and shapes keep right-to-left paragraph direction (`a:pPr rtl`) on XLSX save, so Excel-authored Arabic and Hebrew text boxes reopen right to left | | 2026-10-19 | minor | Save as Web Page and copied HTML mark right-to-left sheets `dir="rtl"`, let General-aligned Arabic and Hebrew text align by its own direction (`dir="auto"`), and keep numbers on right-to-left sheets left to right and on the left | | 2026-10-19 | minor | French and Serbian kept the context in three `context\|label` translations ("Options\|Général", "Opcije\|Opšte" for `Options\|General`; also `Options\|Save`, `Sheet Options\|View`). `tr` shows a found translation as it is, so File › Options headings and the Sheet Options "View" checkboxes showed the prefix. Fixed; a test checks that no catalog shows a `\|` | +| 2026-10-17 | minor | Lao text falls back to an installed Lao face (`sys-lao`) instead of tofu boxes | | 2026-10-14 | minor | CJK fallback probes the read-only Flatpak host font mounts with the existing distribution layouts and TTC locale indices; no new sandbox permissions or bundled fonts | | 2026-10-12 | minor | Format Cells looks up its tabs, labels, options and note through `Language::tr` (Fill tab keyed `Format Cells\|Fill`); dialog titles and OK/Cancel too. Labels already in a table (Number, Currency, Fill…) show translated; the rest fall back to English until the tables add them | | 2026-10-12 | minor | Brazilian Portuguese catalog (`i18n/pt.rs`) grows from 377 to 923 entries: every key the other catalogs translate, including the dialog strings #669 starts looking up (~42%) |