Skip to content

Automatic build-time translation for datavis locales via Loco #340

Description

@horner

Goal

Keep the packages/datavis i18next locales translated automatically via Loco: push new English keys, AI-translate on the server, pull translated JSONs back into the repo. The build never depends on the Loco server at runtime — locale files stay committed (File-Mode philosophy).

flowchart LR
    Source[en-US.json<br/>source of truth] -->|1. push keys| Register[POST /api/textnodes<br/>+ approve]
    Register -->|2. find gaps| Gaps[GET /api/textnodes/untranslated-ids]
    Gaps -->|3. translate| AIJob[POST /api/ai-jobs<br/>poll until done]
    AIJob -->|4. pull| Export[GET /api/export/:lang]
    Export -->|5. write| Locales[src/i18n/locales/*.json<br/>committed to repo]
Loading

Milestone 1 — Connectivity & key-model spike

  • Confirm/create a Loco project for datavis and obtain LOCO_API_KEY
  • Curl smoke tests: GET /api (health), GET /api/languages, POST /api/textnodes with sample keys, GET /api/export/{lang}
  • Decide the key model (blocking): datavis uses ID keys (t('COLUMN_CONFIG') || 'Column configuration') while Loco is text-keyed — push English fallback text as the Loco key with context: 'datavis:<KEY>', or push the raw key?
  • Map repo locale names (zh-Hans-CN, es-MX, …) to Loco language codes (GET /api/languages)
  • Exit criteria: one key travels en-US.json → Loco → AI translation → exported JSON in the expected shape

Milestone 2 — loco-sync.mjs pull path (read-only half)

  • Create packages/datavis/scripts/loco-sync.mjs (zero-dep Node, same style as check-i18n-keys.mjs); config via LOCO_API_URL / LOCO_API_KEY env vars
  • --pull-only mode: GET /api/export/{lang} per language in src/i18n/config.ts, remap to repo keys, write src/i18n/locales/*.json (sorted keys, 2-space indent, trailing newline; skip unchanged files)
  • Keys missing on Loco keep their committed value — never delete translations on pull
  • Add "i18n:pull": "node scripts/loco-sync.mjs --pull-only" to packages/datavis/package.json
  • Exit criteria: pnpm i18n:pull yields a clean/correct diff; pnpm lint:i18n passes; Storybook renders fr-FR unchanged

Milestone 3 — Push + AI-translate path (full sync)

  • Push: diff en-US.json keys against Loco (GET /api/translations/all), register new ones (POST /api/textnodes), bulk-approve (PATCH /api/textnodes/status)
  • Translate: per language GET /api/textnodes/untranslated-idsPOST /api/ai-jobs → poll GET /api/ai-jobs/{jobId} with timeout, then pull
  • Summary output (keys pushed / translated / files changed); nonzero exit on job failure or timeout
  • Add "i18n:sync": "node scripts/loco-sync.mjs" to packages/datavis/package.json
  • Exit criteria: add a new key to en-US.json, run pnpm i18n:sync, all 9 locale files gain a translated entry

Milestone 4 — Build & CI integration

  • Local build hook: sync before build only when LOCO_API_KEY is set; skip silently otherwise so offline/contributor builds work from committed locales
  • PR check workflow (thin wrapper around the script): i18n:pull + git diff --exit-code fail-on-drift
  • Scheduled/manual workflow: full i18n:sync that opens a PR with refreshed locale files (never auto-commits to main)
  • Add LOCO_API_KEY as a repo secret
  • Exit criteria: CI goes red when a new key lacks translations; scheduled run produces a locale-update PR

Milestone 5 — Hardening & docs

  • Retry/backoff on API calls
  • Placeholder guardrail: verify i18next interpolations ({{count}} etc.) survive AI translation; fail the key otherwise
  • Optional: seed Loco glossary with domain terms (chart, pivot, perspective, …)
  • README section in packages/datavis (workflow diagram, env vars, commands); note in TESTING.md if the drift check lands in CI
  • Exit criteria: a developer new to Loco can add a key and get translations by reading the README

Risks

Risk Mitigation
Loco is text-keyed, datavis is ID-keyed Milestone 1 spike decides mapping before any code
AI mangles i18next placeholders Milestone 5 validator; Loco's slot system helps
CI spend on AI jobs Full sync only on schedule/manual; PRs are pull-only
Language code mismatches Explicit mapping table validated against GET /api/languages

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

enhancementNew feature or request

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions