Skip to content

feat(i18n): add Spanish (es-419) locale support - #9870

Open
GuidoMaxier wants to merge 6 commits into
esengine:main-v2from
GuidoMaxier:feat/es-spanish
Open

GuidoMaxier wants to merge 6 commits into
esengine:main-v2from
GuidoMaxier:feat/es-spanish

Conversation

@GuidoMaxier

@GuidoMaxier GuidoMaxier commented Sep 7, 2026

Copy link
Copy Markdown

Summary

Adds Spanish (es-419, neutral Latin American) interface support to both layers, rebased onto the current main-v2 (v1.38.7).

  • CLI/kernel: full Spanish catalogue in internal/i18n/messages_es.go (field-identical to the English baseline, including the ReadStatus*, OperationNeedsUser, SearchModelUnavailable and ProviderErrNotFound fields added upstream after the original revision), ArgLanguageEs in every locale, setLanguage/normalize mapping for es/es-ES/es-419/POSIX forms, a selectable /language es option (CLI + slash completion), and config.SetLanguage persistence for es. SetLanguage/SetReasoningLanguage live in internal/config/edit_language.go to stay inside the repolint file-size ratchet.
  • Desktop: complete desktop/frontend/src/locales/es.ts dictionary — 3,234 keys, verified 1:1 against en.ts (same key set, same order, same {placeholder} names) — plus the locale wiring (Locale union, SPINNER_WORDS.es, detectLocale/preloadLocale, settings picker with an "Español" option, tray locale). Auxiliary per-locale dictionaries are retyped to Record<Exclude<Locale, "es">, ...> and keep their existing ?? en fallbacks until Spanish copy lands there.
  • Bundle budgets: the gate now enumerates the es-*.js lazy chunk (its filter previously matched only zh/zh-TW, so the Spanish chunk went unmeasured) and budgets it at its measured size: 58,071 B gzip (56.710 KiB), 56.8 KiB ceiling. The zh/zh-TW dialect ceilings are unchanged.
  • English remains the system-prompt and model-behavior language; the new catalogues only affect client-side UI strings (i18n scope is documented as such in the package).

Verification (run locally on this rebased revision)

  • gofmt, go vet ./... clean
  • golangci-lint run ./... (CI pin) -> 0 issues
  • go run ./tools/repolint -> clean
  • go test ./internal/i18n/ ./internal/config/ ./internal/control/ ./internal/cli/ ./internal/tool/builtin/ pass
  • desktop/frontend: tsc --noEmit 0 errors, eslint "src/**/*.{ts,tsx}" clean, pnpm build passes (vite + bundle budgets, including the measured es-*.js chunk)
  • internal/boot reports 7 session-context failures that reproduce identically on a pristine upstream/main-v2 worktree (environment-dependent, unrelated to this diff)

Tests

Catalog parity guards cover the Spanish catalogue (completeness, % placeholder counts, code-token sets); TestNormalize/DetectLanguage cover es; CLI completion and config persistence tests cover /language es. The desktop dictionary is enforced 1:1 against en.ts by its Record<DictKey, string> annotation.

