--- name: tinyworld-i18n description: Add, translate, or audit TinyWorld UI strings across English/French/Chinese/Spanish. Use when adding user-facing gameplay text, when `npm run i18n:check` fails, when a string shows up in English in a non-English locale, or when adding a new language. No translation API — Codex does the translating directly, using the established glossary for consistency. --- # TinyWorld i18n workflow TinyWorld localizes its **gameplay** UI into English (`en`), French (`fr`), Simplified Chinese (`zh`), and Spanish (`es`). This skill is the repeatable process for keeping those translations complete and consistent. There is no external API: you (Codex) are the translator. The checker (`npm run i18n:check`) is the safety net. Read `docs/i18n.md` first if you need the architecture. The short version: - Locale dictionaries live in `engine/i18n/{en,fr,es,zh}.js` as flat key→string maps. - **`en.js` is authoritative.** Every other locale must define exactly its key set. - Static HTML uses `data-i18n` / `data-i18n-title` / `data-i18n-tooltip` / `data-i18n-placeholder` / `data-i18n-aria-label` attributes. - JS uses the global `t('key')` (or `tx('key', fallback)` to keep a hard-coded English default). Tool/group/variant labels are localized by a single mutation block near the top of `engine/world/19-tools-toolbar.js`. - Language switching is **reload-on-switch** (persist + `location.reload()`), so every surface re-renders correctly at boot. Don't add live re-render wiring. ## Adding or changing strings (the loop) 1. **Add the English string to `engine/i18n/en.js`** with a namespaced key (`panel.thing`, e.g. `time.season`). Keep keys grouped under their existing comment section; add a new section if it's a new surface. 2. **Reference it:** - Static HTML leaf element → add `data-i18n="key"`. For an element that also has child elements (e.g. a `