feedback5: merge UI-TW — the Traditional Chinese interface (all msgids converted with OpenCC cn → twp, the official TW terms, a manual pass) and the machine-translation mark (_meta.machineTranslated → the pack index → a note under the language switch in 设置); golden unchanged
This commit is contained in:
commit
d0fc57ff4c
11 files changed
+1218
-41
No files matched your search
+27
-13
@@ -4,9 +4,9 @@ Chinese is the default; every other language is a switch (the owner's decision o
|
||||
opens in Chinese until the player picks a language on the title screen (top right) or in 设置 / Settings. Every
|
||||
language but Chinese is a **language pack** — a file in the language folder, nothing else (the owner's decision of
|
||||
2026-10-07; §5 "Adding a language"): the menu lists every pack the server finds, each under its own name (buttons up to
|
||||
four languages, a list beyond). English is a pack like any other; it ships with the game and is the complete one.
|
||||
Japanese, Korean and Traditional Chinese ship too, with the official game texts and no UI strings yet (§5 "Shipped
|
||||
packs"). The choice is kept in `localStorage` (`sp.pref.lang`); `?lang=<code>` in the address bar (`?lang=en`, `?lang=zh`) sets it
|
||||
four languages, a list beyond). English is a pack like any other; it ships with the game, complete. Japanese, Korean
|
||||
and Traditional Chinese ship too, with the official game texts and complete UI strings made by machine, open to
|
||||
corrections (§5 "Shipped packs"). The choice is kept in `localStorage` (`sp.pref.lang`); `?lang=<code>` in the address bar (`?lang=en`, `?lang=zh`) sets it
|
||||
once and is then removed; a stored language whose pack is gone opens in Chinese. A switch re-renders the page in place
|
||||
(no reload). Language packs are the first type of the content packs (docs/PACKS.md: the manifest, the registry, the
|
||||
index, the pack folders).
|
||||
@@ -240,13 +240,24 @@ which are bilingual on purpose.
|
||||
|
||||
## 5. Adding a language
|
||||
|
||||
**Shipped packs** (0.2.0; the owner's decision of 2026-10-07): English (complete) and three packs that carry the
|
||||
official game texts but no UI strings yet — 日本語 (`ja`: the JP client, 96.5 % of the game texts), 한국어 (`ko`: KR,
|
||||
97.4 %) and 繁體中文 (`zh-TW`: TW, 91.1 %; its data is older, and a Traditional text equal to the Simplified one counts as
|
||||
untranslated). Their UI falls back to English (`ja`, `ko`: `"fallback": ["en"]`) or, for `zh-TW`, to the Simplified
|
||||
Chinese msgids (no fallback — the owner's choice); `zh-TW` counts large numbers in 萬 / 億. **UI translations are
|
||||
welcome from the community**: start from the shipped file — `node tools/i18n.mjs template <code>` keeps its `_meta` and
|
||||
adds every msgid with an empty value — then follow the steps below and send a pull request.
|
||||
**Shipped packs** (0.2.0; the owner's decisions of 2026-10-07): English and three packs with the official game texts
|
||||
and complete UI strings — 日本語 (`ja`: the JP client, 96.5 % of the game texts), 한국어 (`ko`: KR, 97.4 %) and 繁體中文
|
||||
(`zh-TW`: TW, 91.1 %; its data is older, and a Traditional text equal to the Simplified one counts as untranslated).
|
||||
The three are made by machine and marked so (`"machineTranslated": true`: 设置 shows a note under the language switch
|
||||
while one is in use); a string a pack lacks falls back to English (`ja`, `ko`: `"fallback": ["en"]`) or, for `zh-TW`, to
|
||||
the Simplified Chinese msgid (no fallback — the owner's choice); `zh-TW` counts large numbers in 萬 / 億.
|
||||
|
||||
- **繁體中文** is a conversion, not a free translation: each msgid converted from the Simplified Chinese with OpenCC
|
||||
(`cn` → `twp`, Traditional characters with Taiwan phrases), the official TW client's word kept where the phrase step
|
||||
words a game concept differently (調度中心, not 排程中心; 更新 for the shop refresh; 啟動 for a bond; 遠程位; 查看; 目前 …;
|
||||
a whole string the TW tables have, such as 時間較短的模擬訓練, as it is there), then a manual pass over the result
|
||||
(one-to-many characters such as 只 / 隻, 重新整理 for a page refresh …). A msgid added later is converted the same way.
|
||||
- **日本語 / 한국어** are machine translations that use the official JP / KR game terms. **Corrections are welcome**, to
|
||||
any pack: edit the string in `public/i18n/<code>.json`, run `node tools/i18n.mjs check <code> --strict` (0 errors,
|
||||
0 missing) and send a pull request on GitHub.
|
||||
|
||||
A new language is welcome too: `node tools/i18n.mjs template <code>` starts its pack (run on an existing pack, it keeps
|
||||
the translations and `_meta` and adds every missing msgid with an empty value); then follow the steps below.
|
||||
|
||||
A language is a file in the language folder; the server lists it on the next page load (no restart, no build step, no
|
||||
code change). For a community translator:
|
||||
@@ -257,7 +268,8 @@ code change). For a community translator:
|
||||
and every msgid (about 1 000) with an empty value, in the order of the English pack (`--fill en` fills in the English
|
||||
to overwrite). Fill in `_meta`: `name` (the language in itself, shown in the menu), `englishName`, `authors`,
|
||||
`version`; keep `"fallback": ["en"]` to show English where a string is still empty (drop it to show Chinese); set
|
||||
`numberUnits` if the language counts large numbers in 10⁴ steps like Chinese (`["万", "億"]`).
|
||||
`numberUnits` if the language counts large numbers in 10⁴ steps like Chinese (`["万", "億"]`), and
|
||||
`"machineTranslated": true` when the strings come from a machine (players then see a note in 设置; docs/PACKS.md).
|
||||
3. **Translate** the values (empty = not yet: it falls back). Keep every `{placeholder}` of the msgid; plural forms as
|
||||
in §1; `public/i18n/en.json` is the reference for meaning and context (`ctx::msgid` keys are the same Chinese text in
|
||||
another context). Use the official terms of your language's client where it has one.
|
||||
@@ -273,8 +285,10 @@ code change). For a community translator:
|
||||
again: it keeps the translations and adds the new msgids.
|
||||
|
||||
The tests: `test/i18n-packs.test.js` (discovery, the fallback chain, placeholders, plurals in English and Russian, the
|
||||
template and check commands, and that the Chinese and English output of `t()` is what it was before packs: every msgid
|
||||
of `public/i18n/en.json` rendered with sample params, compared with the renderer of 0.2.0 before packs).
|
||||
template and check commands, the `machineTranslated` mark — manifest, index, the client's registry, the 设置 note — and
|
||||
that the Chinese and English output of `t()` is what it was before packs: every msgid of `public/i18n/en.json` rendered
|
||||
with sample params, compared with the renderer of 0.2.0 before packs); `test/ui/i18n.e2e.test.js` (`SP_E2E=1`: the
|
||||
shipped packs in the browser, their UI strings and the 设置 note).
|
||||
|
||||
## Credits
|
||||
|
||||
|
||||
+6
-3
@@ -63,7 +63,8 @@ would see one folder).
|
||||
| `name`, `englishName` | the name in its own language (a language pack: the language's own name, shown in the menu) and in English (the menu's tooltip) |
|
||||
| `authors`, `credits`, `license` | who made it; free text (`license`: an SPDX id or text) |
|
||||
| `files` | a folder pack: role → path inside the folder. Each type lists its roles and their extensions (`lang`: `ui` required, `data` optional, both `.json`) |
|
||||
| the type's fields | `lang`: `lang`, `base`, `fallback`, `complete`, `numberUnits` (docs/I18N.md) |
|
||||
| the type's fields | `lang`: `lang`, `base`, `fallback`, `complete`, `machineTranslated`, `numberUnits` (docs/I18N.md) |
|
||||
| `machineTranslated` | `lang`, optional: `true` when the pack's UI strings come from a machine (a translation, or a conversion such as the Traditional Chinese pack's). The index entry carries it (only when true, like `complete`) and the client shows a note under the language switch in 设置 while that language is in use (`public/js/ui/lang.js` `machineTranslationNote`). A value other than `true` / `false` is a warning and reads as false |
|
||||
|
||||
A **problem** keeps a pack from loading (unknown type, no `lang`, a file missing or outside the folder, broken JSON, an
|
||||
id or a language already taken — the language folders' files come first, then the folders by id); a **warning** does
|
||||
@@ -158,7 +159,9 @@ that ship. `test/package.test.js` checks both layouts and that a local pack stay
|
||||
## Tests
|
||||
|
||||
`test/i18n-packs.test.js` (discovery of both layouts, broken / planned / duplicate packs, a pack dropped in or removed
|
||||
while the server runs, the file allowlist, the manifest and app ranges, the fallback chain, placeholders, plurals,
|
||||
while the server runs, the file allowlist, the manifest and app ranges, the `machineTranslated` mark from the manifest
|
||||
to the 设置 note, the fallback chain, placeholders, plurals,
|
||||
the per-text game-text fallback, the client loader and menu, the tools, build-i18n `--lang` / `--dict`),
|
||||
`test/package.test.js`, `test/ui/i18n.e2e.test.js`
|
||||
(`SP_E2E=1`: a pack file and a pack folder dropped in while the server runs show in the menu and switch).
|
||||
(`SP_E2E=1`: a pack file and a pack folder dropped in while the server runs show in the menu and switch; the shipped
|
||||
packs with their UI strings and the 设置 note of a machine-translated one).
|
||||
Reference in new issue
Block a user