mirror of
https://github.com/storytold/wordcraft.git
synced 2026-10-19 02:10:15 -05:00
i18n(hu): complete the Hungarian catalog again (#842)
* i18n: add Hungarian (hu) interface translation
- crates/ui-egui/src/i18n/hu.tsv: complete catalog, all 1,572 keys of
es.tsv in the same order, written clean-room from the plain meaning
of the English labels; placeholders, escapes and trailing ellipses
kept. Commands are nouns, messages use the informal second person,
and only the first word of a label is capitalised. A noun after a
number stays singular in Hungarian, so the context-free format needs
no plural forms.
- LANGUAGES gains `hu` (Magyar); `hu`, `hu-HU` and `hu_HU.UTF-8`
resolve to it.
- The Font dialog's preview sample is "AaBbYyZz ŐőŰű", so All Caps
shows the double acute capitals.
- Tests: locale resolution and saved preference, key parity with the
Spanish catalog, sample translations, count wording, the sample's
capitals and Hungarian letters in the bundled interface fonts.
- Docs: new localization-hu.md (conventions, terminology, scope);
README, ROADMAP, localization-parity and control-protocol list the
new language; ATTRIBUTION row for hu.tsv.
* i18n(hu): built-in style names, equation gallery and citation styles
- hu.tsv now carries every key of the Russian catalog: built-in style
names (Normal, No Spacing, Subtitle, TOC {n}…), the equation gallery
and structure labels, paper sizes, watermarks and the Backstage
greetings, plus the citation style names (1,946 entries).
- The interface audit (untranslated_interface_text) checks Hungarian
alongside Russian and reports every language's gaps in one run.
- Tests: Hungarian keys cover the Russian catalog; built-in style
names and numbered style templates show in Hungarian.
- Docs: entry counts and scope in localization-hu, localization-parity
and ROADMAP.
* Review fixes for #731: Hungarian stays a partial catalog
- The i18n audit requires completeness from Russian only again: hu.tsv lacks ~280 strings of the
dialogs that landed since (Compare Documents, Math AutoCorrect, …), so it can't claim to be
complete. The catalog test no longer asserts it holds every Russian/Spanish key.
- 43 Hungarian rows for tab and command labels that reached main since (charts, content controls,
Developer tab, templates and the styles organizer, WordArt), which every_tab_and_command_is_translated
requires.
- Docs say partial, with the entry count (1,989); localization-parity's header keeps its quote
marker and the #505 note.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Review fixes for #731: Hungarian rows for the Outlining tab
24 rows for Outline view's tab and commands, which landed on main meanwhile; 2,013 entries.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* Review fixes for #731: ROADMAP header keeps main's SmartArt note
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
* i18n(hu): complete the Hungarian catalog again
- hu.tsv: 374 new rows for the strings that reached main while #731 was
in review (Compare Documents, Restrict Editing, Math AutoCorrect,
charts, SmartArt, the Options sections, the print page and more).
The catalog now holds every key of ru.tsv again: 2,397 entries.
- The completeness checks are back: the interface audit requires
Hungarian alongside Russian, and the catalog test asserts hu.tsv holds
every key of ru.tsv and es.tsv. The docs describe a complete catalog.
- Seven review rows follow the catalog's existing patterns: Text Pane
(Szöveg panel, like the other panes), Design Mode (Tervezőmód, one
compound), Picture and Date Picker Content Control (clearer compounds),
Promote to Heading 1 / Demote to Body Text (style name after a colon,
no case ending) and Reset Graphic (Ábra visszaállítása, shorter).
* Hungarian: translate interface strings added on main since this PR
Adds the 10 strings main gained with Polish proofing (spelling and grammar
messages, Do Not Check Spelling or Grammar, comment/browse buttons), so
hu.tsv again covers every key of the other catalogs (2,419 entries), and
drops the stale "Wildcards (regex)" row; updates the documented counts.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
---------
Co-authored-by: Brandon Thomas <echelon@gmail.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Brandon Thomas <brandon@storyteller.ai>
This commit is contained in:
10 files changed
+2648
-22
No files matched your search
@@ -70,4 +70,5 @@ Generated-in-code art is original and has no file to list: the UI icon set (`cra
|
||||
| `crates/ui-egui/src/i18n/de.tsv` | @arekown with Kimi | Original translation from the English interface labels in this repository; no other product localisation copied | MIT OR Apache-2.0 | German interface catalog |
|
||||
| `crates/ui-egui/src/i18n/ru.tsv` | Dmitrii Khlapov with Claude | Original translation from the English interface labels in this repository; no other product localisation copied | MIT OR Apache-2.0 | Russian interface catalog; reviewed by a native speaker |
|
||||
| `crates/ui-egui/src/i18n/tr.tsv` | @PbyLoyth with Codex and Claude Code | Original translation from the English interface labels in this repository; no other product localisation copied | MIT OR Apache-2.0 | Turkish interface catalog |
|
||||
| `crates/ui-egui/src/i18n/hu.tsv` | @Skaywalker | Original translation from the English interface labels in this repository; no other product localisation copied | MIT OR Apache-2.0 | Hungarian interface catalog |
|
||||
| `crates/ui-egui/src/i18n/fr.tsv` | @pechnikov2026-star | Original translation from the English interface labels in this repository; no other product localisation copied | MIT OR Apache-2.0 | French interface catalog |
|
||||
@@ -117,7 +117,7 @@ Every screenshot below is WordCraft itself, rendered offscreen by its own UI tes
|
||||
| **References** | Table of contents, footnotes and endnotes, citations and bibliography (APA, MLA, Chicago, IEEE), captions, table of figures, cross-references, index, table of authorities |
|
||||
| **Review** | Spelling and grammar with suggestions (English and Polish, by each run's language), thesaurus, word count, comments in margin balloons or a pane, track changes, accept/reject, compare documents, restrict editing, accessibility checker, document inspector |
|
||||
| **Mailings** | Mail merge from CSV, merge fields, address block, greeting line, rules, preview, finish to a document; envelopes and labels |
|
||||
| **View** | Print layout, web layout, draft, read mode, focus, zoom, one/multiple pages, page width, Navigation pane, rulers, gridlines, dark mode; interface in English, 简体中文, 繁體中文, 日本語, Português (Brasil), Español, Українська, Српски / Srpski, Eesti, Türkçe, Русский, Italiano, Deutsch, Polski, Čeština or Français (follows the system language by default) |
|
||||
| **View** | Print layout, web layout, draft, read mode, focus, zoom, one/multiple pages, page width, Navigation pane, rulers, gridlines, dark mode; interface in English, 简体中文, 繁體中文, 日本語, Português (Brasil), Español, Українська, Српски / Srpski, Eesti, Türkçe, Русский, Italiano, Deutsch, Polski, Čeština, Magyar or Français (follows the system language by default) |
|
||||
| **Files** | .docx read/write (opens in Word), Word 97-2003 .doc import, PDF export, .odt, .rtf, .html, .md, .tex, .txt import/export, page images |
|
||||
|
||||
The honest picture, area by area, is in [ROADMAP.md](ROADMAP.md), the
|
||||
|
||||
+6
-3
@@ -2,7 +2,7 @@
|
||||
|
||||
**Stage: alpha** · next: beta, ~15 points (60% → 75% ready for real work) and ~150–230 h away
|
||||
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-11 · **Change:** trivial (Reading Mode completed; previously trivial: Insert › SmartArt landed, #497: catalog 429/451 → 437/458 (95.4%); previously trivial: Turkish interface landed; previously trivial: formatting revisions landed, #41; previously trivial: Draw tab ink, #307, and Draw Table and Eraser, #303, landed: catalog 402/434; previously minor: readiness table with hours per audience; full number back to the additive weighted sum, 60%; mainstream and essentials numbers added; alpha gate checked; previously major: full re-measure against Word for Mac 16.113.4; restructured to the craftrules progress-docs standard) · **Target:** Microsoft Word (Microsoft 365) for Mac 16.113.4
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-11 · **Change:** trivial (Hungarian interface landed; previously minor: Polish interface and Polish proofing; previously trivial: table borders and the resize handle drag on the page, #217; previously trivial: Turkish interface landed; previously trivial: formatting revisions landed, #41; previously trivial: Draw tab ink, #307, and Draw Table and Eraser, #303, landed: catalog 402/434; previously minor: readiness table with hours per audience; full number back to the additive weighted sum, 60%; mainstream and essentials numbers added; alpha gate checked; previously major: full re-measure against Word for Mac 16.113.4; restructured to the craftrules progress-docs standard) · **Target:** Microsoft Word (Microsoft 365) for Mac 16.113.4
|
||||
|
||||
WordCraft aims for complete parity with Microsoft Word, then goes further on speed, openness and
|
||||
agent control. This page is the summary; the assessment is
|
||||
@@ -102,7 +102,7 @@ Weights and evidence per area: [docs/target-app-parity.md](docs/target-app-parit
|
||||
| Spanish | es | partial | ~95% |
|
||||
| Hindi | hi | none | 0% |
|
||||
| Arabic | ar | none (document shaping and bidi work; no mirrored UI) | 0% |
|
||||
| French | fr | none | 0% |
|
||||
| French | fr | partial (interface) | ~95% |
|
||||
| Portuguese | pt-br (pt-PT none) | partial | ~95% |
|
||||
| Indonesian | id | none | 0% |
|
||||
| Japanese | ja | partial | ~95% |
|
||||
@@ -111,7 +111,8 @@ Weights and evidence per area: [docs/target-app-parity.md](docs/target-app-parit
|
||||
| Vietnamese | vi | none | 0% |
|
||||
|
||||
Also shipped: Traditional Chinese (`zh-hant`), Ukrainian (`uk`), Serbian (`sr`, `sr-latn`, #250), Russian (`ru`) and Polish (`pl`), all partial (~95%). Estonian (`et`), Turkish (`tr`), Italian (`it`, #594) and Czech (`cs`) now have complete interface catalogs with
|
||||
system-locale selection and a saved language choice (Italian also has 51 strings none of the others had yet); Estonian, Turkish, Italian and Czech proofing are not included.
|
||||
system-locale selection and a saved language choice (Italian also has 51 strings none of the others had yet); Estonian, Turkish, Italian and Czech proofing are not included. Hungarian (`hu`) has a
|
||||
complete 2,419-entry catalog, also without proofing.
|
||||
Proofing: English and Polish (spelling, grammar, hyphenation), chosen per run from its language. Word ships
|
||||
30 interface languages and proofing for ~50. Detail: [docs/localization-parity.md](docs/localization-parity.md).
|
||||
|
||||
@@ -193,6 +194,7 @@ Ranked, to beta (detail and remaining milestones in [docs/roadmap.md](docs/roadm
|
||||
| 2026-10-12 | Native saves use exclusively created sibling temporary files, synchronize before replacement and clean up on failure; existing temporary-name files/links and original files on failed saves are protected. Synthetic CLI and focused tests on macOS; no new Word parity or readiness claim. |
|
||||
| 2026-10-11 | Field codes like Word's field keys (#339): show codes (Alt+F9, Shift+F9), edit, unlink, lock and step through fields |
|
||||
| 2026-10-11 | Word's common keyboard shortcuts (#330): 101 → 125 of ~250 |
|
||||
| 2026-10-11 | Hungarian (`hu`) interface: all 2,419 catalog entries, built-in style names translated, `hu-HU` system locales and a saved language choice; locale, catalog and bundled-font tests; no Hungarian proofing resources |
|
||||
| 2026-10-11 | Turkish (`tr`) interface: all 1,307 catalog entries, `tr-TR`/`tr-CY` system locales and a saved language choice; command search keeps Turkish dotted and dotless I apart (`italik` finds İtalik); locale, catalog, search and bundled-font tests; no Turkish proofing resources |
|
||||
| 2026-10-11 | Italian (`it`) interface (#594): 2,399 entries, feature names as Italian Word users know them, locale and saved-preference tests, bundled-font checks; no Italian proofing resources |
|
||||
| 2026-10-11 | Citations and bibliography in all 12 of Word's styles: Harvard, ISO 690 (author-date and numerical), Turabian, GB/T 7714, GOST (name and title sort) and SIST02 join APA, MLA, Chicago and IEEE; numbered styles count in order of first citation (#383) |
|
||||
@@ -254,6 +256,7 @@ Ranked, to beta (detail and remaining milestones in [docs/roadmap.md](docs/roadm
|
||||
| 2026-10-12 | trivial | Native saves protect existing temporary-name entries and originals on pre-replacement failure; synthetic macOS evidence, explicit durability/platform limits; readiness unchanged |
|
||||
| 2026-10-11 | trivial | Word's common keyboard shortcuts (#330): 125 of ~250 |
|
||||
| 2026-10-11 | trivial | Collapsed duplicate rows left by parallel merges |
|
||||
| 2026-10-11 | trivial | Hungarian interface (`hu`): progress log and shipped languages |
|
||||
| 2026-10-11 | trivial | Turkish interface (`tr`): progress log and shipped languages |
|
||||
| 2026-10-11 | trivial | Progress log: eight more bibliography styles (#383) |
|
||||
| 2026-10-10 | trivial | Progress log: Draw tab ink (#307) |
|
||||
|
||||
@@ -311,12 +311,13 @@ fn untranslated_interface_text() {
|
||||
report.push_str(&format!("{:?} [{}]\n", pseudo::unmarked(text), states.join(", ")));
|
||||
}
|
||||
assert!(found.is_empty(), "{} interface texts skip translation (wrap them in tl!):\n{report}", found.len());
|
||||
russian_has_every_string_the_interface_looked_up(pseudo::looked_up());
|
||||
complete_catalogs_have_every_string_the_interface_looked_up(pseudo::looked_up());
|
||||
}
|
||||
|
||||
/// Russian covers everything the audit saw translated, plus the equation gallery's labels (shown
|
||||
/// in menus the audit doesn't open one by one). Numbered style names go through a template.
|
||||
fn russian_has_every_string_the_interface_looked_up(mut keys: std::collections::BTreeSet<String>) {
|
||||
/// Russian and Hungarian cover everything the audit saw translated, plus the equation gallery's
|
||||
/// labels (shown in menus the audit doesn't open one by one). Numbered style names go through a
|
||||
/// template.
|
||||
fn complete_catalogs_have_every_string_the_interface_looked_up(mut keys: std::collections::BTreeSet<String>) {
|
||||
use wordcraft_engine::math_gallery::{BUILT_INS, STRUCTURES, SYMBOL_SETS};
|
||||
keys.extend(BUILT_INS.iter().map(|(_, label, _)| label.to_string()));
|
||||
keys.extend(SYMBOL_SETS.iter().map(|(name, _)| name.to_string()));
|
||||
@@ -327,10 +328,16 @@ fn russian_has_every_string_the_interface_looked_up(mut keys: std::collections::
|
||||
keys.extend(templates.iter().map(|t| t.label.to_string()));
|
||||
}
|
||||
}
|
||||
let ru = super::Lang::from_code("ru").unwrap_or(super::Lang::EN);
|
||||
let numbered = |s: &str| ["Heading ", "TOC "].iter().any(|p| s.strip_prefix(p).is_some_and(|n| n.chars().all(|c| c.is_ascii_digit())));
|
||||
// Names that read the same in Russian.
|
||||
// Names that read the same in these languages.
|
||||
let same = |s: &str| matches!(s, "LaTeX" | "LaTeX (*.tex)" | "Unicode" | "I. II. III." | "i. ii. iii.");
|
||||
let missing: Vec<String> = keys.into_iter().filter(|s| english_words(s) && !super::has(ru, s) && !numbered(s) && !same(s)).collect();
|
||||
assert!(missing.is_empty(), "{} strings have no Russian entry:\n{missing:#?}", missing.len());
|
||||
let mut report = String::new();
|
||||
for code in ["ru", "hu"] {
|
||||
let lang = super::Lang::from_code(code).unwrap_or(super::Lang::EN);
|
||||
let missing: Vec<&String> = keys.iter().filter(|s| english_words(s) && !super::has(lang, s) && !numbered(s) && !same(s)).collect();
|
||||
if !missing.is_empty() {
|
||||
report.push_str(&format!("{} strings have no {code} entry:\n{missing:#?}\n", missing.len()));
|
||||
}
|
||||
}
|
||||
assert!(report.is_empty(), "{report}");
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
@@ -52,7 +52,7 @@ pub struct LangInfo {
|
||||
}
|
||||
|
||||
/// The registry. English first: it is the fallback and the source language.
|
||||
pub static LANGUAGES: [LangInfo; 17] = [
|
||||
pub static LANGUAGES: [LangInfo; 18] = [
|
||||
LangInfo { code: "en", name: "English", source: "", prefer_hans: false, editing_lang: None, catalog: OnceLock::new() },
|
||||
// Simplified Chinese; `zh`, `zh-CN`, `zh-SG` and `zh-Hans-*` resolve here (see `candidates`).
|
||||
LangInfo {
|
||||
@@ -121,6 +121,8 @@ pub static LANGUAGES: [LangInfo; 17] = [
|
||||
LangInfo { code: "tr", name: "Türkçe", source: include_str!("tr.tsv"), prefer_hans: false, editing_lang: None, catalog: OnceLock::new() },
|
||||
// Italian; `it-IT`, `it-CH` and `it-*` resolve here.
|
||||
LangInfo { code: "it", name: "Italiano", source: include_str!("it.tsv"), prefer_hans: false, editing_lang: None, catalog: OnceLock::new() },
|
||||
// Hungarian; `hu`, `hu-HU` and `hu_HU.UTF-8` resolve here.
|
||||
LangInfo { code: "hu", name: "Magyar", source: include_str!("hu.tsv"), prefer_hans: false, editing_lang: None, catalog: OnceLock::new() },
|
||||
// French; `fr`, `fr-FR`, `fr_CA` and other regions resolve here.
|
||||
LangInfo { code: "fr", name: "Français", source: include_str!("fr.tsv"), prefer_hans: false, editing_lang: None, catalog: OnceLock::new() },
|
||||
];
|
||||
|
||||
@@ -753,6 +753,87 @@ fn bundled_interface_fonts_cover_turkish_without_system_fallbacks() {
|
||||
assert!(!lang("tr").uses_cjk());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hungarian_locales_and_saved_preference_work_without_changing_the_document() {
|
||||
let hu = lang("hu");
|
||||
for tag in ["hu", "hu-HU", "hu_HU.UTF-8", "HU_hu.UTF-8@euro", "hu-Latn-HU"] {
|
||||
assert_eq!(lang_from_tag(tag), Some(hu), "{tag}");
|
||||
}
|
||||
assert_eq!(first_supported(["sv-SE", "hu-HU", "en-US"]), Some(hu));
|
||||
assert_eq!(normalize_pref("HU"), Some("hu"));
|
||||
let mut app = crate::WordApp::new(wordcraft_engine::Session::new(wordcraft_engine::sample::sample_document()), Default::default());
|
||||
let before = serde_json::to_value(&app.session.doc).unwrap();
|
||||
let result = app.run("ui.language", serde_json::json!({"value": "hu"})).unwrap();
|
||||
assert_eq!(result["effective"], "hu");
|
||||
assert!(result["available"].as_array().unwrap().iter().any(|l| l["code"] == "hu" && l["name"] == "Magyar"));
|
||||
assert_eq!(serde_json::to_value(&app.session.doc).unwrap(), before);
|
||||
let saved = serde_json::to_string(&app.ui).unwrap();
|
||||
let restored: crate::UiState = serde_json::from_str(&saved).unwrap();
|
||||
assert_eq!(Lang::from_pref(&restored.language), hu);
|
||||
app.run("ui.language", serde_json::json!({"value": "auto"})).unwrap();
|
||||
assert_eq!(app.ui.language, AUTO);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn hungarian_covers_the_entire_existing_interface_catalog() {
|
||||
use std::collections::HashSet;
|
||||
let keys = |source| parse_entries(source).0.into_iter().map(|e| e.source).collect::<HashSet<_>>();
|
||||
// Every key of the most complete catalog: built-in style names, equation gallery labels, paper
|
||||
// sizes and watermarks included.
|
||||
assert!(keys(lang("hu").0.source).is_superset(&keys(lang("ru").0.source)));
|
||||
assert!(keys(lang("hu").0.source).is_superset(&keys(lang("es").0.source)));
|
||||
let hu = lang("hu");
|
||||
for (source, expected) in [
|
||||
("Home", "Kezdőlap"),
|
||||
("Font", "Betűtípus"),
|
||||
("Review", "Véleményezés"),
|
||||
("Header", "Élőfej"),
|
||||
("Track Changes", "Változáskövetés"),
|
||||
("Save", "Mentés"),
|
||||
("Redo", "Újra"),
|
||||
("UPPERCASE", "NAGYBETŰS"),
|
||||
("WordCraft", "WordCraft"),
|
||||
("unknown future label", "unknown future label"),
|
||||
] {
|
||||
assert_eq!(super::tr(hu, source), expected);
|
||||
}
|
||||
assert_eq!(fmt(super::tr(hu, "Page {page} of {pages}"), &[("page", "3"), ("pages", "9")]), "Oldal: 3/9");
|
||||
// A noun after a number stays singular in Hungarian, whatever the count.
|
||||
for count in [0, 1, 2, 21, 1000] {
|
||||
let words = count.to_string();
|
||||
assert_eq!(fmt(super::tr(hu, "{words} words"), &[("words", &words)]), format!("{count} szó"));
|
||||
}
|
||||
// The Font dialog uppercases its preview sample for All Caps.
|
||||
assert_eq!(super::tr(hu, "AaBbYyZz").to_uppercase(), "AABBYYZZ ŐŐŰŰ");
|
||||
set_current(hu);
|
||||
// Built-in styles show translated names; numbered families go through their template.
|
||||
for (style, expected) in [("Normal", "Normál"), ("No Spacing", "Nincs térköz"), ("Heading 2", "Címsor 2"), ("TOC 3", "Tartalomjegyzék 3")] {
|
||||
assert_eq!(builtin_style_name(style), expected);
|
||||
}
|
||||
assert_eq!(builtin_style_name("My Own Style"), "My Own Style");
|
||||
assert_eq!(location("Home › Font"), "Kezdőlap › Betűtípus");
|
||||
assert_eq!(prefixed("Undo", "Bold"), "Visszavonás: Félkövér");
|
||||
set_current(Lang::EN);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn bundled_interface_fonts_cover_hungarian_without_system_fallbacks() {
|
||||
let db = wordcraft_fonts::FontDb::with_font_dirs(Vec::new());
|
||||
let (entries, errors) = parse_entries(lang("hu").0.source);
|
||||
assert!(errors.is_empty());
|
||||
let extra = "ÁáÉéÍíÓóÖöŐőÚúÜüŰű";
|
||||
let chars: std::collections::HashSet<char> =
|
||||
entries.iter().flat_map(|e| e.translation.chars()).filter(|c| extra.contains(*c)).chain(extra.chars()).collect();
|
||||
for (family, style) in [("Inter", "Regular"), ("Inter", "Medium"), ("Inter", "SemiBold"), ("JetBrains Mono", "Regular")] {
|
||||
let face = db.face(family, style);
|
||||
assert_eq!(face.family, family, "must use the bundled interface face");
|
||||
for ch in &chars {
|
||||
assert_ne!(face.glyph_for(*ch), 0, "{family} {style} lacks {ch}");
|
||||
}
|
||||
}
|
||||
assert!(!lang("hu").uses_cjk());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn french_locales_and_saved_preference_work_without_changing_the_document() {
|
||||
let fr = lang("fr");
|
||||
@@ -833,9 +914,9 @@ fn polish_covers_every_key_of_every_other_catalog() {
|
||||
use std::collections::HashSet;
|
||||
let keys = |source| parse_entries(source).0.into_iter().map(|e| e.source).collect::<HashSet<_>>();
|
||||
let polish = keys(lang("pl").0.source);
|
||||
// Russian and Italian also translate the built-in style names and the equation gallery,
|
||||
// Russian, Italian and Hungarian also translate the built-in style names and the equation gallery,
|
||||
// which the others don't yet; Polish matches every other catalog.
|
||||
for other in Lang::all().filter(|l| *l != Lang::EN && !matches!(l.code(), "pl" | "ru" | "it")) {
|
||||
for other in Lang::all().filter(|l| *l != Lang::EN && !matches!(l.code(), "pl" | "ru" | "it" | "hu")) {
|
||||
let mut missing: Vec<String> = keys(other.0.source).difference(&polish).cloned().collect();
|
||||
missing.sort();
|
||||
assert!(missing.is_empty(), "pl lacks {}'s {missing:?}", other.code());
|
||||
|
||||
@@ -50,7 +50,7 @@ and set `WORDCRAFT_CONTROL_KEY` to that app's key.
|
||||
|
||||
| Method | Params | Result |
|
||||
|---|---|---|
|
||||
| `engine.execute` | `command`, `params` | the command's result (any id from `engine.commands`, including UI commands `ui.tab`, `ui.dialog`, `ui.backstage`, `ui.zotero.*` (see `docs/zotero.md`), `ui.language` (`{"value": "auto"|"en"|"zh-hans"|"zh-hant"|"ja"|"pt-br"|"es"|"uk"|"sr"|"sr-latn"|"et"|"tr"|"ru"|"pl"|"de"|"it"|"cs"|"fr"}`), `ui.theme` (`{"value": "system"|"light"|"dark"}`; `system` follows the OS appearance, light when it reports none), `ui.interfaceSize` (`{"percent": 80–200}`, clamped; no value reads it; scales the interface on top of the system display scale, document zoom stays `view.zoom`), `ui.animations` (`{"value": "system"|"on"|"off"}`; no value reads it; `system` follows the system's animation setting, which the desktop app reads on Windows, macOS, Linux and the BSDs and the web app from `prefers-reduced-motion`, and means on where the system doesn't say; the result's `enabled` is what the setting comes to and `system` what the system reports, `null` when it doesn't say), `ui.fileBrowser` (desktop: `{"purpose": "document"|"picture"|"recipients"|"save"}` opens WordCraft's own file browser, for when the system file dialog doesn't show up, #576), `ui.caretAnimation` (`{"value": true|false}`; no value reads it; off, the caret jumps and blinks on and off instead of gliding and fading)…) |
|
||||
| `engine.execute` | `command`, `params` | the command's result (any id from `engine.commands`, including UI commands `ui.tab`, `ui.dialog`, `ui.backstage`, `ui.zotero.*` (see `docs/zotero.md`), `ui.language` (`{"value": "auto"|"en"|"zh-hans"|"zh-hant"|"ja"|"pt-br"|"es"|"uk"|"sr"|"sr-latn"|"et"|"tr"|"ru"|"pl"|"de"|"it"|"cs"|"hu"|"fr"}`), `ui.theme` (`{"value": "system"|"light"|"dark"}`; `system` follows the OS appearance, light when it reports none), `ui.interfaceSize` (`{"percent": 80–200}`, clamped; no value reads it; scales the interface on top of the system display scale, document zoom stays `view.zoom`), `ui.animations` (`{"value": "system"|"on"|"off"}`; no value reads it; `system` follows the system's animation setting, which the desktop app reads on Windows, macOS, Linux and the BSDs and the web app from `prefers-reduced-motion`, and means on where the system doesn't say; the result's `enabled` is what the setting comes to and `system` what the system reports, `null` when it doesn't say), `ui.fileBrowser` (desktop: `{"purpose": "document"|"picture"|"recipients"|"save"}` opens WordCraft's own file browser, for when the system file dialog doesn't show up, #576), `ui.caretAnimation` (`{"value": true|false}`; no value reads it; off, the caret jumps and blinks on and off instead of gliding and fading)…) |
|
||||
| `engine.commands` | — | every command: id, label, location, shortcut, params, enabled |
|
||||
| `document.inspect` | `text?` | blocks (text, style, runs, lists, tables), parts, sections, selection, pages |
|
||||
| `ui.inspect` | — | UI state, view, dialog, window size, page rects on screen, caret, comment balloons (`balloons`: id + screen rect; `balloon`: the selected one), perf |
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
# Hungarian interface
|
||||
|
||||
> **Last reviewed:** 2026-10-11 · **Last updated:** 2026-10-11 · **Change:** minor (Hungarian interface catalog and regression checks) · **Target:** WordCraft 0.5.0
|
||||
|
||||
Choose **File › Options › Interface language › Magyar**, or follow a Hungarian system display
|
||||
language (`hu-HU`, `hu_HU.UTF-8`). The catalog code is `hu`; `ui.language` with `{"value":"hu"}`
|
||||
selects it explicitly, and `WORDCRAFT_LANGUAGE=hu-HU` does the same for a headless screenshot or a
|
||||
launch while the preference is `auto`. The choice is saved with the other interface settings.
|
||||
Document text, command ids, CLI/MCP/control responses and file paths do not change.
|
||||
|
||||
`crates/ui-egui/src/i18n/hu.tsv` has 2,419 entries: every key of the Russian catalog (built-in style
|
||||
names, equation gallery labels, paper sizes, watermarks and greetings included) plus the citation
|
||||
style names. It is written from the meaning of the English labels; no proprietary translation resources were consulted. The catalog
|
||||
format has no plural forms, and Hungarian doesn't need them: a noun after a number stays singular
|
||||
(`0 szó`, `1 szó`, `21 szó`). Placeholders, `\n` breaks in ribbon labels and dialog ellipses are
|
||||
kept, and strings added later fall back to English until they are translated.
|
||||
|
||||
## Conventions
|
||||
|
||||
- Commands are nouns (`Mentés`, `Másolás`, `Beillesztés`); messages address the user with the
|
||||
informal second person (`Mentsd a dokumentumot`).
|
||||
- Only the first word of a label is capitalised, as Hungarian spelling requires
|
||||
(`Összes módosítás elfogadása`).
|
||||
- Decimal comma (`1,5-es sorköz`) and Hungarian quotation marks („…”).
|
||||
- A placeholder never takes a case ending, because the value is not known when the text is
|
||||
written. The wording puts it after a colon or in parentheses instead
|
||||
(`Undo {action}` → `Visszavonás: {action}`, `Couldn't open {path}: {error}` →
|
||||
`Nem sikerült megnyitni: {path} ({error})`).
|
||||
- Text columns and table columns are different words: `Hasábok` (Layout › Columns, column break)
|
||||
and `Oszlopok` (table rows and columns).
|
||||
|
||||
## Terminology
|
||||
|
||||
| Source | Hungarian |
|
||||
|---|---|
|
||||
| Home / Insert / Draw / Design / Layout | Kezdőlap / Beszúrás / Rajzolás / Tervezés / Elrendezés |
|
||||
| References / Mailings / Review / View / Help | Hivatkozások / Levelezés / Véleményezés / Nézet / Súgó |
|
||||
| Font / Paragraph / Styles | Betűtípus / Bekezdés / Stílusok |
|
||||
| Header / Footer / Heading | Élőfej / Élőláb / Címsor |
|
||||
| Footnote / Endnote / Caption | Lábjegyzet / Végjegyzet / Felirat |
|
||||
| Table of Contents / Index | Tartalomjegyzék / Tárgymutató |
|
||||
| Citation / Bibliography | Forráshivatkozás / Irodalomjegyzék |
|
||||
| Link / Hyperlink | Link |
|
||||
| Track Changes / Accept / Reject | Változáskövetés / Elfogadás / Elutasítás |
|
||||
| Comment / Markup | Megjegyzés / Jelölések |
|
||||
| Mail Merge / Recipients / Merge Field | Körlevél / Címzettek / Egyesítési mező |
|
||||
| Columns (text) / Columns (table) | Hasábok / Oszlopok |
|
||||
| Section / Section Break | Szakasz / Szakasztörés |
|
||||
| Undo / Redo / Repeat | Visszavonás / Újra / Ismétlés |
|
||||
| Undo {action} | Visszavonás: {action} |
|
||||
| Page {page} of {pages} | Oldal: {page}/{pages} |
|
||||
| Ribbon / Pane / Quick Access Toolbar | Menüszalag / Panel / Gyorselérési eszköztár |
|
||||
| Proofing / Word Count | Nyelvi ellenőrzés / Szavak száma |
|
||||
|
||||
Product and format names stay as they are (WordCraft, PDF, DOCX, Markdown, MCP, Zotero). The Font
|
||||
dialog's preview sample is `AaBbYyZz ŐőŰű`, so the All Caps preview shows the Hungarian double
|
||||
acute capitals.
|
||||
|
||||
## Verification and remaining scope
|
||||
|
||||
`cargo test -p wordcraft-ui-egui --lib i18n::tests` covers Hungarian locale tags and preference
|
||||
order, saving and restoring `hu`, unchanged document content, every key of the Russian catalog,
|
||||
built-in style names, placeholders, count wording, the font sample's capitals, English fallback,
|
||||
and the glyphs `ÁáÉéÍíÓóÖöŐőÚúÜüŰű` in the bundled Inter (Regular, Medium, SemiBold) and JetBrains Mono. The shared catalog checks
|
||||
(validation, every tab and command translated) include Hungarian automatically, and the on-demand
|
||||
interface audit (`untranslated_interface_text`) checks Hungarian alongside Russian.
|
||||
|
||||
Spelling, grammar and hyphenation stay English-only: this is an interface translation, not
|
||||
Hungarian proofing. A native-speaker review of the catalog is welcome.
|
||||
|
||||
## Revision history
|
||||
|
||||
| Date | Change | Summary |
|
||||
|---|---|---|
|
||||
| 2026-10-11 | minor | Hungarian catalog (2,419 entries: built-in style names, equation gallery, citation styles), conventions, terminology, scope and regression checks |
|
||||
@@ -1,6 +1,6 @@
|
||||
# Localization parity with Microsoft Word
|
||||
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-11 · **Change:** minor (French interface added; previously minor: Polish interface; Polish proofing — spelling, grammar, hyphenation — and a proofing language per run; previously minor: Turkish interface added; previously major: first version; catalogs measured from `crates/ui-egui/src/i18n`, Word's languages from its bundle listing) · **Target:** Microsoft Word (Microsoft 365) for Mac 16.113.4
|
||||
> **Last reviewed:** 2026-10-10 · **Last updated:** 2026-10-11 · **Change:** minor (Hungarian interface added; previously minor: Polish interface; Polish proofing — spelling, grammar, hyphenation — and a proofing language per run; previously minor: Turkish interface added; previously major: first version; catalogs measured from `crates/ui-egui/src/i18n`, Word's languages from its bundle listing) · **Target:** Microsoft Word (Microsoft 365) for Mac 16.113.4
|
||||
|
||||
Interface languages, script support and proofing per language. How translation works (catalog
|
||||
format, adding a language, clean-room rule): `crates/ui-egui/src/i18n/mod.rs`.
|
||||
@@ -19,9 +19,9 @@ native-speaker review (human).
|
||||
|
||||
## What WordCraft ships (measured)
|
||||
|
||||
- **17 interface languages**: English plus `zh-hans`, `zh-hant`, `ja`, `uk`, `es`, `pt-br`,
|
||||
Serbian `sr`/`sr-latn` (#250), Estonian `et`, Turkish `tr`, Russian `ru`, Italian `it` (#594), German `de` (#574), Polish `pl`, Czech `cs` and French `fr`. Catalogs have 2,021–2,399 entries
|
||||
each; Polish has every key of every other catalog (a test checks it). A test (`every_tab_and_command_is_translated`) enforces that every ribbon tab, command
|
||||
- **18 interface languages**: English plus `zh-hans`, `zh-hant`, `ja`, `uk`, `es`, `pt-br`,
|
||||
Serbian `sr`/`sr-latn` (#250), Estonian `et`, Turkish `tr`, Russian `ru`, Italian `it` (#594), German `de` (#574), Polish `pl`, Czech `cs`, Hungarian `hu` and French `fr`. Catalogs have 2,021–2,419 entries
|
||||
each; Polish has every key of every other catalog except the style names and equation gallery labels only Russian, Italian and Hungarian translate so far (a test checks it). A test (`every_tab_and_command_is_translated`) enforces that every ribbon tab, command
|
||||
label and ribbon location is translated in every language.
|
||||
`pl`, `pl-PL` and `pl_PL.UTF-8` system locales pick Polish automatically.
|
||||
- Of the 675 English strings a scan extracts from `tl!(…)` calls and command labels/locations, each
|
||||
@@ -57,8 +57,8 @@ shared items below.
|
||||
| Korean | ko | 0 | ❌ | Hangul ✅; macOS Korean IME fixes pending (#163, #164) | no | none | 3–5 |
|
||||
| Vietnamese | vi | 0 | ❌ | Latin with stacked diacritics, untested | no | none | 3–4 |
|
||||
|
||||
Other shipped languages: **10** — Traditional Chinese (`zh-hant`), Ukrainian (`uk`), Serbian
|
||||
Cyrillic and Latin (`sr`, `sr-latn`, #250), Estonian (`et`), Turkish (`tr`), Russian (`ru`), Italian (`it`, #594), Polish (`pl`) and Czech (`cs`), all partial.
|
||||
Other shipped languages: **12** — Traditional Chinese (`zh-hant`), Ukrainian (`uk`), Serbian
|
||||
Cyrillic and Latin (`sr`, `sr-latn`, #250), Estonian (`et`), Turkish (`tr`), Russian (`ru`), Italian (`it`, #594), Polish (`pl`), Czech (`cs`), Hungarian (`hu`) and French (`fr`), all partial.
|
||||
Estonian uses the existing fonts, follows `et-EE` system locales, and is available in Options or
|
||||
through `ui.language` with `{"value":"et"}`. Its 1,307 entries cover the existing interface catalog.
|
||||
Estonian spelling, grammar, dates and document templates are not added by the interface catalog.
|
||||
@@ -66,6 +66,9 @@ Turkish works the same way (`tr-TR` and `tr-CY` system locales, `{"value":"tr"}`
|
||||
entries. Command search folds the Turkish dotted and dotless I (`italik` finds İtalik, `YAZI TİPİ`
|
||||
finds Yazı Tipi) while English labels and ASCII command ids keep their usual matching. Turkish
|
||||
proofing is not included; terminology and checks: [`localization-tr.md`](localization-tr.md).
|
||||
Hungarian follows `hu-HU` system locales and `{"value":"hu"}`, with a complete catalog of 2,419 entries: every key of
|
||||
the Russian catalog, built-in style names shown translated, plus the citation style names. Hungarian proofing is not included; terminology and conventions:
|
||||
[`localization-hu.md`](localization-hu.md).
|
||||
|
||||
Polish is the only one besides English with proofing tools, and a Polish interface writes new
|
||||
documents in Polish (`pl-PL`).
|
||||
@@ -111,6 +114,7 @@ allows); all other text is written from the meaning of the English. No Italian p
|
||||
| 2026-10-11 | minor | Font list shows installed fonts by their names in the interface language (宋体 for SimSun in Chinese, Japanese and Korean names likewise) and finds them by either name; a Chinese, Japanese or Korean font is stored as `w:eastAsia` too (#505) |
|
||||
| 2026-10-11 | minor | Chinese/Japanese interface fonts: a test checks every catalog character has a glyph; an installed CJK font follows the embedded faces whenever they miss one; macOS font asset folders searched for PingFang (#486) |
|
||||
| 2026-10-10 | minor | Russian interface (#300; 1,524 entries, built-in style names shown translated; covers everything the interface audit finds) |
|
||||
| 2026-10-11 | minor | Hungarian interface catalog (2,419 entries, built-in style names shown translated; covers everything the interface audit finds), locale selection, saved preference and font coverage checks |
|
||||
| 2026-10-11 | minor | Turkish interface catalog (1,307 entries), locale selection, saved preference, Turkish casing in command search and font coverage checks; catalog sizes re-counted |
|
||||
| 2026-10-11 | trivial | English spelling (#520): our supplement `assets/spelling/en-extra.txt` adds ~220 common modern words the Moby list lacks ("desktop", "download", "email"…) |
|
||||
| 2026-10-10 | minor | Estonian interface catalog, locale selection, saved preference and font coverage checks; count labels put the noun first so they read right at 1 |
|
||||
|
||||
Reference in new issue
Block a user