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:
1 parent
0025ceac16
commit
c2e77c7fe9
3 files changed
+67
-90
No files matched your search
+41
-15
@@ -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
|
||||
|
||||
|
||||
Reference in new issue
Block a user