Add German (de) interface language

New catalog crates/ui-egui/src/i18n/de.rs (266 entries) mirroring the ru.rs
key set exactly; original translations written from the meaning of the
English UI strings, MIT OR Apache-2.0.

- Language::De registered (code de, name Deutsch); de/de-DE/de_AT/de-CH
  resolve via from_tag
- Tests: German coverage in the i18n coverage loop, de/de-AT/de-CH locale
  tags, ribbon round-trip case, default CJK font-order assertion
- Docs: localization-parity.md row, ROADMAP.md languages section

cargo test -p gridcraft-ui-egui i18n: 5 passed; --lib: 21 passed;
interaction + formula_locale: 13 + 8 passed.
This commit is contained in:
arekown 2026-10-11 10:57:27 +02:00
parent 9f896c1249
commit a44cc8540d
7 changed files with 307 additions and 18 deletions

View File

@ -62,7 +62,7 @@ collaboration, mobile, AI).
| File formats | ~50% | 80–120 | [file-format-parity.md](docs/file-format-parity.md) |
| Performance | ~35% | 35–55 | [target-app-parity.md](docs/target-app-parity.md#performance) |
| Stability | ~60% | 15–25 | [gaps.md](docs/gaps.md) |
| Localization | ~10% (ribbon in 5 languages) | 100–165 | [localization-parity.md](docs/localization-parity.md) |
| Localization | ~10% (ribbon in 6 languages) | 100–165 | [localization-parity.md](docs/localization-parity.md) |
| Hardware (multi-core calc, GPU, pen, multi-window) | ~40% | 25–40 | [hardware-parity.md](docs/hardware-parity.md) |
| Platforms | ~80% (no iOS/Android; ahead on Linux, BSD, RISC-V) | 30–60 | [target-app-parity.md](docs/target-app-parity.md#platforms) |
| Ecosystem / add-ins | ~10% (VBA out of scope; own scripts, MCP, CLI) | 25–40 | [target-app-parity.md](docs/target-app-parity.md#ecosystem-and-ai) |
@ -89,11 +89,12 @@ collaboration, mobile, AI).
## Languages
The ribbon is translated into Japanese, Simplified Chinese, Korean, Brazilian Portuguese and
Russian (266–268 labels each, ~12% of ~2,200 strings; merged 10-10 in #31, #104, #82), the
The ribbon is translated into Japanese, Simplified Chinese, Korean, Brazilian Portuguese, Russian
and German (266–268 labels each, ~12% of ~2,200 strings; merged 10-10 in #31, #104, #82, German
added 10-11), the
interface follows the system language, and CJK, Thai and Hebrew text falls back to system fonts
(#38). Dialogs, menus and messages are English; formulas and number formats are en-US only. German
is in PR #163. Detail: [localization-parity.md](docs/localization-parity.md).
(#38). Dialogs, menus and messages are English; formulas and number formats are en-US only.
Localized German formulas and numbers are in PR #163. Detail: [localization-parity.md](docs/localization-parity.md).
| Language | Code | Status | UI strings |
|---|---|---|---|
@ -106,11 +107,11 @@ is in PR #163. Detail: [localization-parity.md](docs/localization-parity.md).
| Portuguese | pt-BR | menus only | ~12% |
| Indonesian | id | none | 0% |
| Japanese | ja | menus only | ~12% |
| German | de | none (PR #163 open) | 0% |
| German | de | menus only | ~12% |
| Korean | ko | menus only | ~12% |
| Vietnamese | vi | none | 0% |
Other shipped languages: 1 (Russian, menus only, ~12%).
Other shipped languages: 2 (Russian and German, menus only, ~12%).
## Upcoming
@ -131,6 +132,7 @@ Ranked; estimates in Opus 5.5 agent-hours. Detail and the full beta-gate list in
| Date | What landed |
|---|---|
| 2026-10-11 | Ribbon translated into German (266 labels; `de`, `de-DE`, `de-AT`, `de-CH` locale tags resolve to German) |
| 2026-10-10 | Ribbon translated into Japanese, Chinese, Korean, Brazilian Portuguese and Russian with system-language default (#31, #104, #82); CJK/Thai/Hebrew font fallback (#38); clear messages for encrypted and `.xls` files (#17); smooth line charts (#62). Progress docs restructured to the craftrules standard; full re-measure (this page). Initial ribbon key tips (#43), in-place text box editing (#84), copy as HTML table (#36). ODS and XLSB data import (#100, #101); recalc linear in the number of range formulas (#66); RISC-V Linux build; Flatpak repository on Pages; web cell-commit trap fixed |
| 2026-10-09 | Community fixes: spill range operator `A1#`, sheet-scoped names, protection refuses locked-cell edits, Insert/Delete Cells adjust references, `DATE(1900,2,29)`, SUMIF sizing, `ROUND` at 15 digits, `_xlpm.` LAMBDA parameters in XLSX, vertical scrollbar, system appearance, border previews; v0.4.0 |
| 2026-10-08 | v0.2.0 and v0.3.0 releases; Flatpak, AppImage zsync, branded DMG; desktop log file; DirectX 12 default on Windows |

View File

@ -174,7 +174,7 @@ pub fn handle(app: &mut SheetApp, ctx: &egui::Context, method: &str, p: &Json) -
("view.theme", "Display Theme", ""),
("view.zoom100", "100%", ""),
("ui.dialog", "Open Dialog", ""),
("app.language.set", "Interface Language", "{language: \"en\"|\"zh\"|\"ja\"|\"ko\"|\"ru\"|\"pt\"} (alias: code)"),
("app.language.set", "Interface Language", "{language: \"en\"|\"zh\"|\"ja\"|\"ko\"|\"ru\"|\"pt\"|\"de\"} (alias: code)"),
("app.language.english", "Interface Language: English", ""),
("app.language.japanese", "Interface Language: Japanese", ""),
] {

View File

@ -9,6 +9,7 @@
use serde::{Deserialize, Serialize};
mod de;
mod ko;
mod pt;
mod ru;
@ -26,10 +27,11 @@ pub enum Language {
Ru,
#[serde(rename = "pt")]
PtBr,
De,
}
impl Language {
pub const ALL: [Self; 7] = [Self::En, Self::Es, Self::Zh, Self::Ja, Self::Ko, Self::Ru, Self::PtBr];
pub const ALL: [Self; 8] = [Self::En, Self::Es, Self::Zh, Self::Ja, Self::Ko, Self::Ru, Self::PtBr, Self::De];
/// The language's own name, shown in the switcher.
pub fn name(self) -> &'static str {
@ -41,6 +43,7 @@ impl Language {
Self::Ko => "한국어",
Self::Ru => "Русский",
Self::PtBr => "Português (Brasil)",
Self::De => "Deutsch",
}
}
@ -54,6 +57,7 @@ impl Language {
Self::Ko => "ko",
Self::Ru => "ru",
Self::PtBr => "pt",
Self::De => "de",
}
}
@ -70,6 +74,7 @@ impl Language {
"ko" => Some(Self::Ko),
"ru" => Some(Self::Ru),
"pt" => Some(Self::PtBr),
"de" => Some(Self::De),
_ => None,
}
}
@ -103,6 +108,7 @@ impl Language {
Self::Ko => ko::translate(text),
Self::Ru => ru::translate(text),
Self::PtBr => pt::translate(text),
Self::De => de::translate(text),
};
translated.unwrap_or_else(|| text.rsplit_once('|').map_or(text, |(_, label)| label))
}
@ -434,12 +440,15 @@ 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!(de::translate(english).is_some_and(|text| !text.is_empty()), "missing German: {english}");
}
assert_eq!(Language::Ja.tr("Data"), "データ");
assert_eq!(Language::Zh.tr("Data"), "数据");
assert_eq!(Language::Ko.tr("Data"), "데이터");
assert_eq!(Language::Ru.tr("Data"), "Данные");
assert_eq!(Language::PtBr.tr("Data"), "Dados");
assert_eq!(Language::De.tr("Data"), "Daten");
assert_eq!(Language::De.tr("Sheet1!A1"), "Sheet1!A1");
assert_eq!(Language::PtBr.tr("Date"), "Data");
assert_eq!(Language::PtBr.tr("Sheet1!A1"), "Sheet1!A1");
assert_eq!(Language::Ja.tr("Sheet1!A1"), "Sheet1!A1");
@ -476,7 +485,9 @@ mod tests {
assert_eq!(Language::from_tag("zh-Hans-CN"), Some(Language::Zh));
assert_eq!(Language::from_tag("ko-KR"), Some(Language::Ko));
assert_eq!(Language::from_tag("RU_ru"), Some(Language::Ru));
assert_eq!(Language::from_tag("de-DE"), None);
assert_eq!(Language::from_tag("de-DE"), Some(Language::De));
assert_eq!(Language::from_tag("de_AT"), Some(Language::De));
assert_eq!(Language::from_tag("de-CH"), Some(Language::De));
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));

View File

@ -0,0 +1,274 @@
//! German translations for the interface strings in i18n.rs. Labels follow the wording German
//! spreadsheet users know; anything absent falls back to English.
pub(super) fn translate(text: &str) -> Option<&'static str> {
Some(match text {
"Paste" => "Einfügen",
"Paste Values" => "Werte einfügen",
"Paste Formulas" => "Formeln einfügen",
"Paste Formatting" => "Formatierung einfügen",
"Transpose" => "Transponieren",
"Paste Link" => "Verknüpfung einfügen",
"Paste Special…" => "Inhalte einfügen…",
"Cut (⌘X)" => "Ausschneiden (⌘X)",
"Copy (⌘C)" => "Kopieren (⌘C)",
"Format Painter (double-click to keep it on)" => "Format übertragen (Doppelklick zum Beibehalten)",
"Bold (⌘B)" => "Fett (⌘B)",
"Italic (⌘I)" => "Kursiv (⌘I)",
"Underline (⌘U)" => "Unterstrichen (⌘U)",
"Double Underline" => "Doppelt unterstrichen",
"Strikethrough" => "Durchgestrichen",
"Underline" => "Unterstrichen",
"Increase Font Size" => "Schriftgrad vergrößern",
"Decrease Font Size" => "Schriftgrad verkleinern",
"Wrap Text" => "Zeilenumbruch",
"Merge & Center" => "Verbinden und zentrieren",
"Merge Cells" => "Zellen verbinden",
"Merge Across" => "Zeilenweise verbinden",
"Unmerge Cells" => "Zellverbindung aufheben",
"Fill Color" => "Füllfarbe",
"Font Color" => "Schriftfarbe",
"Borders" => "Rahmen",
"Top\nAlign" => "Oben\nausrichten",
"Middle\nAlign" => "Vertikal\nzentrieren",
"Bottom\nAlign" => "Unten\nausrichten",
"Left" => "Links",
"Right" => "Rechts",
"Center" => "Zentriert",
"Horizontal" => "Horizontal",
"Vertical Text" => "Vertikaler Text",
"Decrease Indent" => "Einzug verkleinern",
"Increase Indent" => "Einzug vergrößern",
"Orientation" => "Ausrichtung",
"Angle Counterclockwise" => "Gegen den Uhrzeigersinn neigen",
"Angle Clockwise" => "Im Uhrzeigersinn neigen",
"Rotate Text Up" => "Text nach oben drehen",
"Rotate Text Down" => "Text nach unten drehen",
"Accounting Number Format" => "Buchhaltungszahlenformat",
"Percent Style" => "Prozentformat",
"Comma Style" => "Kommaformat",
"Increase Decimal" => "Dezimalstelle hinzufügen",
"Decrease Decimal" => "Dezimalstelle entfernen",
"More Accounting Formats…" => "Weitere Buchhaltungsformate…",
"Conditional\nFormatting" => "Bedingte\nFormatierung",
"Conditional Formatting" => "Bedingte Formatierung",
"Format\nas Table" => "Als Tabelle\nformatieren",
"Cell\nStyles" => "Zell-\nformate",
"Format Cells…" => "Zellen formatieren…",
"Format Cell Alignment…" => "Zellausrichtung…",
"Format\nPane" => "Format-\nbereich",
"Format" => "Format",
"Insert" => "Einfügen",
"Insert Cells…" => "Zellen einfügen…",
"Delete" => "Löschen",
"Delete Cells…" => "Zellen löschen…",
"Insert Sheet Rows" => "Blattzeilen einfügen",
"Insert Sheet Columns" => "Blattspalten einfügen",
"Delete Sheet Rows" => "Blattzeilen löschen",
"Delete Sheet Columns" => "Blattspalten löschen",
"Row Height…" => "Zeilenhöhe…",
"AutoFit Row Height" => "Zeilenhöhe automatisch anpassen",
"Column Width…" => "Spaltenbreite…",
"AutoFit Column Width" => "Spaltenbreite automatisch anpassen",
"Default Width…" => "Standardbreite…",
"Hide Rows" => "Zeilen ausblenden",
"Unhide Rows" => "Zeilen einblenden",
"Hide Columns" => "Spalten ausblenden",
"Unhide Columns" => "Spalten einblenden",
"Lock Cell" => "Zelle sperren",
"Clear" => "Löschen",
"Clear All" => "Alles löschen",
"Clear Formats" => "Formate löschen",
"Clear Contents" => "Inhalte löschen",
"Clear Comments and Notes" => "Kommentare und Notizen löschen",
"Clear Hyperlinks" => "Hyperlinks löschen",
"AutoSum" => "AutoSumme",
"AutoSum (⌘⇧T)" => "AutoSumme (⌘⇧T)",
"Flash\nFill" => "Blitz-\nvorschau",
"Flash Fill" => "Blitzvorschau",
"Fill" => "Ausfüllen",
"Clear Print Area" => "Druckbereich aufheben",
"Find &\nSelect" => "Suchen und\nAuswählen",
"Find…" => "Suchen…",
"Replace…" => "Ersetzen…",
"Go To…" => "Gehe zu…",
"Go To Special…" => "Inhalte auswählen…",
"PivotTable" => "PivotTable",
"Recommended\nCharts" => "Empfohlene\nDiagramme",
"Table" => "Tabelle",
"Pictures" => "Bilder",
"Shapes" => "Formen",
"Icons" => "Symbole",
"Text\nBox" => "Text-\nfeld",
"Comment" => "Kommentar",
"New\nComment" => "Neuer\nKommentar",
"New Note" => "Neue Notiz",
"Show/Hide Note" => "Notiz anzeigen/ausblenden",
"Header &\nFooter" => "Kopf- und\nFußzeile",
"Text to\nColumns" => "Text in\nSpalten",
"Link" => "Link",
"Symbol" => "Symbol",
"Sparklines" => "Sparklines",
"Header & Footer" => "Kopf- und Fußzeile",
"Draw with ink" => "Mit Freihand zeichnen",
"Eraser" => "Radierer",
"Ink to\nShape" => "Freihand in\nForm umwandeln",
"Select\nObjects" => "Objekte\nauswählen",
"Themes" => "Designs",
"Margins" => "Seitenränder",
"Size" => "Größe",
"Print\nArea" => "Druck-\nbereich",
"Set Print Area" => "Druckbereich festlegen",
"Breaks" => "Umbrüche",
"Insert Page Break" => "Seitenumbruch einfügen",
"Remove Page Break" => "Seitenumbruch entfernen",
"Reset All Page Breaks" => "Alle Seitenumbrüche zurücksetzen",
"Print\nTitles" => "Druck-\ntitel",
"Narrow" => "Schmal",
"Wide" => "Breit",
"Normal" => "Normal",
"Portrait" => "Hochformat",
"Landscape" => "Querformat",
"Custom Margins…" => "Benutzerdefinierte Seitenränder…",
"Insert\nFunction" => "Funktion\neinfügen",
"Name\nManager" => "Namens-\nmanager",
"Define Name" => "Namen definieren",
"Use in Formula" => "In Formel verwenden",
"Create from Selection" => "Aus Auswahl erstellen",
"Trace Precedents" => "Spur zum Vorgänger",
"Trace Dependents" => "Spur zum Nachfolger",
"Remove Arrows" => "Pfeile entfernen",
"Show Formulas" => "Formeln anzeigen",
"Error Checking" => "Fehlerüberprüfung",
"Evaluate Formula" => "Formel auswerten",
"Watch Window" => "Überwachungsfenster",
"Calculation\nOptions" => "Berechnungs-\noptionen",
"Calculate Now" => "Jetzt berechnen",
"Calculate Sheet" => "Blatt berechnen",
"Automatic" => "Automatisch",
"Automatic Except for Data Tables" => "Automatisch, außer für Datentabellen",
"Manual" => "Manuell",
"Sort &\nFilter" => "Sortieren und\nFiltern",
"Sort" => "Sortieren",
"Sort A to Z" => "Von A bis Z sortieren",
"Sort Z to A" => "Von Z bis A sortieren",
"Custom Sort…" => "Benutzerdefiniertes Sortieren…",
"Filter" => "Filtern",
"Reapply" => "Erneut anwenden",
"Get Data\n(Text/CSV)" => "Daten abrufen\n(Text/CSV)",
"Remove\nDuplicates" => "Duplikate\nentfernen",
"Data\nValidation" => "Daten-\nüberprüfung",
"Data Validation" => "Datenüberprüfung",
"Data Validation…" => "Datenüberprüfung…",
"Circle Invalid Data" => "Ungültige Daten einkreisen",
"Clear Validation" => "Datenüberprüfung löschen",
"Group" => "Gruppieren",
"Ungroup" => "Gruppierung aufheben",
"Subtotal" => "Teilergebnis",
"What-If\nAnalysis" => "Was-wäre-wenn-\nAnalyse",
"Data Table…" => "Datentabelle…",
"Scenario Manager…" => "Szenario-Manager…",
"Goal Seek…" => "Zielwertsuche…",
"Spelling" => "Rechtschreibung",
"Check\nAccessibility" => "Barrierefreiheit\nprüfen",
"Threaded Comments" => "Threadkommentare",
"Show\nComments" => "Kommentare\nanzeigen",
"Protect\nWorkbook" => "Arbeitsmappe\nschützen",
"Unprotect\nSheet" => "Blattschutz\naufheben",
"Protect Sheet…" => "Blatt schützen…",
"Comments" => "Kommentare",
"Notes" => "Notizen",
"Page Break\nPreview" => "Seitenumbruch-\nvorschau",
"Page\nLayout" => "Seiten-\nlayout",
"Formula Bar" => "Formelleiste",
"Gridlines" => "Gitternetzlinien",
"Headings" => "Überschriften",
"Zoom" => "Zoom",
"100%" => "100%",
"Zoom to\nSelection" => "Zoom auf die\nAuswahl",
"Freeze\nPanes" => "Fenster\nfixieren",
"Freeze Panes" => "Fenster fixieren",
"Freeze Top Row" => "Oberste Zeile fixieren",
"Freeze First Column" => "Erste Spalte fixieren",
"Unfreeze Panes" => "Fixierung aufheben",
"Dark Mode" => "Dunkler Modus",
"Interface language" => "Anzeigesprache",
"Command\nPalette" => "Befehls-\npalette",
"Agent\nControl" => "Agenten-\nsteuerung",
"Action\nJournal" => "Aktions-\nprotokoll",
"About\nGridCraft" => "Über\nGridCraft",
"Share" => "Teilen",
"Add Chart\nElement" => "Diagrammelement\nhinzufügen",
"Change\nChart Type" => "Diagrammtyp\nändern",
"Switch\nRow/Column" => "Zeile/Spalte\nwechseln",
"Data Labels: None" => "Datenbeschriftungen: Keine",
"Data Labels: Show" => "Datenbeschriftungen: Anzeigen",
"Legend: None" => "Legende: Keine",
"Legend: Bottom" => "Legende: Unten",
"Legend: Top" => "Legende: Oben",
"Legend: Right" => "Legende: Rechts",
"Gridlines: None" => "Gitternetzlinien: Keine",
"Gridlines: Show" => "Gitternetzlinien: Anzeigen",
"Chart\nTitle" => "Diagramm-\ntitel",
"Delete\nChart" => "Diagramm\nlöschen",
"Convert\nto Range" => "In Bereich\nkonvertieren",
"Table\nStyles" => "Tabellen-\nformate",
"Top 10 Items" => "Obere 10 Elemente",
"Top 10%" => "Obere 10 %",
"Bottom 10 Items" => "Untere 10 Elemente",
"Bottom 10%" => "Untere 10 %",
"Above Average" => "Überdurchschnittlich",
"Below Average" => "Unterdurchschnittlich",
"Clear Rules from Entire Sheet" => "Regeln im gesamten Blatt löschen",
"Clear Rules from Selected Cells" => "Regeln in den ausgewählten Zellen löschen",
"Constants" => "Konstanten",
"Data Bars" => "Datenbalken",
"Color Scales" => "Farbskalen",
"Icon Sets" => "Symbolsätze",
"Home" => "Start",
"Draw" => "Zeichnen",
"Page Layout" => "Seitenlayout",
"Formulas" => "Formeln",
"Data" => "Daten",
"Review" => "Überprüfen",
"View" => "Ansicht",
"Automate" => "Automatisieren",
"Table Design" => "Tabellenentwurf",
"Chart Design" => "Diagrammentwurf",
"Ready" => "Bereit",
"Enter" => "Eingeben",
"Edit" => "Bearbeiten",
"Point" => "Zeigen",
"Calculate" => "Berechnen",
"Select destination and press Enter or choose Paste" => "Ziel auswählen und die Eingabetaste drücken oder „Einfügen“ wählen",
"General" => "Standard",
"Number" => "Zahl",
"Currency" => "Währung",
"Accounting" => "Buchhaltung",
"Date" => "Datum",
"Time" => "Uhrzeit",
"Percentage" => "Prozentsatz",
"Fraction" => "Bruch",
"Scientific" => "Wissenschaftlich",
"Text" => "Text",
"Special" => "Sonderformat",
"Custom" => "Benutzerdefiniert",
"Short Date" => "Kurzes Datum",
"Long Date" => "Langes Datum",
"More Number Formats…" => "Weitere Zahlenformate…",
"Financial" => "Finanzmathematik",
"Logical" => "Logisch",
"Date &\nTime" => "Datum &\nUhrzeit",
"Lookup &\nReference" => "Nachschlagen &\nVerweisen",
"Math &\nTrig" => "Mathematik &\nTrigonometrie",
"More\nFunctions" => "Weitere\nFunktionen",
"Page Layout|Orientation" => "Seitenausrichtung",
"Display theme" => "Anzeigedesign",
"System" => "System",
"Light" => "Hell",
"Dark" => "Dunkel",
"Sheet Options|View" => "Anzeige",
"Print" => "Drucken",
_ => return None,
})
}

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::De] {
assert_eq!(HanOrder::of(l), HanOrder::Chinese, "{l:?} shares the default order (no font rebuild)");
}
}