Cache-impact: none - the provider-visible system-prompt prefix is byte-identical; catalogues are client-side UI strings and config.SetLanguage only selects which catalogue loads.
Cache-guard: existing - no prompt/tool/prefix code path changed (internal/i18n scope is CLI text; desktop dictionaries load lazily per locale).
System-prompt-review: maintainers - the diff touches internal/config (UI-language persistence only); no system-prompt, memory-prefix, output-style, or skill-index content changes.
Documentation-impact: none - the embedded docs/*.md corpus is unchanged; CONTRIBUTING.md (repo root) was updated to document the multi-catalogue locale flow.

@github-actions github-actions Bot added v2 Go rewrite (1.x) — main-v2 branch, active development desktop Wails desktop app (desktop/**) tui Terminal UI / CLI (internal/cli, internal/control) agent Core agent loop (internal/agent, internal/control) config Configuration & setup (internal/config) and removed v2 Go rewrite (1.x) — main-v2 branch, active development labels Sep 7, 2026
@GuidoMaxier
GuidoMaxier force-pushed the feat/es-spanish branch 2 times, most recently from d5d3102 to 275c401 Compare September 11, 2026 21:51
@GuidoMaxier

Copy link
Copy Markdown
Author

Rebased onto the current main-v2 (v1.38.7, #10151) and re-ported both catalogues. The PR is mergeable again.

What changed since the original revision:

  • Conflicts (4) resolved: Composer.tsx and check-bundle-budget.mjs now follow main-v2 (the run-strip rewrite removed the SPINNER_WORDS read we had touched), ScrollDiagnosticPanel.tsx follows its deletion upstream, and bridge.ts keeps main-v2's comment with the widened SetTrayLocale union.
  • CLI catalogue: the 8 fields main-v2 added after the original revision (ReadStatus*Fmt, ReadStatusRecovery, OperationNeedsUser, SearchModelUnavailable, ProviderErrNotFound) are now translated in es-419; completeness, placeholder and code-token parity pass.
  • Desktop dictionary: regenerated in en.ts order — 3,234 keys, 1:1 with en.ts (key set, order and {placeholder} names verified). 536 keys removed upstream are gone; the 209 new ones are translated.
  • Bundle gate fix worth reviewing: check-bundle-budget.mjs filtered locale chunks with /^(?:zh|zh-TW)-.+\.js$/, so the lazy es-*.js chunk was invisible to the gate and went unmeasured. The filter now includes es, expects 3 chunks and budgets the measured 58,071 B gzip (56.710 KiB) at a 56.8 KiB ceiling. The zh/zh-TW ceilings are untouched.
  • Dropped the unused LANGUAGE_PREFS export added in i18n.tsx; the settings picker uses its own local list, which this PR extends with "es" / "Español".

Local gates on this revision: gofmt/go vet clean, golangci-lint 0 issues, repolint clean, go test ./internal/{i18n,config,control,cli}/ ./internal/tool/builtin/ pass, tsc --noEmit 0 errors, eslint clean, pnpm build passes with the es chunk budgeted.

Two things that need a maintainer:

  1. CI has not run. The CI, CodeQL, App memory screening and Release notes workflows on this PR are stuck in action_required — they need a maintainer to approve the run for this fork. Until then nothing is compiled or tested by the repository.
  2. internal/boot reports 7 session-context failures on this machine, but they reproduce identically on a pristine upstream/main-v2 worktree, so they are environment-dependent and unrelated to this diff.

@SivanCola @esengine — could you take a look when you have a moment?

internal/i18n: new Spanish catalogue (messages_es.go, 556 fields), ArgLanguageEs in every locale, setLanguage/normalize mapping for es*, /language es completion in cli+control, config SetLanguage persistence (extracted to edit_language.go), and parity/placeholder/code-token/plan-choice test coverage.
locales/es.ts: full 3,527-key es-419 dictionary (1:1 with en.ts); startup wiring (Locale union, LANGUAGE_PREFS, SPINNER_WORDS.es, detect/preload); auxiliary dictionaries retyped Record<Exclude<Locale,"es">, ...> with existing ?? en fallbacks; SetTrayLocale accepts es; bundle-budget gates updated for the es startup wiring and the lazy es-*.js chunk.
The i18n section now describes the multi-catalogue flow (messages_es.go as the Spanish baseline) and the setLanguage/normalize, /language, and parity-test steps.
After rebasing onto main-v2: add ProviderErrWaitExhaustedFmt to messages_es.go; add the 100 new en.ts keys to es.ts, drop the 66 preset keys upstream removed (superseded by the catalog structure), and re-measure the es-*.js chunk budget (62.2 KiB -> 62.3 KiB ceiling).
Drop the two leftover conflict markers and re-align the Spanish catalogue
with the permission-preset wording that main-v2 adopted (esengine#10209).
The es-419 dictionary is 3,332 keys on the current main-v2 and measures
59567 B (58.171 KiB) gzip, so the 56.8 KiB ceiling no longer holds. Keep the
next one-decimal ceiling with bounded headroom, like the Chinese dialects.
@GuidoMaxier

Copy link
Copy Markdown
Author

Rebased onto the current main-v2 (36852da4d) and finished the pass.

  • Conflicts are gone. The previous revision still carried two unresolved >>>>>>> markers (desktop/frontend/src/components/SettingsPanel.tsx and desktop/frontend/src/lib/bridge.ts); git grep '^>>>>>' is clean now, and git merge-tree against main-v2 reports no conflicts.
  • Desktop dictionary regenerated in en.ts order — 3,332 keys, 1:1 with en.ts. The current main-v2 added 98 keys after the original revision, and all of them are translated.
  • CLI catalogue re-aligned with the permission-preset wording that #10209 adopted: the YOLO/auto-approve copy is gone and the approval prompt offers three choices, matching main-v2.
  • Bundle gate: the es chunk ceiling moved 56.8 → 58.3 KiB (measured 59,567 B = 58.171 KiB). The dictionary genuinely grew with the rebase, so the old ceiling no longer held. The zh / zh-TW ceilings are untouched.

Local gates on this revision: go test ./internal/{i18n,config,cli}/... pass, pnpm typecheck and pnpm test:typecheck 0 errors, pnpm build + check-bundle-budget.mjs 9/9 PASS (es 58.1/58.3, zh 57.6/63.3, zh-TW 58.5/64.0), locale unit tests 119/119.

CI evidence. ci.yml only triggers on pull_request against main-v2, and pull requests from a fork leave its checks in action_required, so nothing has been compiled by this repository. I ran the same commit inside my fork instead: 30 jobs green, including desktop-frontend, lint, test (ubuntu/macos/windows), race, desktop and every windows-* job — https://github.com/GuidoMaxier/DeepSeek-Reasonix/actions/runs/34788173613

The single red job there is desktop-windows-go (reasonix/desktop), which fails on the Windows runner of the fork with The native Windows restricted-token/AppContainer sandbox is unavailable — a runner capability gap, not this diff.

Still needs a maintainer: approving the workflow runs on this PR so the CI of the repository can run here. @SivanCola @esengine

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

Labels

agent Core agent loop (internal/agent, internal/control) config Configuration & setup (internal/config) desktop Wails desktop app (desktop/**) tui Terminal UI / CLI (internal/cli, internal/control) v2 Go rewrite (1.x) — main-v2 branch, active development

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant