Internationalization

Games use i18next keys instead of inline English strings.

Files

Path Content
locales/en/apgames.json English source — game names, descriptions, UI strings
locales/en/apresults.json English source — move result / chat log strings
locales/{de,fr,it,es-US}/*.json Translations only (Weblate + CI)
locale-src/{de,fr,it,es-US}/*.json English snapshot for machine-translation diffing (CI only)

Community partial locales (es, uk, ta, etc.) live under locales/ with no sidecars.

locale-src/ sidecars

Managed locales (de, fr, it, es-US) are machine-translated by scripts/translate.mjs when English changes. The script compares each key against a flat English snapshot in locale-src/ to detect stale translations.

One-time migration: node scripts/split-locale-src.mjs (already run; kept for reference).

Weblate merges

  1. Merge migration before accepting Weblate PRs that strip _src
  2. Close bulk "Cleanup translation files" PRs — they delete metadata and unrelated keys
  3. Small human-editing PRs merge normally; locale-src/ is never in the diff
  4. In hosted Weblate: disable the "Cleanup translation files" add-on for managed components

Weblate key naming

Weblate's i18next parser treats a bare key as conflicting with siblings whose names look like plural or context suffixes (_one, _other, _2, _11, etc.) in the same JSON object. For example, do not place INSTRUCTIONS alongside INSTRUCTIONS_one — rename the non-plural key (e.g. INSTRUCTIONS_ANY).

npm run lint runs check-weblate-keys against locales/en/*.json and fails on conflicts. Use a distinct stem for each purpose (e.g. nowhere_what vs nowhere_count_one/nowhere_count_other).

In game code

description: "apgames:descriptions.complica"

Add keys when introducing new user-visible text. Variant names in gameinfo also reference apgames.json.

addResource

Front end merges bundles via APGames.addResource(lang) — see API.

Scripts

Script Purpose
npm run translate Gemini incremental translate en → de/fr/it/es-US
npm run check-weblate-keys Fail on Weblate plural-stem key conflicts in English locales
npm run check-locale-readiness Audit locales vs English
node scripts/publish-locales.mjs --stage dev|prod Upload supported locales to S3

Example games