View File

@ -200,7 +200,7 @@ fn language_switch_translates_the_ribbon_and_persists() {
assert!(ids.contains(&id), "engine.commands lists {id}");
}
for (language, expected) in
[(Language::Zh, "数据"), (Language::Ja, "データ"), (Language::Ko, "데이터"), (Language::Ru, "Данные"), (Language::PtBr, "Dados")]
[(Language::Zh, "数据"), (Language::Ja, "データ"), (Language::Ko, "데이터"), (Language::Ru, "Данные"), (Language::PtBr, "Dados"), (Language::De, "Daten")]
{
h.state_mut().run("app.language.set", json!({"language": language.code()})).unwrap();
h.run_steps(2); // every locale renders the ribbon without panicking

View File

@ -1,6 +1,6 @@
# Localization parity
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-10 · **Change:** minor (re-measured after the 10-10 language and font-fallback merges) · **Target:** Microsoft Excel (Microsoft 365), Excel for Mac 16.113.4
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-11 · **Change:** minor (German ribbon catalog added) · **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,
@ -10,9 +10,10 @@ right-to-left sheets and full complex-script support. Part of
## Where we are (measured from source on `main`, after the 2026-10-10 merges)
- **A first catalog exists, for the ribbon only.** `crates/ui-egui/src/i18n.rs` (merged 10-10 in
#31, #104, #82) adds an interface-language preference that defaults to the system language
(closes #20) and a View-tab switcher, with English-keyed lookup tables: Japanese 268 labels,
Simplified Chinese, Korean, Russian and Brazilian Portuguese 266 each. The tables are used by
#31, #104, #82; German added 10-11) adds an interface-language preference that defaults to the
system language (closes #20) and a View-tab switcher, with English-keyed lookup tables:
Japanese 268 labels, Simplified Chinese, Korean, Russian, Brazilian Portuguese and German 266
each. The tables are used by
the ribbon, sheet tabs and widgets (`ribbon.rs`, `tabs.rs`, `widgets.rs`); dialogs, menus,
context menus, task panes, status messages, command labels and function descriptions are still
English literals. Untranslated labels fall back to English.
@ -47,11 +48,11 @@ separators, number/date formats, machine translation with agent review, and scri
| Portuguese | pt-BR | 266 (~12%) | no | Latin: yes | no | menus only | 4–8 h |
| Indonesian | id | 0 (0%) | no | Latin: yes | no | none | 5–8 h |
| Japanese | ja | 268 (~12%) | no | CJK system-font fallback; IME unverified; no furigana display | no | menus only | 8–12 h |
| German | de | 0 (0%; PR #163 open) | no | Latin: yes | no | none | 6–10 h |
| German | de | 266 (~12%) | no | Latin: yes | no | menus only | 4–8 h |
| Korean | ko | 266 (~12%) | no | Hangul via the CJK fallback; IME unverified | no | menus only | 6–10 h |
| Vietnamese | vi | 0 (0%) | no | Latin with stacked diacritics: unverified | no | none | 6–10 h |
Other shipped languages: Russian (ru), 266 labels (~12%), menus only.
Other shipped languages: Russian (ru) and German (de), 266 labels each (~12%), menus only.
**Total:** catalog work 10–20 h + languages 92–144 h ≈ **100–165 h**. Parallelizes almost fully
once the catalog covers dialogs and commands. **Needs a human:** native-speaker review of every
@ -73,5 +74,6 @@ language (none so far) and of localized function names.
| Date | Change | Summary |
|---|---|---|
| 2026-10-11 | minor | German ribbon catalog (`i18n/de.rs`, 266 labels, ~12%); `de` locale tags (de-DE, de-AT, de-CH…) resolve to German. PR #163 (localized German formulas/numbers) still open |
| 2026-10-10 | minor | Re-measured after #31, #104, #82, #38 merged: ribbon translated into ja, zh, ko, pt-BR and ru (266–268 labels, ~12%), system-language default, CJK/Thai/Hebrew font fallback; ~10% ready, 100–165 h |
| 2026-10-10 | major | Created: English only, no catalog, ~2,200 strings, script-support gaps, open language PRs |