Skip to content

feat: i18n / locale support for user-facing messages#125

Open
IyadhKhalfallah wants to merge 1 commit into
mainfrom
feat/i18n-locale-support
Open

feat: i18n / locale support for user-facing messages#125
IyadhKhalfallah wants to merge 1 commit into
mainfrom
feat/i18n-locale-support

Conversation

@IyadhKhalfallah

Copy link
Copy Markdown
Owner

Closes #122.

Summary

  • Adds a locale field to ~/.clauditor/config.json (falls back to $LANG, then en)
  • Lightweight t() helper in src/i18n.ts backed by src/locales/{en,es}.json
  • All ~190 user-facing strings across cli.ts, install.ts, tui/dashboard.tsx, and hooks/user-prompt-submit.ts now route through t() with {var} interpolation
  • Spanish translation included (the user who filed Feature request: i18n / locale support for user-facing messages #122 volunteered to help — this gives them a starting es.json to refine)

Test plan

  • npx tsc --noEmit — clean
  • npx vitest run — 356/356 tests pass (16 new across i18n.test.ts + locales.test.ts)
  • npm run build — tsup bundles JSON inline, no runtime FS call
  • Smoke test: LANG=es node dist/cli.js --help renders full Spanish
  • Reviewer verifies clauditor install / clauditor login still work in English (default)

New tests

  • src/i18n.test.ts — fallback behavior, interpolation, locale code normalization (es_ES.UTF-8es, etc.), env loading
  • src/locales.test.tskey parity between en.json and es.json + placeholder-var parity. Fails CI the moment someone adds a new en key without translating it, or drifts interpolation params between locales.

Design notes

  • No new dependency. Helper is ~30 lines, JSON bundles ship inline via tsup.
  • Key namespace: feature.subkey (e.g., block.title, sessions.minAgo).
  • ANSI colors stay in code; plain text in JSON. Call sites wrap with \x1b[...].
  • Stripped box-drawing (╔╗╚╝║═) from block/continue titles — the English padding assumed fixed width, which any translation would break.

Known limitations (Phase 2 follow-up)

  1. Hub errors leak English. The clauditor hub (/api/v1/*) returns { error: "..." } strings that the CLI prints verbatim via src/hub/client.ts:64-65. A full i18n UX requires changing the API contract to return error codes. Out of scope for this PR.
  2. continue.command round-trip. The translated string "lee {path} y continúa donde lo dejé" is what the hook shows a Spanish user to copy-paste; but the hook's own continue-prompt detection regex is English-only. If a Spanish user pastes the translated line back, detection won't fire. Options: keep that specific string English-only, or extend the regex to recognize Spanish forms. Worth a follow-up issue.
  3. A handful of tiny labels in dashboard.tsx ("Cache:", "Turns:") and literal shell commands (claude mcp add ...) are intentionally not translated.

How translators can contribute

Only need to touch one file per language: src/locales/<lang>.json. The key-parity test will flag any drift.

Adds a `locale` config field (falls back to $LANG, then "en") and a
lightweight t() helper backed by src/locales/{en,es}.json. All ~190
user-facing strings across cli.ts, install.ts, tui/dashboard.tsx, and
hooks/user-prompt-submit.ts now route through t() with {var}
interpolation.

Smoke-tested: LANG=es node dist/cli.js --help renders full Spanish.

Key-parity test (src/locales.test.ts) fails CI if a new key is added
to en.json without matching es.json, or if placeholder vars drift
between locales.

Known limitations (for a follow-up Phase 2):
- Hub errors from /api/v1/* still flow back in English
- continue.command literal is translated but the hook's continue-
  prompt regex is English-only
esmelyvaldivieso99-code added a commit to esmelyvaldivieso99-code/clauditor that referenced this pull request Apr 17, 2026
…nue prompts

Review of IyadhKhalfallah#125 translation. Two related changes:

1) src/locales/es.json — align phrasing to Latin American Spanish
   (the user who filed IyadhKhalfallah#122 is LATAM) and fix two visual issues:

   - Monitorización → Monitoreo
   - Coste → Costo (status.costLine, stats.estCost)
   - punta → pico (horas pico) across time.* and cli.cmd.time.desc
   - pulsa Enter → presiona Enter (block.orContinue)
   - "Escrituras cch:" → "Escrit. caché:" (truncated label was unclear)
   - "DESP." → "DESPERD." in report.columns
     (DESP. can read as "después" in Spanish — ambiguous)

2) src/hooks/user-prompt-submit.ts — extend CONTINUE_PATTERNS with
   Spanish variants so the translated `continue.command` string still
   triggers the handoff injection. Addresses known limitation IyadhKhalfallah#2 in
   the PR description:

     continúa, continuemos, sigue donde/desde/con, retoma, reanuda,
     dónde (nos) quedamos, qué estábamos haciendo,
     "… y continúa donde …" (matches the default es.json command line)

Tested
- npx tsc --noEmit: clean
- npx vitest run src/locales.test.ts src/i18n.test.ts: 16/16 pass
  (key-parity + placeholder-var parity preserved)
- npm run build: clean
- LANG=es node dist/cli.js --help: renders Spanish correctly

Note: 10 time-dependent tests in feat/i18n-locale-support
(pre-tool-use, project-brief, file-index, error-index, decay,
time-analysis) are pre-existing failures — they reproduce on the
base branch without these changes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Feature request: i18n / locale support for user-facing messages

1 participant