feedback5 W5S: i18n phase 2 coverage — test/i18n.test.js scans the whole client, shared and the server messages (no Chinese literal unwrapped, every msgid translated: extract 0 and check --strict as a test; floors 1 000 catalog entries, 1 350 msgid uses), public/i18n/en.json drops the 64 fragments / renamed msgids the sweep replaced (none is a data text), docs/I18N.md: phase-2 coverage, what stays Chinese and why, the server's game texts, the audit's skip rules

This commit is contained in:
sganggs committed 2026-10-06 18:31:28 +08:00
1 parent 0025ceac16
commit c2e77c7fe9
3 files changed
+67 -90

No files matched your search

+41 -15
View File
@@ -46,8 +46,9 @@ html`<span>${tParts('第 {r} 回合 · 最终攻势', { r: html`<b class="num">$
### Translating
Edit `public/i18n/en.json` (`"msgid": "English"`, two-space JSON; `_about` is metadata). Keep every `{placeholder}`;
`test/i18n.test.js` checks that, that no Chinese is left in a value, and that every msgid of the converted screens is
present. Use the official EN terms of the game (the EN client's own wording, e.g. its tips and mode texts):
`test/i18n.test.js` checks that, that no Chinese is left in a value, and that every msgid the code uses is present. A
translation may use more params than its msgid (`'{n} {count|unit|units}'` with `count` passed beside a vnode `n`). Use
the official EN terms of the game (the EN client's own wording, e.g. its tips and mode texts):
| 中文 | English | 中文 | English |
|---|---|---|---|
@@ -80,7 +81,15 @@ present. Use the official EN terms of the game (the EN client's own wording, e.g
code uses (`--all`: also the literals not wrapped yet, under the msgid the codemod will give them).
Server code is scanned too: the first argument of `msg()` and a Chinese literal handed to `m.toast` / `ctx.toast` /
`tickerText` are msgids (`server/sim` only for those — its own `t()` helpers are not translation calls).
`tickerText` are msgids (`server/sim` only for those — its own `t()` helpers are not translation calls). Not player text,
so neither wrapped nor counted: `console.*` / logger calls (`log.warn(…)`, `this.m.log?.info?.(…)`), `Error` messages,
the `detail` of an error result (`{ error: 'BAD_TARGET', detail: '…' }`, `ev.detail = '…'` — players see `ERR_TEXT`), a
line marked `// i18n-ignore` and a file marked `i18n-ignore-file` in a comment (the developer invariant reports
`server/match/audit.js` / `invariants.js`, the bilingual HTTP error pages `server/http/*`). An aliased import
(`import { t as tr }`, where `t` is a local variable) is read as the function it names.
`test/i18n.test.js` scans what `extract` / `check` scan (public/js, shared, server) and fails on a Chinese literal left
unwrapped or a msgid missing from `public/i18n/en.json` — `extract` 0 and `check --strict` are part of the tests.
## 2. Game texts: `data/i18n/en.json`
@@ -138,21 +147,38 @@ protocol is backward compatible both ways (new fields are optional).
this.m.toast(this, 'warn', msg('{names}只能部署在召唤者攻击范围内,已退回整备区', { names: back.map(dn) }));
```
## 4. Phase 2 (after the 0.2.0 feature screens land)
Game texts the server copies into `m.public` / `m.private` in Chinese — a 机变 card's name and description, the draft's
name, an effect entry of the effects column, a reward offer's label, a result title — are shown from the localized data
on the client: names through `tName()` (every record name is in the overlay's `names`), texts through
`ui/lang.js sentText(sent, raw, local)`, which takes the localized record's text when the sent text is that record's own
Chinese text (`data.lookupRaw` / `data.getRaw`), else the sent text (a line the server reworded — the two-battle text of a
multi-round 悬赏, `server/match/choices.js bountyText` — stays Chinese). In Chinese both return what the server sent.
## 4. Coverage of the UI strings (phase 2, 0.2.0)
Phase 1 converted the title screen, the lobby, the room, the settings panel (with the language switch), the app shell
(main.js: toasts, close reasons, the crash screen), `ui/toasts.js`, `DifficultyTag` and the server messages. Phase 2:
(main.js: toasts, close reasons, the crash screen), `ui/toasts.js`, `DifficultyTag` and the server messages. Phase 2
(2026-10-06) converted the rest: of the 1 128 Chinese literals `extract` listed, 1 056 go through `t()` / `tParts()` /
`N_()` — the briefing, the band draft, the game screen and its overlays, 干员调配 / 干员持有, the result (275), the HUD,
shop bar, detail card, bond strip, 机变 overlay, enemy drawer, team panel, guide, emotes, components and the client
models (579), the phase banners, refusal reasons and formats of `ui/gameLogic` (106), the canvas / fallback-field / facing
labels (16) and the msgid tables of `shared/constants.js` (80) — and 72 are marked as no player text (above). Now
`node tools/i18n.mjs extract` reports 0, `check` 1 002 msgids, all in `public/i18n/en.json` (1 015 entries). The Chinese
output did not change: a render of every converted file in Chinese (each `t()` call put back as the string it renders,
html`` parsed with htm, text runs compared) equals the code before the sweep; the few rewrites it cannot follow (a
variable folded into whole sentences, a list param in place of `.join('、')`, `fmtNum`'s English branch) were checked by
hand. Numbers: `fmtNum` writes 万 / 亿 in Chinese and K / M / B in English.
1. `node tools/i18n.mjs extract` lists the rest (2026-10-05: 1 033 literals in 56 files — briefing, band draft, game
screen and its HUD / panels / overlays, loadout, result, guide, connection banner, components …; 964 of them already
have a translation seeded from PR #70).
2. Per file (one stream per file group to avoid conflicts): `node tools/i18n.mjs codemod <file> --write`, review the
diff (module-level tables: `t()` at the use site; join split sentences; `tc()` where one Chinese text needs two
English ones), then `node tools/i18n.mjs check` and translate what is missing, in the official terms above.
3. Texts the server puts in `m.public` / `m.private` (机变 card names and descriptions, effect names in views) should be
looked up by id on the client (`getEffect` / `data.lookup`) instead of shown as sent.
4. `public/js/ui/guide.js` chapter / page titles, the `GuideButton` / `LoadoutButton` default labels and tooltips.
5. When the sweep is complete: `node tools/i18n.mjs check --strict` in CI, and `extract` reporting 0.
What stays Chinese in English, and why:
- player names, including the AI seats' (`AI·华法琳` …, `server/lobby.js BOT_NAMES`) — a name is never translated;
- a server text the client cannot match to a data record (the reworded multi-round 悬赏 text above);
- game texts the official EN client does not have yet (§2: some 自选 operators, newer modules);
- the 玩法说明 pages, which are the official Chinese pictures (their titles are translated).
Not player text, never translated: developer details and logs (`detail`, `log.*`, the invariant reports), the data keys
(`shared/highGround.js` reads the trait text 「可以放置于远程位」), the development STUB match, and the HTTP error pages,
which are bilingual on purpose.
## Credits