From cb059716592935b9b0b9542b7e80d34a4748631e Mon Sep 17 00:00:00 2001 From: Zinadin Zidan Date: Thu, 5 Nov 2026 11:47:39 +0600 Subject: [PATCH] =?UTF-8?q?i18n:=20German=20context=20menus'=20Insert=20re?= =?UTF-8?q?ads=20"Zellen=20einf=C3=BCgen",=20not=20a=20second=20"Einf?= =?UTF-8?q?=C3=BCgen"=20(#2874)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit German showed "Einfügen" for Paste and again for Insert in the cell menu ("Einfügen…") and the row and column header menus ("Einfügen"). The cell menu's Insert… now reads "Zellen einfügen…", as Excel's German menu does. The header menus' Insert gets its own key, "Header Menu|Insert", German "Zellen einfügen"; the plain "Insert" stays as the Insert dialog's title and button use it, and every other catalog gets the new key with the text it shows today. A test reads the three menus' items from menus.rs and checks that no two read alike in German. Co-Authored-By: Claude Opus 5.5 --- crates/ui-egui/src/grid/menus.rs | 4 +-- crates/ui-egui/src/grid/tests.rs | 46 ++++++++++++++++++++++++++++++++ crates/ui-egui/src/i18n/cs.rs | 1 + crates/ui-egui/src/i18n/de.rs | 3 ++- crates/ui-egui/src/i18n/el.rs | 1 + crates/ui-egui/src/i18n/es.rs | 1 + crates/ui-egui/src/i18n/fr.rs | 1 + crates/ui-egui/src/i18n/it.rs | 1 + crates/ui-egui/src/i18n/ja.rs | 1 + crates/ui-egui/src/i18n/ko.rs | 1 + crates/ui-egui/src/i18n/nl.rs | 1 + crates/ui-egui/src/i18n/pl.rs | 1 + crates/ui-egui/src/i18n/pt.rs | 1 + crates/ui-egui/src/i18n/ro.rs | 1 + crates/ui-egui/src/i18n/ru.rs | 1 + crates/ui-egui/src/i18n/sr.rs | 1 + crates/ui-egui/src/i18n/tr.rs | 1 + crates/ui-egui/src/i18n/uk.rs | 1 + crates/ui-egui/src/i18n/vi.rs | 1 + crates/ui-egui/src/i18n/zh.rs | 1 + 20 files changed, 67 insertions(+), 3 deletions(-) diff --git a/crates/ui-egui/src/grid/menus.rs b/crates/ui-egui/src/grid/menus.rs index 575dac504..e9ee1a976 100644 --- a/crates/ui-egui/src/grid/menus.rs +++ b/crates/ui-egui/src/grid/menus.rs @@ -496,7 +496,7 @@ pub(super) fn header_menu(app: &mut SheetApp, ui: &mut egui::Ui, was_open: bool) ("Copy", "edit.copy"), ("Paste", "edit.paste"), ("-", ""), - ("Insert", "home.insertRows"), + ("Header Menu|Insert", "home.insertRows"), ("Delete", "home.deleteRows"), ("Clear Contents", "edit.clearContents"), ("-", ""), @@ -513,7 +513,7 @@ pub(super) fn header_menu(app: &mut SheetApp, ui: &mut egui::Ui, was_open: bool) ("Copy", "edit.copy"), ("Paste", "edit.paste"), ("-", ""), - ("Insert", "home.insertColumns"), + ("Header Menu|Insert", "home.insertColumns"), ("Delete", "home.deleteColumns"), ("Clear Contents", "edit.clearContents"), ("-", ""), diff --git a/crates/ui-egui/src/grid/tests.rs b/crates/ui-egui/src/grid/tests.rs index 74abfc861..427c67629 100644 --- a/crates/ui-egui/src/grid/tests.rs +++ b/crates/ui-egui/src/grid/tests.rs @@ -180,6 +180,52 @@ fn filter_menu_uses_the_table_whose_header_was_clicked() { assert_eq!(filter_table_range(&sh, 1, 4), None); } +/// The `("Label", "id")` keys written in `src`, without separators. +fn menu_labels(src: &str) -> Vec<&str> { + src.split("(\"").skip(1).filter_map(|rest| rest.split_once("\", \"").map(|(label, _)| label)).filter(|label| *label != "-").collect() +} + +/// The source of `menus.rs` from `start` to the first `end` after it. +fn menu_source<'a>(src: &'a str, start: &str, end: &str) -> &'a str { + let from = src.find(start).unwrap_or_else(|| panic!("{start:?} not in menus.rs")); + let rest = &src[from..]; + &rest[..rest.find(end).unwrap_or_else(|| panic!("{end:?} not after {start:?}"))] +} + +/// German read "Einfügen" for Paste and "Einfügen…"/"Einfügen" for Insert in the same menu +/// (#2874): no two items of the cell, row header or column header menu may read alike, ignoring +/// case and a trailing ellipsis. The items are read from `menus.rs`, so new ones are checked too. +#[test] +fn german_context_menus_have_no_two_items_alike() { + use crate::i18n::Language; + let src = include_str!("menus.rs"); + let cell = menu_labels(menu_source(src, "fn context_menu(", "let lang =")); + let (rows, columns) = + menu_source(src, "fn header_menu(", "let lang =").split_once("} else {").expect("header menu has a rows and a columns list"); + let insert_copied = menu_labels(menu_source(src, "fn insert_copied_item(", "\n}")); + assert_eq!(insert_copied.len(), 3, "{insert_copied:?}"); + for (menu, keys) in [("cell", cell), ("row header", menu_labels(rows)), ("column header", menu_labels(columns))] { + assert!(keys.contains(&"Paste") && keys.len() > 8, "{menu} menu not read from menus.rs: {keys:?}"); + // A menu holds at most one Insert Copied/Cut Cells entry. + for extra in &insert_copied { + let mut seen: Vec<(String, &str)> = Vec::new(); + for key in keys.iter().chain([extra]) { + let shown = Language::De.tr(key).trim_end_matches('…').trim().to_lowercase(); + if let Some((_, other)) = seen.iter().find(|(text, _)| *text == shown) { + panic!("German {menu} menu shows {key:?} and {other:?} both as {shown:?}"); + } + seen.push((shown, key)); + } + } + } + assert_eq!(Language::De.tr("Insert…"), "Zellen einfügen…"); + assert_eq!(Language::De.tr("Header Menu|Insert"), "Zellen einfügen"); + // Only German changed: the header menu's Insert reads as the plain Insert everywhere else. + for language in Language::ALL.into_iter().filter(|l| *l != Language::De) { + assert_eq!(language.tr("Header Menu|Insert"), language.tr("Insert"), "{}", language.code()); + } +} + #[test] fn cell_text_y_moves_monotonically_in_standard_and_tall_rows() { let rect_std = Rect::from_min_max(pos2(0.0, 0.0), pos2(100.0, 20.0)); diff --git a/crates/ui-egui/src/i18n/cs.rs b/crates/ui-egui/src/i18n/cs.rs index 58d308413..39e6337dd 100644 --- a/crates/ui-egui/src/i18n/cs.rs +++ b/crates/ui-egui/src/i18n/cs.rs @@ -57,6 +57,7 @@ pub(super) fn translate(text: &str) -> Option<&'static str> { "Format\nPane" => "Podokno\nformátu", "Format" => "Formát", "Insert" => "Vložit", + "Header Menu|Insert" => "Vložit", "Insert Cells…" => "Vložit buňky…", "Delete" => "Odstranit", "Delete Cells…" => "Odstranit buňky…", diff --git a/crates/ui-egui/src/i18n/de.rs b/crates/ui-egui/src/i18n/de.rs index 2e6ba713f..f136e483b 100644 --- a/crates/ui-egui/src/i18n/de.rs +++ b/crates/ui-egui/src/i18n/de.rs @@ -57,6 +57,7 @@ pub(super) fn translate(text: &str) -> Option<&'static str> { "Format\nPane" => "Format-\nbereich", "Format" => "Format", "Insert" => "Einfügen", + "Header Menu|Insert" => "Zellen einfügen", "Insert Cells…" => "Zellen einfügen…", "Delete" => "Löschen", "Select Data…" => "Daten auswählen…", @@ -476,7 +477,7 @@ pub(super) fn translate(text: &str) -> Option<&'static str> { // grid.rs cell and row/column header context menus. "Cut" => "Ausschneiden", "Copy" => "Kopieren", - "Insert…" => "Einfügen…", + "Insert…" => "Zellen einfügen…", "Delete…" => "Löschen…", "Filter by Selected Cell's Value" => "Nach Wert der gewählten Zelle filtern", "New Comment" => "Neuer Kommentar", diff --git a/crates/ui-egui/src/i18n/el.rs b/crates/ui-egui/src/i18n/el.rs index 218fa5a6f..dc57982c7 100644 --- a/crates/ui-egui/src/i18n/el.rs +++ b/crates/ui-egui/src/i18n/el.rs @@ -56,6 +56,7 @@ pub(super) fn translate(text: &str) -> Option<&'static str> { "Format\nPane" => "Παράθυρο\nμορφοποίησης", "Format" => "Μορφοποίηση", "Insert" => "Εισαγωγή", + "Header Menu|Insert" => "Εισαγωγή", "Insert Cells…" => "Εισαγωγή κελιών…", "Delete" => "Διαγραφή", "Delete Cells…" => "Διαγραφή κελιών…", diff --git a/crates/ui-egui/src/i18n/es.rs b/crates/ui-egui/src/i18n/es.rs index b6adcf774..3c15a16b1 100644 --- a/crates/ui-egui/src/i18n/es.rs +++ b/crates/ui-egui/src/i18n/es.rs @@ -60,6 +60,7 @@ pub(super) fn translate(text: &str) -> Option<&'static str> { "Format\nPane" => "Panel\nde formato", "Format" => "Formato", "Insert" => "Insertar", + "Header Menu|Insert" => "Insertar", "Insert Cells…" => "Insertar celdas…", "Delete" => "Eliminar", "Delete Cells…" => "Eliminar celdas…", diff --git a/crates/ui-egui/src/i18n/fr.rs b/crates/ui-egui/src/i18n/fr.rs index e11ef4599..3e95d4b72 100644 --- a/crates/ui-egui/src/i18n/fr.rs +++ b/crates/ui-egui/src/i18n/fr.rs @@ -67,6 +67,7 @@ pub(super) fn translate(text: &str) -> Option<&'static str> { "Format\nPane" => "Volet\nFormat", "Format" => "Format", "Insert" => "Insertion", + "Header Menu|Insert" => "Insertion", "Insert Cells…" => "Insérer des cellules…", "Delete" => "Supprimer", "Delete Cells…" => "Supprimer des cellules…", diff --git a/crates/ui-egui/src/i18n/it.rs b/crates/ui-egui/src/i18n/it.rs index 9a371e673..3ad0ff328 100644 --- a/crates/ui-egui/src/i18n/it.rs +++ b/crates/ui-egui/src/i18n/it.rs @@ -60,6 +60,7 @@ pub(super) fn translate(text: &str) -> Option<&'static str> { "Format\nPane" => "Riquadro\nFormato", "Format" => "Formato", "Insert" => "Inserisci", + "Header Menu|Insert" => "Inserisci", "Insert Cells…" => "Inserisci celle…", "Delete" => "Elimina", "Delete Cells…" => "Elimina celle…", diff --git a/crates/ui-egui/src/i18n/ja.rs b/crates/ui-egui/src/i18n/ja.rs index 47fd0e9f3..19fc85f02 100644 --- a/crates/ui-egui/src/i18n/ja.rs +++ b/crates/ui-egui/src/i18n/ja.rs @@ -64,6 +64,7 @@ pub(super) const CORE: &[(&str, &str)] = &[ ("Format\nPane", "書式ウィンドウ"), ("Format", "書式"), ("Insert", "挿入"), + ("Header Menu|Insert", "挿入"), ("Insert Cells…", "セルの挿入…"), ("Delete", "削除"), ("Delete Cells…", "セルの削除…"), diff --git a/crates/ui-egui/src/i18n/ko.rs b/crates/ui-egui/src/i18n/ko.rs index 906dea54f..8c28be26e 100644 --- a/crates/ui-egui/src/i18n/ko.rs +++ b/crates/ui-egui/src/i18n/ko.rs @@ -62,6 +62,7 @@ pub(super) fn translate(text: &str) -> Option<&'static str> { "Format\nPane" => "서식\n창", "Format" => "서식", "Insert" => "삽입", + "Header Menu|Insert" => "삽입", "Insert Cells…" => "셀 삽입…", "Delete" => "삭제", "Delete Cells…" => "셀 삭제…", diff --git a/crates/ui-egui/src/i18n/nl.rs b/crates/ui-egui/src/i18n/nl.rs index b1d415211..b5cddb88d 100644 --- a/crates/ui-egui/src/i18n/nl.rs +++ b/crates/ui-egui/src/i18n/nl.rs @@ -61,6 +61,7 @@ pub(super) fn translate(text: &str) -> Option<&'static str> { "Format\nPane" => "Opmaak-\nvenster", "Format" => "Opmaak", "Insert" => "Invoegen", + "Header Menu|Insert" => "Invoegen", "Insert Cells…" => "Cellen invoegen…", "Delete" => "Verwijderen", "Delete Cells…" => "Cellen verwijderen…", diff --git a/crates/ui-egui/src/i18n/pl.rs b/crates/ui-egui/src/i18n/pl.rs index ad9c254c1..f2bfd72c7 100644 --- a/crates/ui-egui/src/i18n/pl.rs +++ b/crates/ui-egui/src/i18n/pl.rs @@ -56,6 +56,7 @@ pub(super) fn translate(text: &str) -> Option<&'static str> { "Format\nPane" => "Okienko\nformatowania", "Format" => "Formatuj", "Insert" => "Wstaw", + "Header Menu|Insert" => "Wstaw", "Insert Cells…" => "Wstaw komórki…", "Delete" => "Usuń", "Delete Cells…" => "Usuń komórki…", diff --git a/crates/ui-egui/src/i18n/pt.rs b/crates/ui-egui/src/i18n/pt.rs index f78ef4cf5..d525f027e 100644 --- a/crates/ui-egui/src/i18n/pt.rs +++ b/crates/ui-egui/src/i18n/pt.rs @@ -59,6 +59,7 @@ pub(super) fn translate(text: &str) -> Option<&'static str> { "Format\nPane" => "Painel de\nFormatação", "Format" => "Formatar", "Insert" => "Inserir", + "Header Menu|Insert" => "Inserir", "Insert Cells…" => "Inserir Células…", "Delete" => "Excluir", "Delete Cells…" => "Excluir Células…", diff --git a/crates/ui-egui/src/i18n/ro.rs b/crates/ui-egui/src/i18n/ro.rs index 738fc554f..66eb854b7 100644 --- a/crates/ui-egui/src/i18n/ro.rs +++ b/crates/ui-egui/src/i18n/ro.rs @@ -63,6 +63,7 @@ pub(super) fn translate(text: &str) -> Option<&'static str> { "Format\nPane" => "Panou\nformatare", "Format" => "Format", "Insert" => "Inserare", + "Header Menu|Insert" => "Inserare", "Insert Cells…" => "Inserare celule…", "Delete" => "Ștergere", "Delete Cells…" => "Ștergere celule…", diff --git a/crates/ui-egui/src/i18n/ru.rs b/crates/ui-egui/src/i18n/ru.rs index 60141a853..00a3062bd 100644 --- a/crates/ui-egui/src/i18n/ru.rs +++ b/crates/ui-egui/src/i18n/ru.rs @@ -62,6 +62,7 @@ pub(super) fn translate(text: &str) -> Option<&'static str> { "Format\nPane" => "Область\nформатирования", "Format" => "Формат", "Insert" => "Вставить", + "Header Menu|Insert" => "Вставить", "Insert Cells…" => "Вставить ячейки…", "Delete" => "Удалить", "Delete Cells…" => "Удалить ячейки…", diff --git a/crates/ui-egui/src/i18n/sr.rs b/crates/ui-egui/src/i18n/sr.rs index d02c66bb8..9254dc938 100644 --- a/crates/ui-egui/src/i18n/sr.rs +++ b/crates/ui-egui/src/i18n/sr.rs @@ -63,6 +63,7 @@ pub(super) fn translate(text: &str) -> Option<&'static str> { "Format\nPane" => "Okno za\noblikovanje", "Format" => "Oblikovanje", "Insert" => "Umetni", + "Header Menu|Insert" => "Umetni", "Insert Cells…" => "Umetni ćelije…", "Delete" => "Obriši", "Delete Cells…" => "Obriši ćelije…", diff --git a/crates/ui-egui/src/i18n/tr.rs b/crates/ui-egui/src/i18n/tr.rs index a58505848..c8da06cb1 100644 --- a/crates/ui-egui/src/i18n/tr.rs +++ b/crates/ui-egui/src/i18n/tr.rs @@ -59,6 +59,7 @@ pub(super) fn translate(text: &str) -> Option<&'static str> { "Format\nPane" => "Biçim\nBölmesi", "Format" => "Biçim", "Insert" => "Ekle", + "Header Menu|Insert" => "Ekle", "Insert Cells…" => "Hücre Ekle…", "Delete" => "Sil", "Delete Cells…" => "Hücreleri Sil…", diff --git a/crates/ui-egui/src/i18n/uk.rs b/crates/ui-egui/src/i18n/uk.rs index 96070eaaf..35fc9f0f7 100644 --- a/crates/ui-egui/src/i18n/uk.rs +++ b/crates/ui-egui/src/i18n/uk.rs @@ -58,6 +58,7 @@ pub(super) fn translate(text: &str) -> Option<&'static str> { "Format\nPane" => "Область\nформатування", "Format" => "Формат", "Insert" => "Вставити", + "Header Menu|Insert" => "Вставити", "Insert Cells…" => "Вставити комірки…", "Delete" => "Видалити", "Delete Cells…" => "Видалити комірки…", diff --git a/crates/ui-egui/src/i18n/vi.rs b/crates/ui-egui/src/i18n/vi.rs index 7a188a08e..8cb5a32ac 100644 --- a/crates/ui-egui/src/i18n/vi.rs +++ b/crates/ui-egui/src/i18n/vi.rs @@ -64,6 +64,7 @@ pub(super) fn translate(text: &str) -> Option<&'static str> { "Format\nPane" => "Ngăn\nđịnh dạng", "Format" => "Định dạng", "Insert" => "Chèn", + "Header Menu|Insert" => "Chèn", "Insert Cells…" => "Chèn ô…", "Delete" => "Xóa", "Delete Cells…" => "Xóa ô…", diff --git a/crates/ui-egui/src/i18n/zh.rs b/crates/ui-egui/src/i18n/zh.rs index 601e0a1bb..e71a0df3f 100644 --- a/crates/ui-egui/src/i18n/zh.rs +++ b/crates/ui-egui/src/i18n/zh.rs @@ -62,6 +62,7 @@ pub(super) fn translate(text: &str) -> Option<&'static str> { "Format\nPane" => "格式\n窗格", "Format" => "格式", "Insert" => "插入", + "Header Menu|Insert" => "插入", "Insert Cells…" => "插入单元格…", "Delete" => "删除", "Delete Cells…" => "删除单元格…",