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…" => "删除单元格…",