i18n: missing translations are reported, never a failure (#2729)

A message a catalog lacks, or translates as an empty string, shows in
English and fails nothing:

- build.rs no longer requires every formats catalog to carry the same
  messages, and tr_format! gets a last arm that formats the English
  source, so a message no catalog has builds.
- Coverage tests (every language translates X) and tests of one
  language's exact wording are gone; the language-switching, layout,
  date, placeholder and user-value tests read the catalog's own value
  instead of a hard-coded translation.
- i18n::tests::translation_gaps_report lists, per language, the plain
  and format messages it lacks and its untranslated What's New lines.
  It always passes; cargo xtask ci
  runs it from the test step's binary after the tests.
- catalogs_load checks that every catalog file is a JSON object of
  strings with each key once; it.json named "Dimensions" twice.
This commit is contained in:
aiongg
2026-10-23 16:42:28 -04:00
committed by GitHub
parent d71b83b2bc
commit b264557916
18 changed files with 495 additions and 950 deletions
+3 -2
View File
@@ -46,8 +46,9 @@ ani anglické zdrojové řetězce. Rozložení panelů a seznamu jazyků je beze
## Ověření a revize
Testy `i18n::tests` ověřují registraci příkazu, přepínání přes nabídku a řídicí kanál,
uložení jazyka, pokrytí katalogů, placeholdery, neutrální formulace počtů, datum, čas
a české glyfy. Překladové šablony kontroluje také Rust při sestavení.
uložení jazyka, placeholdery, datum, čas a české glyfy. Překladové šablony kontroluje také
Rust při sestavení. Chybějící překlady se zobrazují anglicky a vypisuje je
`i18n::tests::translation_gaps_report`; žádný test kvůli nim neselže.
Při jazykové korektuře doporučujeme zkontrolovat „asistované třídění“, „sada“ pro Stack,
„bodová barva“, „měkký nátisk“ a názvy kreativních přednastavení.
+3 -3
View File
@@ -29,8 +29,8 @@ cargo test -p lightcraft-ui-egui i18n::tests
LIGHTCRAFT_LANGUAGE=de lightcraft-cli snapshot --demo -o deutsch.png --size 1600x1000
```
Die Tests prüfen Katalogabdeckung, Platzhalter, Sprachwechsel per Menü und Steuerkanal,
Speicherung, Datumsformate, unveränderte Benutzernamen und gerenderte Texte sowie Umlaute
und ß. Ein weiterer Render-Test prüft die Schaltflächenbreiten; der Importtest prüft
Die Tests prüfen Platzhalter, Sprachwechsel per Menü und Steuerkanal, Speicherung,
Datumsformate, unveränderte Benutzernamen und gerenderte Texte sowie Umlaute und ß. Fehlende
Übersetzungen erscheinen auf Englisch; `i18n::tests::translation_gaps_report` listet sie auf. Ein weiterer Render-Test prüft die Schaltflächenbreiten; der Importtest prüft
auch den Sprachwechsel nach der Hintergrundprüfung der Quellen. Akzeptierte Sprachangaben umfassen `de`, `de-DE`, `de_AT.UTF-8` und `de-CH`;
gespeichert wird stets `de`. Weitere Hinweise stehen in [localization.md](localization.md).
+3 -2
View File
@@ -52,8 +52,9 @@ englanniksi. Käännös ei muuta kirjastotietoja eikä englanninkielisiä lähde
## Testaus
`i18n::tests` tarkistaa komennon rekisteröinnin, vaihdon valikosta ja ohjauskanavasta,
kielen tallennuksen, luetteloiden kattavuuden, paikkamerkit, määrämuodot, päivämäärän, ajan ja
suomen kirjaimet. Rust tarkistaa muotoilumallit käännösvaiheessa.
kielen tallennuksen, paikkamerkit, päivämäärän, ajan ja suomen kirjaimet. Rust tarkistaa
muotoilumallit käännösvaiheessa. Puuttuvat käännökset näkyvät englanniksi, ja
`i18n::tests::translation_gaps_report` luettelee ne; mikään testi ei epäonnistu niiden takia.
Kielentarkistuksessa kannattaa katsoa erityisesti: ”Väriluokittelu” (Color Grading),
”Valoalueet / Valkoiset” (Highlights / Whites), ”Näyttövedos” (Soft Proofing),
+4 -4
View File
@@ -19,7 +19,7 @@ not translated. Descriptions for SAM 3 go to the model unchanged.
## Georgian script
Mkhedruli has no upper and lower case: `i18n::upper_first` leaves Georgian letters alone, and the
interface never uses Mtavruli (a test checks the whole catalog). Commands are verbal nouns. Counts
interface never uses Mtavruli. Commands are verbal nouns. Counts
are count-neutral, noun first (`იმპორტირებულია ფოტო: 3`); English plural endings are dropped with
`{:.0}`. Dates read `კვირა, 20.09.2026` (`{weekday}, {day:02}.{month:02}.{year}`), months `09.2026`.
@@ -73,7 +73,7 @@ cargo test -p lightcraft-ui-egui i18n::tests -- --nocapture
LIGHTCRAFT_LANGUAGE=ka lightcraft-cli snapshot --demo -o georgian.png --size 1600x1000
```
The tests check catalog coverage, placeholders, switching language by menu and control channel,
saving, the `ka` locale tags, dates, count wording, the absence of Mtavruli and that sentence case
keeps Georgian lowercase. More notes are in
The tests check placeholders, switching language by menu and control channel, saving, the `ka`
locale tags, dates and that sentence case keeps Georgian lowercase. Messages Georgian lacks show in
English; `i18n::tests::translation_gaps_report` lists them. More notes are in
[localization.md](localization.md).
+3 -2
View File
@@ -66,8 +66,9 @@ LIGHTCRAFT_LANGUAGE=vi lightcraft-cli snapshot --demo -o vi.png --size 1600x1000
LIGHTCRAFT_LANGUAGE=vi lightcraft-cli snapshot --demo -o vi-narrow.png --size 1280x800
```
Các test tiếng Việt bắt buộc phủ catalog union, nhãn lệnh/control/Settings/Smart Album,
đổi ngôn ngữ, lưu `vi`, formats, ngày, dữ liệu người dùng, và glyph dấu.
Các test tiếng Việt kiểm tra đổi ngôn ngữ, lưu `vi`, formats, ngày, dữ liệu người dùng và glyph
dấu. Chuỗi còn thiếu hiện bằng tiếng Anh và được `i18n::tests::translation_gaps_report` liệt kê;
không test nào thất bại vì thiếu bản dịch.
## Nguồn dịch (clean-room)
+2 -1
View File
@@ -34,5 +34,6 @@ LightCraft 的界面支持英语、简体中文、繁体中文(台湾)和日
`LIGHTCRAFT_LANGUAGE=zh-hans lightcraft-cli snapshot ...` 可以渲染中文界面用于检查。
翻译是否完整、两种目录的键与占位符是否一致、字形是否齐全,都由
两种目录的占位符是否一致、字形是否齐全,由
`cargo test -p lightcraft-ui-egui i18n::tests` 验证(字形检查只在指定 `CRAFT_FONTS_DIR` 时实际执行)。
缺少的译文显示为英文,由 `i18n::tests::translation_gaps_report` 列出,不会让测试失败。
+16 -12
View File
@@ -12,11 +12,10 @@ are in [`localization-zh-hans.md`](localization-zh-hans.md), [`localization-zh-h
1. **Translate the two catalogs.** Copy `locales/ja.json` and `locales/ja-formats.json` to
`locales/<code>.json` and `locales/<code>-formats.json`, then translate the values. Keys are the
English source strings and must stay byte-for-byte identical. The plain catalog may grow at its
own pace: a message it lacks shows in English, and `cargo test -p lightcraft-ui-egui i18n::tests
-- --nocapture` lists the gaps (it fails on an empty entry or mismatched placeholders). The
formats catalog must carry every message (the build fails otherwise; a message copied in English,
value equal to its key, is an untranslated placeholder until someone translates it), including the date
English source strings and must stay byte-for-byte identical. Both catalogs may grow at their
own pace: a message a catalog lacks, or translates as an empty string, shows in English, and
nothing fails. The translation gaps report lists what each language lacks (see
[Testing and looking at it](#testing-and-looking-at-it)). The formats catalog also holds the date
patterns (`{year}`, `{month} {year}`, `{weekday}, {day} {month} {year}`…) that date headings and
capture times use in every language but English; weekday names go in the plain catalog.
2. **Add the table entry** in `crates/ui-egui/src/i18n.rs`:
@@ -81,18 +80,23 @@ tr_format!("Added {n} photo{} to “{}”", if n == 1 { "" } else { "s" }, album
`"已将 {n} 张照片添加到“{1}”{0:.0}"`. Keep the source's spec (`{:.1}`, `{d:+}`, `{:.0}%`).
- `format!` rejects an unused argument, so a value a language does not need — the English plural
suffix (`"s"` / `""`) — is consumed as `{:.0}` (a string at precision 0 prints nothing).
- Every formats catalog carries the same messages (`build.rs` fails the build otherwise), and a
`tr_format!` call whose message is in no catalog does not compile: add it to every
`*-formats.json` file.
- A language whose formats catalog lacks a message shows the English source there, and a
`tr_format!` call whose message is in no catalog formats the English source (the macro's last
arm). A new message builds with no catalog entry.
## Testing and looking at it
```sh
cargo test -p lightcraft-ui-egui i18n::tests # catalogs, keys, placeholders, commands
cargo test -p lightcraft-ui-egui i18n::tests # catalogs load, placeholders, switching
CRAFT_FONTS_DIR=../craft-fonts cargo test -p lightcraft-ui-egui i18n::tests # + glyph coverage
cargo test -p lightcraft-ui-egui --lib -- --exact i18n::tests::translation_gaps_report --nocapture
```
The glyph tests are skipped without `CRAFT_FONTS_DIR` (there are no CJK faces to check then).
The tests fail on a broken catalog (malformed JSON, a repeated key, placeholders that differ from
the source), never on a missing translation. The last command is the translation gaps report: per
language, the count and list of plain and format messages it lacks and the number of untranslated
What's New lines. It always passes, and `cargo xtask ci` prints it after its test step. The glyph
tests are skipped without `CRAFT_FONTS_DIR` (there are no CJK faces to check then).
To look at a language, render it headless:
```sh
@@ -114,5 +118,5 @@ when a region has no dedicated entry.
Help ▸ What's New shows `docs/whats-new.md`, and each of its lines (a heading, or one wrapped line of a
bullet, without the `- ` or `### `) is looked up like any message, so a catalog can translate the notes
line by line (German does). A line that is re-wrapped or edited no longer matches its translation and
shows in English until the catalog is updated; untranslated lines are reported by
`display_label_gaps_are_reported`, never failed.
shows in English until the catalog is updated; the translation gaps report counts the untranslated
lines.