Translate form-dialog field labels, choices and notes

Page Setup, Insert and the other form dialogs drew their field labels in
English in every interface language, though their titles and OK/Cancel
were translated and most catalogs already carry the labels.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01JadgGo4G2GHaAMNb3qyygk
This commit is contained in:
Viorel Toader
2026-10-21 10:57:10 +03:00
committed by Claude
co-authored by Claude Opus 5.5
parent 37e41424ed
commit 29adb19872
2 changed files with 53 additions and 10 deletions
+12 -10
View File
@@ -1389,12 +1389,14 @@ fn form(ui: &mut egui::Ui, d: &mut Dialog, confirm: &mut bool, open: &mut bool)
/// Draws a dialog's `fields`, editing its values.
fn form_fields(ui: &mut egui::Ui, d: &mut Dialog) {
// Field labels, choices and notes are English source strings, translated as they are drawn.
let lang = crate::i18n::current(ui.ctx());
egui::Grid::new("form").num_columns(1).spacing(vec2(8.0, 6.0)).show(ui, |ui| {
for f in d.fields.clone() {
match f {
Field::Text { key, label } => {
ui.vertical(|ui| {
ui.label(label);
ui.label(lang.tr(label));
let mut s = d
.values
.get(key)
@@ -1414,17 +1416,17 @@ fn form_fields(ui: &mut egui::Ui, d: &mut Dialog) {
Field::Password { key, label } => {
// Masked as typed (Excel shows dots); "Show password" reveals it on purpose.
ui.vertical(|ui| {
ui.label(label);
ui.label(lang.tr(label));
let mut s = d.values.get(key).and_then(Json::as_str).unwrap_or_default().to_string();
if ui.add(egui::TextEdit::singleline(&mut s).password(!d.show_password).desired_width(320.0)).changed() {
d.values.insert(key.into(), json!(s));
}
ui.checkbox(&mut d.show_password, "Show password");
ui.checkbox(&mut d.show_password, lang.tr("Show password"));
});
}
Field::Number { key, label } => {
ui.horizontal(|ui| {
ui.label(label);
ui.label(lang.tr(label));
let mut n = d.values.get(key).and_then(Json::as_f64).unwrap_or(0.0);
if ui.add(egui::DragValue::new(&mut n).speed(0.5)).changed() {
d.values.insert(key.into(), json!(n));
@@ -1433,20 +1435,20 @@ fn form_fields(ui: &mut egui::Ui, d: &mut Dialog) {
}
Field::Choice { key, label, options } => {
ui.vertical(|ui| {
ui.label(egui::RichText::new(label).strong());
ui.label(egui::RichText::new(lang.tr(label)).strong());
let cur = d.values.get(key).and_then(Json::as_str).unwrap_or("").to_string();
if d.name == "dataValidation" {
let selected = options.iter().find(|(val, _)| *val == cur).map(|(_, text)| *text).unwrap_or("");
let selected = options.iter().find(|(val, _)| *val == cur).map(|(_, text)| lang.tr(text)).unwrap_or("");
egui::ComboBox::from_id_salt(("dataValidation", key)).selected_text(selected).width(300.0).show_ui(ui, |ui| {
for (val, text) in options {
if ui.selectable_label(cur == val, text).clicked() {
if ui.selectable_label(cur == val, lang.tr(text)).clicked() {
d.set_value(key, json!(val));
}
}
});
} else {
for (val, text) in options {
if ui.radio(cur == val, text).clicked() {
if ui.radio(cur == val, lang.tr(text)).clicked() {
d.set_value(key, json!(val));
}
}
@@ -1455,12 +1457,12 @@ fn form_fields(ui: &mut egui::Ui, d: &mut Dialog) {
}
Field::Check { key, label } => {
let mut b = d.values.get(key).and_then(Json::as_bool).unwrap_or(false);
if ui.checkbox(&mut b, label).changed() {
if ui.checkbox(&mut b, lang.tr(label)).changed() {
d.values.insert(key.into(), json!(b));
}
}
Field::Note(t) => {
ui.label(egui::RichText::new(t).small());
ui.label(egui::RichText::new(lang.tr(&t)).small());
}
}
ui.end_row();
@@ -0,0 +1,41 @@
//! Form dialogs draw their field labels and choices in the interface language, as their titles
//! and OK/Cancel buttons already were (Page Setup showed "Left margin (in):" in every language).
use egui_kittest::kittest::Queryable as _;
use gridcraft_engine::Session;
use gridcraft_ui_egui::SheetApp;
use serde_json::json;
fn harness() -> egui_kittest::Harness<'static, SheetApp> {
let mut session = Session::new();
session.new_workbook();
let mut h = egui_kittest::Harness::builder().with_size(egui::vec2(1200.0, 800.0)).build_ui_state(
|ui, app: &mut SheetApp| {
let ctx = ui.ctx().clone();
app.logic(&ctx);
app.ui(ui);
},
SheetApp::new(session, Default::default()),
);
h.run_steps(4);
h
}
#[test]
fn form_fields_are_translated() {
for (dialog, translated, english) in [
("pageSetup", ["Margem esquerda (pol.):", "Rodapé (pol.):"], ["Left margin (in):", "Footer (in):"]),
("insertPaste", ["Deslocar células para a direita", "Deslocar células para baixo"], ["Shift cells right", "Shift cells down"]),
] {
let mut h = harness();
h.state_mut().run("app.language.set", json!({"language": "pt"})).unwrap();
h.state_mut().open_dialog(dialog, json!({}));
h.run_steps(3);
for label in translated {
assert!(h.query_by_label_contains(label).is_some(), "{dialog}: no {label}");
}
for label in english {
assert!(h.query_by_label_contains(label).is_none(), "{dialog}: {label} is untranslated");
}
}
}