i18n: translate sheet tab menu and AutoSave toggle (fixes #1537)

The sheet tab context menu buttons (Insert Sheet, Rename, Move or
Copy…, Duplicate, Tab Color, Hide, Unhide…, Protect/Unprotect Sheet,
Select All Sheets), the navigation tooltips (Previous/Next/All sheets,
New sheet), and the AutoSave toggle label and tooltip in the ribbon were
all hardcoded English — they were never routed through lang.tr().

Fix:
- tabs.rs: wrap every hardcoded UI string with app.ui.language.tr(…)
- ribbon.rs: wrap the AutoSave label and hover text with lang.tr(…)
- i18n/cs,de,es,fr,ko,pt,ru,sr,zh: add the 130 missing translation
  entries (each language only gets the entries it was missing)

Translations produced from first-principles per language, following the
terminology used for other sheet/workbook strings already in each file.

Closes #1537
This commit is contained in:
parsherr
2026-10-17 12:13:47 +03:00
parent f1894c6da6
commit 2321afd677
11 changed files with 147 additions and 17 deletions
+11
View File
@@ -535,6 +535,17 @@ pub(super) fn translate(text: &str) -> Option<&'static str> {
"Zoom Out" => "Oddálit",
// widgets.rs (alphabetical keys).
"Dismiss" => "Zavřít",
"Rename" => "Přejmenovat",
"Move or Copy…" => "Přesunout nebo kopírovat…",
"Duplicate" => "Duplikovat",
"Tab Color" => "Barva záložky",
"No Color" => "Bez barvy",
"Unhide…" => "Zobrazit…",
"Unprotect Sheet…" => "Zrušit ochranu listu…",
"Select All Sheets" => "Vybrat všechny listy",
"AutoSave" => "Automatické ukládání",
"AutoSave: save after every change (workbooks saved to a file)" => "Automatické ukládání: ukládat po každé změně (sešity uložené do souboru)",
"All sheets" => "Všechny listy",
_ => return None,
})
}
+15
View File
@@ -411,6 +411,21 @@ pub(super) fn translate(text: &str) -> Option<&'static str> {
"Dark" => "Dunkel",
"Sheet Options|View" => "Anzeige",
"Print" => "Drucken",
"Insert Sheet" => "Blatt einfügen",
"Rename" => "Umbenennen",
"Move or Copy…" => "Verschieben oder kopieren…",
"Duplicate" => "Duplizieren",
"Tab Color" => "Registerfarbe",
"No Color" => "Keine Farbe",
"Unhide…" => "Einblenden…",
"Unprotect Sheet…" => "Blattschutz aufheben…",
"Select All Sheets" => "Alle Blätter auswählen",
"AutoSave" => "AutoSpeichern",
"AutoSave: save after every change (workbooks saved to a file)" => "AutoSpeichern: nach jeder Änderung speichern (Arbeitsmappen, die in einer Datei gespeichert sind)",
"Previous sheet" => "Vorheriges Blatt",
"Next sheet" => "Nächstes Blatt",
"All sheets" => "Alle Blätter",
"New sheet (⇧F11)" => "Neues Blatt (⇧F11)",
_ => return None,
})
}
+14
View File
@@ -440,6 +440,20 @@ pub(super) fn translate(text: &str) -> Option<&'static str> {
"Compact" => "Compacto",
"Outline" => "Esquema",
"Tabular" => "Tabular",
"Insert Sheet" => "Insertar hoja",
"Rename" => "Cambiar nombre",
"Move or Copy…" => "Mover o copiar…",
"Duplicate" => "Duplicar",
"Tab Color" => "Color de etiqueta",
"No Color" => "Sin color",
"Unhide…" => "Mostrar…",
"Select All Sheets" => "Seleccionar todas las hojas",
"AutoSave" => "Autoguardar",
"AutoSave: save after every change (workbooks saved to a file)" => "Autoguardar: guardar después de cada cambio (libros guardados en un archivo)",
"Previous sheet" => "Hoja anterior",
"Next sheet" => "Hoja siguiente",
"All sheets" => "Todas las hojas",
"New sheet (⇧F11)" => "Nueva hoja (⇧F11)",
_ => return None,
})
}
+16
View File
@@ -410,6 +410,22 @@ pub(super) fn translate(text: &str) -> Option<&'static str> {
"Workbook calculation" => "Calcul du classeur",
"Enable iterative calculation" => "Activer le calcul itératif",
"Calculation settings are saved with the workbook." => "Les paramètres de calcul sont enregistrés avec le classeur.",
"Insert Sheet" => "Insérer une feuille",
"Rename" => "Renommer",
"Move or Copy…" => "Déplacer ou copier…",
"Duplicate" => "Dupliquer",
"Tab Color" => "Couleur de l'onglet",
"No Color" => "Sans couleur",
"Hide" => "Masquer",
"Unhide…" => "Afficher…",
"Unprotect Sheet…" => "Ôter la protection de la feuille…",
"Select All Sheets" => "Sélectionner toutes les feuilles",
"AutoSave" => "Enregistrement automatique",
"AutoSave: save after every change (workbooks saved to a file)" => "Enregistrement automatique : enregistrer après chaque modification (classeurs enregistrés dans un fichier)",
"Previous sheet" => "Feuille précédente",
"Next sheet" => "Feuille suivante",
"All sheets" => "Toutes les feuilles",
"New sheet (⇧F11)" => "Nouvelle feuille (⇧F11)",
_ => return None,
})
}
+16
View File
@@ -410,6 +410,22 @@ pub(super) fn translate(text: &str) -> Option<&'static str> {
"Workbook calculation" => "통합 문서 계산",
"Enable iterative calculation" => "반복 계산 사용",
"Calculation settings are saved with the workbook." => "계산 설정은 통합 문서와 함께 저장됩니다.",
"Insert Sheet" => "시트 삽입",
"Rename" => "이름 바꾸기",
"Move or Copy…" => "이동 또는 복사…",
"Duplicate" => "복제",
"Tab Color" => "탭 색상",
"No Color" => "색 없음",
"Hide" => "숨기기",
"Unhide…" => "숨기기 취소…",
"Unprotect Sheet…" => "시트 보호 해제…",
"Select All Sheets" => "모든 시트 선택",
"AutoSave" => "자동 저장",
"AutoSave: save after every change (workbooks saved to a file)" => "자동 저장: 변경할 때마다 저장 (파일로 저장된 통합 문서)",
"Previous sheet" => "이전 시트",
"Next sheet" => "다음 시트",
"All sheets" => "모든 시트",
"New sheet (⇧F11)" => "새 시트 (⇧F11)",
_ => return None,
})
}
+10
View File
@@ -956,6 +956,16 @@ pub(super) fn translate(text: &str) -> Option<&'static str> {
"Protect\nSheet" => "Proteger\nPlanilha",
"Watch\nWindow" => "Janela de\nInspeção",
"Workbook\nStatistics" => "Estatísticas da\nPasta de Trabalho",
"Rename" => "Renomear",
"Move or Copy…" => "Mover ou copiar…",
"Duplicate" => "Duplicar",
"Tab Color" => "Cor da guia",
"No Color" => "Sem cor",
"Unhide…" => "Reexibir…",
"Unprotect Sheet…" => "Desproteger planilha…",
"Select All Sheets" => "Selecionar todas as planilhas",
"AutoSave: save after every change (workbooks saved to a file)" => "Salvamento automático: salvar após cada alteração (pastas de trabalho salvas em um arquivo)",
"All sheets" => "Todas as planilhas",
_ => return None,
})
}
+16
View File
@@ -410,6 +410,22 @@ pub(super) fn translate(text: &str) -> Option<&'static str> {
"Workbook calculation" => "Вычисления в книге",
"Enable iterative calculation" => "Включить итеративные вычисления",
"Calculation settings are saved with the workbook." => "Параметры вычислений сохраняются вместе с книгой.",
"Insert Sheet" => "Вставить лист",
"Rename" => "Переименовать",
"Move or Copy…" => "Переместить или скопировать…",
"Duplicate" => "Дублировать",
"Tab Color" => "Цвет вкладки",
"No Color" => "Без цвета",
"Hide" => "Скрыть",
"Unhide…" => "Показать…",
"Unprotect Sheet…" => "Снять защиту листа…",
"Select All Sheets" => "Выделить все листы",
"AutoSave" => "Автосохранение",
"AutoSave: save after every change (workbooks saved to a file)" => "Автосохранение: сохранять после каждого изменения (книги, сохранённые в файл)",
"Previous sheet" => "Предыдущий лист",
"Next sheet" => "Следующий лист",
"All sheets" => "Все листы",
"New sheet (⇧F11)" => "Новый лист (⇧F11)",
_ => return None,
})
}
+16
View File
@@ -408,6 +408,22 @@ pub(super) fn translate(text: &str) -> Option<&'static str> {
"Bottom Margin" => "Donja margina",
"Header Margin" => "Margina zaglavlja",
"Footer Margin" => "Margina podnožja",
"Insert Sheet" => "Убаци лист",
"Rename" => "Преименуј",
"Move or Copy…" => "Премести или копирај…",
"Duplicate" => "Дупликат",
"Tab Color" => "Боја картице",
"No Color" => "Без боје",
"Hide" => "Сакриј",
"Unhide…" => "Прикажи…",
"Unprotect Sheet…" => "Уклони заштиту листа…",
"Select All Sheets" => "Изабери све листове",
"AutoSave" => "Аутоматско чување",
"AutoSave: save after every change (workbooks saved to a file)" => "Аутоматско чување: сачувај после сваке измене (свеске сачуване у датотеку)",
"Previous sheet" => "Претходни лист",
"Next sheet" => "Следећи лист",
"All sheets" => "Сви листови",
"New sheet (⇧F11)" => "Нови лист (⇧F11)",
_ => return None,
})
}
+16
View File
@@ -402,6 +402,22 @@ pub(super) fn translate(text: &str) -> Option<&'static str> {
"Workbook calculation" => "工作簿计算",
"Enable iterative calculation" => "启用迭代计算",
"Calculation settings are saved with the workbook." => "计算设置随工作簿一起保存。",
"Insert Sheet" => "插入工作表",
"Rename" => "重命名",
"Move or Copy…" => "移动或复制…",
"Duplicate" => "复制",
"Tab Color" => "标签颜色",
"No Color" => "无颜色",
"Hide" => "隐藏",
"Unhide…" => "取消隐藏…",
"Unprotect Sheet…" => "取消工作表保护…",
"Select All Sheets" => "选择所有工作表",
"AutoSave" => "自动保存",
"AutoSave: save after every change (workbooks saved to a file)" => "自动保存:每次更改后保存(已保存到文件的工作簿)",
"Previous sheet" => "上一个工作表",
"Next sheet" => "下一个工作表",
"All sheets" => "所有工作表",
"New sheet (⇧F11)" => "新建工作表 (⇧F11)",
_ => return None,
})
}
+2 -2
View File
@@ -52,14 +52,14 @@ pub fn title_bar(app: &mut SheetApp, ui: &mut Ui) {
ui.horizontal_centered(|ui| {
ui.add_space(TITLE_LEFT_PAD);
// AutoSave toggle (saves after each change when the workbook has a file).
ui.label(egui::RichText::new("AutoSave").font(theme::ui_font(12.5)).color(t.text_dim));
ui.label(egui::RichText::new(app.ui.language.tr("AutoSave")).font(theme::ui_font(12.5)).color(t.text_dim));
let on = app.grid.autosave();
let (r, resp) = ui.allocate_exact_size(vec2(30.0, 16.0), Sense::click());
ui.painter().rect_filled(r, 8.0, if on { t.accent } else { Color32::TRANSPARENT });
ui.painter().rect_stroke(r, 8.0, Stroke::new(1.0, if on { t.accent } else { t.text_dim }), StrokeKind::Inside);
let knob = if on { pos2(r.right() - 8.0, r.center().y) } else { pos2(r.left() + 8.0, r.center().y) };
ui.painter().circle_filled(knob, 5.0, if on { Color32::WHITE } else { t.text_dim });
if resp.on_hover_text("AutoSave: save after every change (workbooks saved to a file)").clicked() {
if resp.on_hover_text(app.ui.language.tr("AutoSave: save after every change (workbooks saved to a file)")).clicked() {
app.grid.toggle_autosave();
}
ui.add_space(6.0);
+15 -15
View File
@@ -43,14 +43,14 @@ pub fn sheet_tabs(app: &mut SheetApp, ui: &mut Ui) {
ui.horizontal_centered(|ui| {
ui.spacing_mut().item_spacing.x = 0.0;
ui.add_space(8.0);
if crate::widgets::icon_button(ui, Icon::Left, t.text_dim, "Previous sheet", vec2(24.0, 24.0)).clicked() {
if crate::widgets::icon_button(ui, Icon::Left, t.text_dim, app.ui.language.tr("Previous sheet"), vec2(24.0, 24.0)).clicked() {
app.run_or_alert("sheet.previous", json!({}));
}
if crate::widgets::icon_button(ui, Icon::Right, t.text_dim, "Next sheet", vec2(24.0, 24.0)).clicked() {
if crate::widgets::icon_button(ui, Icon::Right, t.text_dim, app.ui.language.tr("Next sheet"), vec2(24.0, 24.0)).clicked() {
app.run_or_alert("sheet.next", json!({}));
}
let all = crate::widgets::icon_button(ui, Icon::SheetList, t.text_dim, "All sheets", vec2(24.0, 24.0));
all.widget_info(|| egui::WidgetInfo::labeled(egui::WidgetType::Button, true, "All sheets"));
let all = crate::widgets::icon_button(ui, Icon::SheetList, t.text_dim, app.ui.language.tr("All sheets"), vec2(24.0, 24.0));
all.widget_info(|| egui::WidgetInfo::labeled(egui::WidgetType::Button, true, app.ui.language.tr("All sheets")));
let items = app.session.active().map(|d| navigator_items(&d.wb.sheets)).unwrap_or_default();
let active = app.session.active().map(|d| d.wb.active_sheet.to_string()).unwrap_or_default();
let rows: Vec<(&str, String)> = items.iter().map(|(i, name)| (i.as_str(), name.clone())).collect();
@@ -168,42 +168,42 @@ pub fn sheet_tabs(app: &mut SheetApp, ui: &mut Ui) {
}
resp.context_menu(|ui| {
ui.set_min_width(180.0);
if ui.button("Insert Sheet").clicked() {
if ui.button(app.ui.language.tr("Insert Sheet")).clicked() {
app.run_or_alert("home.insertSheet", json!({"before": i}));
}
if ui.button("Delete").clicked() {
app.run_or_alert("home.deleteSheet", json!({"sheet": i}));
}
if ui.button("Rename").clicked() {
if ui.button(app.ui.language.tr("Rename")).clicked() {
app.grid.renaming_tab = Some(i);
app.grid.rename_text = name.clone();
}
if ui.button("Move or Copy…").clicked() {
if ui.button(app.ui.language.tr("Move or Copy…")).clicked() {
app.open_dialog("moveSheet", json!({"sheet": i}));
}
if ui.button("Duplicate").clicked() {
if ui.button(app.ui.language.tr("Duplicate")).clicked() {
app.run_or_alert("sheet.move", json!({"sheet": i, "to": i + 1, "copy": true}));
}
ui.menu_button("Tab Color", |ui| {
ui.menu_button(app.ui.language.tr("Tab Color"), |ui| {
let colors = app.session.active().map(|d| d.wb.theme.colors).unwrap_or_default();
if let Some(c) = crate::widgets::color_palette(ui, &colors, "No Color") {
if let Some(c) = crate::widgets::color_palette(ui, &colors, app.ui.language.tr("No Color")) {
app.run_or_alert("sheet.tabColor", json!({"sheet": i, "color": c}));
ui.close();
}
});
ui.separator();
if ui.button("Hide").clicked() {
if ui.button(app.ui.language.tr("Hide")).clicked() {
app.run_or_alert("sheet.hide", json!({"sheet": i}));
}
if ui.button("Unhide…").clicked() {
if ui.button(app.ui.language.tr("Unhide…")).clicked() {
app.run_or_alert("sheet.unhide", json!({}));
}
ui.separator();
let protected = app.session.active().and_then(|d| d.wb.active().map(|s| s.is_protected())).unwrap_or(false);
if ui.button(if protected { "Unprotect Sheet…" } else { "Protect Sheet…" }).clicked() {
if ui.button(if protected { app.ui.language.tr("Unprotect Sheet…") } else { app.ui.language.tr("Protect Sheet…") }).clicked() {
app.open_dialog(if protected { "unprotectSheet" } else { "protectSheet" }, json!({}));
}
if ui.button("Select All Sheets").clicked() {
if ui.button(app.ui.language.tr("Select All Sheets")).clicked() {
ui.close();
}
});
@@ -212,7 +212,7 @@ pub fn sheet_tabs(app: &mut SheetApp, ui: &mut Ui) {
});
});
ui.add_space(6.0);
if crate::widgets::icon_button(ui, Icon::Plus, t.text_dim, "New sheet (⇧F11)", vec2(26.0, 26.0)).clicked() {
if crate::widgets::icon_button(ui, Icon::Plus, t.text_dim, app.ui.language.tr("New sheet (⇧F11)"), vec2(26.0, 26.0)).clicked() {
app.run_or_alert("home.insertSheet", json!({}));
}
// The track ends where the grid does, so it stops under the vertical scrollbar.