Add complete Italian UI localization (#1941)
* Add complete Italian UI localization Translate all 1509 English catalog entries originally, register Italiano, guard complete coverage and exercise Italian labels and UI rendering. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> * i18n: Italian is a partial catalog it.json lacks 19 messages main has gained since this branch began, so as a complete catalog it would fail every_complete_catalog_carries_every_english_message. Like the other community languages, Italian is now partial: its gaps fall back to English and new labels don't require an Italian string. The docs line goes back to main's wording, with Italian among the partial catalogs. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01LGeCa5jWWdroMWvXxN3LLM --------- Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Co-authored-by: Ben Herbruck <bherbruck@herbrucks.com> Co-authored-by: bherbruck <brennen.herbruck@gmail.com> Co-authored-by: jyviko <2501648+jyviko@users.noreply.github.com> Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
5 files changed
+1595
-5
No files matched your search
@@ -93,6 +93,7 @@ Editable drawing code, native projects and shipped exports are collected under `
|
||||
| assets/locales/es.json | jawler | Spanish (Spain) translation of the English catalog, contributed upstream | MIT OR Apache-2.0 |
|
||||
| assets/locales/fr.json | rlartot | French translation of the English catalog, contributed upstream | MIT OR Apache-2.0 |
|
||||
| assets/locales/gl.json | Pablo López (pablopeza) | Galician translation of the English catalog, contributed upstream | MIT OR Apache-2.0 |
|
||||
| assets/locales/it.json | SolidCraft contributors | Original Italian translation of SolidCraft's English catalog; no commercial CAD text used | MIT OR Apache-2.0 |
|
||||
| assets/locales/ja.json | SolidCraft contributors | Original SolidCraft resource data or drawing code, collected without redesign | MIT OR Apache-2.0 |
|
||||
| assets/locales/ko.json | SolidCraft contributors | Original SolidCraft resource data or drawing code, collected without redesign | MIT OR Apache-2.0 |
|
||||
| assets/locales/ru.json | Alex Pro (del000) | Russian translation of the English catalog, contributed upstream | MIT OR Apache-2.0 |
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
@@ -37,6 +37,7 @@ static GERMAN: Catalog = Catalog::new("de", "Deutsch", include_str!(concat!(env!
|
||||
static SPANISH: Catalog = Catalog::new("es", "Español (España)", include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../../assets/locales/es.json")));
|
||||
static FRENCH: Catalog = Catalog::new("fr", "Français", include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../../assets/locales/fr.json")));
|
||||
static GALICIAN: Catalog = Catalog::new("gl", "Galego", include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../../assets/locales/gl.json")));
|
||||
static ITALIAN: Catalog = Catalog::new("it", "Italiano", include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../../assets/locales/it.json")));
|
||||
static JAPANESE: Catalog = Catalog::new("ja", "日本語", include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../../assets/locales/ja.json")));
|
||||
static KOREAN: Catalog = Catalog::new("ko", "한국어", include_str!(concat!(env!("CARGO_MANIFEST_DIR"), "/../../assets/locales/ko.json")));
|
||||
static PORTUGUESE_BR: Catalog =
|
||||
@@ -55,6 +56,7 @@ pub const LOCALES: &[&Catalog] = &[
|
||||
&SPANISH,
|
||||
&FRENCH,
|
||||
&GALICIAN,
|
||||
&ITALIAN,
|
||||
&JAPANESE,
|
||||
&KOREAN,
|
||||
&PORTUGUESE_BR,
|
||||
@@ -238,8 +240,8 @@ mod tests {
|
||||
ENGLISH.messages().values().map(String::as_str).collect()
|
||||
}
|
||||
|
||||
/// Catalogs delivered complete. English is the source catalog; Japanese was completed
|
||||
/// upstream, Chinese and Czech land complete here. German, Korean, Russian, French and Ukrainian
|
||||
/// Catalogs delivered complete. English is the source catalog; Czech, Italian, Japanese and Chinese
|
||||
/// are complete. German, Korean, Russian, French and Ukrainian
|
||||
/// are partial (German and Korean predate the coverage guards; Russian, French and Ukrainian
|
||||
/// are kept partial so a new label doesn't need more translations), so their gaps fall back
|
||||
/// to English and are reported by `cargo xtask i18n` without failing the build, while
|
||||
@@ -392,6 +394,39 @@ mod tests {
|
||||
assert_eq!(Locale(&PARTIAL).text("ui.extrude"), "Extrude");
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn italian_labels_templates_and_names_preserve_technical_values() {
|
||||
assert!(is_supported("it"));
|
||||
let it = Locale::for_language("it");
|
||||
assert_eq!(it.name(), "Italiano");
|
||||
for (source, expected) in [
|
||||
("Sketch", "Schizzo"),
|
||||
("Extrude", "Estrusione"),
|
||||
("Fillet", "Raccordo"),
|
||||
("Chamfer", "Smusso"),
|
||||
("Body", "Corpo"),
|
||||
("New Component", "Nuovo componente"),
|
||||
("CONSTRAINTS", "VINCOLI"),
|
||||
("Draft", "Sformo"),
|
||||
("Counterbore", "Lamatura"),
|
||||
("Countersink", "Svasatura"),
|
||||
] {
|
||||
assert_eq!(it.label(source), expected, "{source}");
|
||||
}
|
||||
assert_eq!(it.dynamic("Sketch12"), "Schizzo12");
|
||||
assert_eq!(it.dynamic("Body2"), "Corpo2");
|
||||
assert_eq!(it.dynamic("Component3"), "Componente3");
|
||||
assert_eq!(it.dynamic("Units: mm"), "Unità: mm");
|
||||
assert_eq!(it.dynamic("4 degrees of freedom"), "4 gradi di libertà");
|
||||
assert_eq!(it.given_name("Fillet"), "Fillet");
|
||||
assert_eq!(it.label("solid.extrude"), "solid.extrude");
|
||||
assert_eq!(it.format("document.save_changes", &[("name", "Staffa {v2}")]), "Salvare le modifiche a Staffa {v2}?");
|
||||
assert_eq!(
|
||||
it.format("ui.command_palette_hint", &[("example", "solid.extrude {\"distance\": 20}")]),
|
||||
"Digita un comando, ad es. solid.extrude {\"distance\": 20} — oppure premi S per cercare"
|
||||
);
|
||||
}
|
||||
|
||||
/// `label()`'s id fallback (an argument that matches no other entry's English text is
|
||||
/// looked up as an id directly) is how the Sketch Palette reaches `ui.palette_profile` and
|
||||
/// `ui.palette_points` without colliding with "Profile" / "Points" elsewhere (see the
|
||||
|
||||
@@ -21,6 +21,24 @@ fn japanese_dialog_keeps_english_scenario_handles() {
|
||||
assert!(h.widget("Cancel").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn italian_dialog_keeps_english_scenario_handles() {
|
||||
let mut h = Harness::new();
|
||||
h.app.preferences.language = "it".into();
|
||||
h.app.home.open = false;
|
||||
h.call("ui.start", json!({"command":"sketch.create"}));
|
||||
h.frames(3);
|
||||
assert!(h.widget("Piano").is_some());
|
||||
assert!(h.widget("Annulla").is_some());
|
||||
assert!(!scenario::handles("dialog:Plane").is_empty());
|
||||
assert_eq!(crate::i18n::tr("ui.preferences"), "Preferences");
|
||||
|
||||
h.app.preferences.language = "en".into();
|
||||
h.frames(3);
|
||||
assert!(h.widget("Plane").is_some());
|
||||
assert!(h.widget("Cancel").is_some());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn sketch_palette_profile_and_points_rows_show_their_own_translation() {
|
||||
// ui.palette_profile / ui.palette_points are reached by id, not by the usual English-text
|
||||
@@ -67,6 +85,7 @@ fn window_chrome_renders_in_the_active_language() {
|
||||
("ko", "브라우저", "선택 필터", "면"),
|
||||
("ru", "БРАУЗЕР", "Фильтр выделения", "Грани"),
|
||||
("fr", "NAVIGATEUR", "Filtre de sélection", "Faces"),
|
||||
("it", "STRUTTURA", "Filtro di selezione", "Facce"),
|
||||
("uk", "БРАУЗЕР", "Фільтр виділення", "Грані"),
|
||||
] {
|
||||
let mut h = Harness::new();
|
||||
@@ -135,6 +154,22 @@ fn home_page_renders_in_the_active_language() {
|
||||
}
|
||||
}
|
||||
let cases = [
|
||||
(
|
||||
"it",
|
||||
[
|
||||
"Nuovo progetto",
|
||||
"Apri…",
|
||||
"Documentazione",
|
||||
"Segnala un problema",
|
||||
"Novità",
|
||||
"Scorciatoie da tastiera",
|
||||
"Preferenze",
|
||||
"Recenti",
|
||||
"Esempi",
|
||||
"Piastra di esempio",
|
||||
],
|
||||
"non presente\nAperto 2 h fa",
|
||||
),
|
||||
(
|
||||
"ja",
|
||||
[
|
||||
|
||||
+11
-3
@@ -1,7 +1,7 @@
|
||||
# UI localization
|
||||
|
||||
SolidCraft embeds its translations and works offline. English, Japanese, German, French, Galician, Korean,
|
||||
Brazilian Portuguese, Russian, Ukrainian, Turkish and Chinese are currently registered in `crates/ui-egui/src/i18n.rs`. Adding a language requires an
|
||||
SolidCraft embeds its translations and works offline. English, Czech, German, Spanish, French, Galician, Italian,
|
||||
Japanese, Korean, Brazilian Portuguese, Russian, Turkish, Ukrainian and Chinese are currently registered in `crates/ui-egui/src/i18n.rs`. Adding a language requires an
|
||||
embedded catalog and one registration there; the preferences selector and validation use the same
|
||||
registry.
|
||||
|
||||
@@ -31,7 +31,7 @@ that looks untranslated. Two guards catch that in the build:
|
||||
|
||||
- `every_complete_catalog_carries_every_english_message` — adding a key to `en.json`
|
||||
without giving it to a complete catalog fails the tests. English is the source catalog,
|
||||
Japanese and Chinese are delivered complete; German, Galician, Korean, Brazilian Portuguese, Russian, French, Ukrainian and
|
||||
Japanese and Chinese are delivered complete; German, Spanish, Galician, Italian, Korean, Brazilian Portuguese, Russian, French, Ukrainian and
|
||||
Turkish are partial — their gaps fall back to English and are reported by `cargo xtask i18n` without
|
||||
failing the build. A new label needs en, ja, zh, de and ko; Russian, French and Ukrainian may
|
||||
follow later.
|
||||
@@ -59,6 +59,14 @@ claim it, or the English-text lookup would silently pick one.
|
||||
|
||||
## Rendering and coverage
|
||||
|
||||
The Italian catalog uses original translations of SolidCraft's English messages, not text
|
||||
extracted from commercial CAD software. Its core terminology is Schizzo (Sketch),
|
||||
Estrusione (Extrude), Raccordo (Fillet), Smusso (Chamfer), Corpo (Body), Componente
|
||||
(Component) and Vincolo (Constraint). Draft geometry is Sformo, while a report draft
|
||||
is Bozza; Counterbore is Lamatura and Countersink is Svasatura. Established technical
|
||||
terms such as Loft, Sweep, Spline and Offset remain unchanged. Command IDs, shortcuts,
|
||||
file formats, units and user-provided names are not translated.
|
||||
|
||||
One immutable `Locale` type handles all translations. Table widgets without an app reference
|
||||
use a render scope that restores the previous locale when it exits, including nested renders.
|
||||
Standalone translated panels enter the same scope. Measure rendered text to size custom
|
||||
|
||||
Reference in new issue
Block a user