i18n-locale-fill
GitHub用于在发布时自动填充多语言本地化缺失条目,解决 I18N_RELEASE_TIER=1 门禁失败问题。涵盖工作列表生成、不同作用域填写位置及陷阱规避,确保所有区域版本就绪可发布。
Trigger Scenarios
Install
npx skills add levy-street/world-of-claudecraft --skill i18n-locale-fill -g -y
SKILL.md
Frontmatter
{
"name": "i18n-locale-fill",
"description": "Fill pending i18n rows across every locale for World of ClaudeCraft, the release-time workflow. Use when the release-tier gate (I18N_RELEASE_TIER=1) fails on pending rows, when asked to translate or fill locales, overlays, or matcher DICTs, or when preparing a release branch whose registry still has pending entries. Covers the worklist generator, where each scope's fills land, the placeholder and glossary contracts, and the known traps (English-in-overlay, shared DICT references, the \"todo\" guard, reword staleness, native punctuation in overlays).",
"user-invocable": true
}
i18n locale fill (release time)
Contributors add ENGLISH only; the maintainer fills every locale at release. This skill is
that fill workflow. The release-tier gate (I18N_RELEASE_TIER=1, automatic on release/**
branches) hard-fails on any pending registry row, so a release is not shippable until the
fill lands.
1. Generate the worklist
npm run i18n:gen # refresh the registry first
npm run i18n:worklist # writes one batch per language under docs/i18n-scaling/worklist/ (gitignored)
scripts/i18n_fill_worklist.mjs is data-only (no translation): each batch entry carries
{ scope, key, english, placeholders, siblings }.
main-scope keys are filled in the matchingsrc/ui/i18n.locales/<lang>.tsoverlay.sim/server/adminscope keys are filled in their matcher DICTs (the worklist header inscripts/i18n_fill_worklist.mjsnames the exact files).- Sim-scope keys DO reach the worklist (since Masterwrought Phase 19F, ruling
qr-19-sim-scope-pending-is-unreachable): the registry reads each locale's OWN source
blocks through
simDictProvidedKeysinsrc/ui/sim_i18n.ts, never the assembledDICT(which is dense by construction,baseEnTablespread under every locale), so a sim row with no fill in a locale's block ispendingand lands in that locale's batch. Fill a sim key in the locale'sBASE_DICTblock ofsrc/ui/sim_i18n.ts(the eight newest locales keep theirs inBASE_NEWofsrc/ui/sim_i18n.newlocales.ts, a hand-maintained file despite its old banner; each of those locales' own block insim_i18n.tsspreadsBASE_NEWin the MIDDLE of its literal rows, so a key spelled in both is read from whichever spelling comes last in the block, and the registry's row-count anchor intests/i18n_status_registry.test.tsreds on the duplicate either way), and NEVER paste the English into a locale block: a copied row readstranslatedand ships English (the sim scope has no copied-English guard; onlytests/localization_fixes.test.ts's release-tiers3_localizedarm sees it late). Runnpm run i18n:genbefore the suites: the registry pin compares the artifact against the live source and reds on a stale one. The five per-locale*_EXTRAtables the RULES matchers read (arena, battleground, quest, item, raid) are tsc-forced dense and stay outside the registry; check them by eye at release. humanRequiredentries are blocked by default (quest narratives, names, lore, SEO copy): never machine-fill them; onlyautoFillableentries are fair game for a model pass.
Batches are per-language and independent: fan out one fill agent per language when the volume is large, then regenerate once at the end.
1b. The chunk families OUTSIDE the registry (deeds and reliquary)
The Deeds and Reliquary systems keep their locale tables in lazy per-base-locale chunks
that the registry and scripts/i18n_fill_worklist.mjs never see:
src/ui/deed_i18n.locales/<locale>.ts and src/ui/reliquary_i18n.locales/<locale>.ts
(loader contract pinned by tests/deed_i18n_lazy.test.ts and
tests/reliquary_i18n_lazy.test.ts). Consequences:
- Zero pending registry rows does NOT prove full coverage. A fill pass driven only by
the worklist ships English deed/reliquary rows while the registry reads clean. Their
coverage is enforced only by the release-tier arms (
it.runIf(I18N_RELEASE_TIER === '1')) intests/deed_i18n.test.tsandtests/reliquary_i18n.test.ts, which walkdeedTranslationManifest()/reliquaryTranslationManifest()against every base locale table. Run those release-tier to prove this surface, not the pending count. - Fill every base locale chunk in the family; a chunk carries only real catalog ids (the same tests reject a stale id or a title on a deed that rewards none).
- The overlay punctuation exemption does NOT extend here. These chunk files sit
outside the
src/ui/i18n.localescopy-scan exemption: no em/en dashes or emoji in any value, even where the locale would natively use them (the pin tests enforce it).
2. The fill contract
- Translate, never transplant. The registry counts PRESENCE, not language: pasting the English value into an overlay marks the row filled and silently ships English. Do not.
- Placeholder parity. Every
{token}in the English value must appear verbatim in the fill (the worklist lists them). The scanner checks parity; a dropped token is a break. - Locked terminology. Classic-MMO terms per locale live in
scripts/i18n_glossary.jsonand are locked; follow them, and extend the glossary when a new recurring term appears. - Matcher DICT values must be literal string copies. Never alias or share a reference between DICT rows; the matcher relies on per-row literals.
- Native punctuation in overlays is legitimate. Russian and other locales use real em
dashes; NEVER strip them. The repo copy scans deliberately exclude
src/ui/i18n.locales. - The placeholder guard flags a bare "todo" value, which is also a real word in es/pt. Phrase such fills differently (for example "por hacer") so the guard does not trip.
3. Regenerate, verify
npm run i18n:genregenerates the resolved bundles and the status registry.- Biome-format every overlay file the fill touched in the same change:
npx @biomejs/biome check --write src/ui/i18n.locales/<touched>.ts .... CJK and other wide-glyph fills blow the 100-column lineWidth silently (the line LOOKS short in an editor but is over by bytes), and the changed-files biome gate then fails a later round on a format diff you never saw (it cost the phase 13 closing gate its first round). Note biome SIZE-SKIPS files over 1.0 MiB (ru_RU is there already): gate green is not format evidence for those, and that is a known accepted state, not something to fix. - Stage the regenerated artifacts in the SAME commit as the fills. The freshness gate diffs the regenerated output against the staged/committed copies; unstaged artifacts fail it.
- Prove completion: run the i18n steps release-tier,
I18N_RELEASE_TIER=1 npm run gate(or at minimumi18n:gen+ the guard tests), and confirm zeropendingrows remain. Zero pending covers the REGISTRY only: the deed/reliquary chunk families (section 1b) are proven by their own release-tier test arms, not by the pending count.
4. Reword staleness (the silent trap)
Rewording an EXISTING English value does not mark its translations pending: every locale
silently keeps the old meaning. After any English copy change, diff the resolved en output
between the base branch and HEAD and re-fill the touched keys in the same change.
Version History
-
cecebab
Current 2026-09-22 05:03
修正 Sim 作用域键值在工作列表中的可见性逻辑,新增对 Deeds 和 Reliquary 系统的本地化支持说明。
-
ce662ac
2026-09-03 01:11
新增 sim/server/admin 作用域键的 matcher DICTs 填写说明;明确 humanRequired 条目禁止机器填充;增加 Deeds 和 Reliquary 系统的独立检查与填充流程。
-
51b342b
2026-08-13 10:12
新增 Deeds 和 Reliquary 系统的本地化处理流程,强调需直接填充独立 chunk 文件而非仅依赖注册表,并补充了标点符号豁免不适用的约束。
- dd03ada 2026-08-05 06:41
- 2edc3ac 2026-07-19 18:52


