feat(i18n): complete Japanese localization and eliminate UI hardcoded strings (#753)

Completes the Japanese catalog (all commands, panels, dialogs and preferences) and routes the remaining hard-coded UI labels through the translation lookup. English stays the default.
This commit is contained in:
Mithril_MEX authored and GitHub committed 2026-10-13 13:24:24 -04:00
1 parent a8b3b21fd0
commit d437c21368
35 files changed
+2219 -265

No files matched your search

+18 -14
View File
@@ -368,14 +368,14 @@ pub fn rows(app: &mut SolveApp, ui: &mut egui::Ui, k: &mut Mo, inputs: &mut [Sel
if ui.small_button(if off { "Unsuppress" } else { "Suppress" }).clicked() {
let _ = app.run("contact.edit", json!({"set": n, "suppressed": !off}));
}
if ui.small_button("×").on_hover_text("Delete the set").clicked() {
if ui.small_button("×").on_hover_text(crate::i18n::tr_label("Delete the set")).clicked() {
let _ = app.run("contact.edit", json!({"set": n, "delete": true}));
}
});
ui.end_row();
}
row_label(ui, "");
if ui.button("Check collisions").clicked() {
if ui.button(crate::i18n::tr_label("Check collisions")).clicked() {
*check = Some(app.session.execute("contact.check", &json!({})).unwrap_or_else(|e| json!({"error": e.to_string()})));
}
ui.end_row();
@@ -415,7 +415,7 @@ pub fn rows(app: &mut SolveApp, ui: &mut egui::Ui, k: &mut Mo, inputs: &mut [Sel
let moving = joints_moving(app);
if moving.is_empty() {
row_label(ui, "");
ui.label(RichText::new("no joint that moves yet").color(t.text_dim));
ui.label(RichText::new(crate::i18n::tr_label("no joint that moves yet")).color(t.text_dim));
ui.end_row();
return enter;
}
@@ -448,7 +448,7 @@ pub fn rows(app: &mut SolveApp, ui: &mut egui::Ui, k: &mut Mo, inputs: &mut [Sel
*playing = false;
}
ui.add_space(6.0);
ui.checkbox(looping, "Loop");
ui.checkbox(looping, crate::i18n::tr_label("Loop"));
let names: Vec<String> = SPEEDS.iter().map(|x| format!("{x}×")).collect();
let refs: Vec<&str> = names.iter().map(String::as_str).collect();
combo(ui, "ms_speed", &refs, speed);
@@ -479,7 +479,7 @@ pub fn rows(app: &mut SolveApp, ui: &mut egui::Ui, k: &mut Mo, inputs: &mut [Sel
row_label(ui, &format!("Track {}", ti + 1));
ui.horizontal(|ui| {
combo(ui, &format!("ms_joint{ti}"), &refs, &mut pos);
if ui.small_button("×").on_hover_text("Remove the track").clicked() {
if ui.small_button("×").on_hover_text(crate::i18n::tr_label("Remove the track")).clicked() {
remove = Some(ti);
}
});
@@ -532,7 +532,7 @@ pub fn rows(app: &mut SolveApp, ui: &mut egui::Ui, k: &mut Mo, inputs: &mut [Sel
tracks.remove(i);
}
row_label(ui, "");
if ui.button("Add Key").on_hover_text("Key a joint's value at this step").clicked()
if ui.button(crate::i18n::tr_label("Add Key")).on_hover_text(crate::i18n::tr_label("Key a joint's value at this step")).clicked()
&& let Some((ji, _, kind)) = moving.first()
{
let unit = if kind.is_angle(0) { "deg" } else { "mm" };
@@ -622,7 +622,7 @@ pub fn rows(app: &mut SolveApp, ui: &mut egui::Ui, k: &mut Mo, inputs: &mut [Sel
ui.style_mut().wrap_mode = Some(egui::TextWrapMode::Extend);
egui::Grid::new("configuration_table").num_columns(2).min_col_width(210.0).spacing(vec2(10.0, 8.0)).show(ui, |ui| {
// Header.
ui.label(RichText::new("Configuration").strong());
ui.label(RichText::new(crate::i18n::tr_label("Configuration")).strong());
ui.horizontal(|ui| {
for c in &tb.columns {
ui.allocate_ui_with_layout(vec2(190.0, 22.0), egui::Layout::left_to_right(egui::Align::Center), |ui| {
@@ -641,7 +641,7 @@ pub fn rows(app: &mut SolveApp, ui: &mut egui::Ui, k: &mut Mo, inputs: &mut [Sel
.map(str::to_string)
.unwrap_or(label);
ui.add_sized(vec2(156.0, 22.0), egui::Label::new(RichText::new(label).strong()).truncate()).on_hover_text(c);
if ui.small_button("×").on_hover_text("Remove the column").clicked() {
if ui.small_button("×").on_hover_text(crate::i18n::tr_label("Remove the column")).clicked() {
let key = if kind == "suppress" { "feature" } else { kind };
run(
app,
@@ -663,11 +663,11 @@ pub fn rows(app: &mut SolveApp, ui: &mut egui::Ui, k: &mut Mo, inputs: &mut [Sel
)
.on_hover_text(name);
if active {
ui.label(RichText::new("Active").color(t.accent));
ui.label(RichText::new(crate::i18n::tr_label("Active")).color(t.accent));
if v.get("matches").and_then(Value::as_bool) == Some(false) && ui.button("Apply").clicked() {
run(app, error, "config.activate", json!({ "row": name }));
}
} else if ui.button("Activate").clicked() {
} else if ui.button(crate::i18n::tr_label("Activate")).clicked() {
run(app, error, "config.activate", json!({ "row": name }));
}
});
@@ -737,7 +737,7 @@ pub fn rows(app: &mut SolveApp, ui: &mut egui::Ui, k: &mut Mo, inputs: &mut [Sel
}
});
}
if ui.small_button("×").on_hover_text("Delete the row").clicked() {
if ui.small_button("×").on_hover_text(crate::i18n::tr_label("Delete the row")).clicked() {
run(app, error, "config.row", json!({"name": name, "delete": true}));
}
});
@@ -748,8 +748,12 @@ pub fn rows(app: &mut SolveApp, ui: &mut egui::Ui, k: &mut Mo, inputs: &mut [Sel
// New row (a copy of the active one) and new column.
ui.horizontal(|ui| {
ui.style_mut().wrap_mode = Some(egui::TextWrapMode::Extend);
ui.add(egui::TextEdit::singleline(new_row).hint_text("new configuration").desired_width(160.0));
if ui.button("Add Row").on_hover_text("A new configuration, a copy of the active one").clicked() {
ui.add(egui::TextEdit::singleline(new_row).hint_text(crate::i18n::tr_label("new configuration")).desired_width(160.0));
if ui
.button(crate::i18n::tr_label("Add Row"))
.on_hover_text(crate::i18n::tr_label("A new configuration, a copy of the active one"))
.clicked()
{
let name = if new_row.trim().is_empty() {
(tb.rows.len() + 1..).map(|k| format!("Configuration{k}")).find(|n| !tb.rows.iter().any(|r| &r.0 == n)).unwrap_or_default()
} else {
@@ -802,7 +806,7 @@ pub fn rows(app: &mut SolveApp, ui: &mut egui::Ui, k: &mut Mo, inputs: &mut [Sel
}
}
ui.menu_button("Face Appearance", |ui| {
ui.label("Semantic faces share their appearance across instances.");
ui.label(crate::i18n::tr_label("Semantic faces share their appearance across instances."));
let state = app.session.model.state();
for body in &state.bodies {
if body.body.is_mesh() {