Skip to content

feat(il): P11 i18n — full 10-locale set (es/fr/ja/ko/pt/ru/zh-CN/zh-TW)#452

Merged
Luis85 merged 21 commits into
nextfrom
feature/i18n-locales
May 27, 2026
Merged

feat(il): P11 i18n — full 10-locale set (es/fr/ja/ko/pt/ru/zh-CN/zh-TW)#452
Luis85 merged 21 commits into
nextfrom
feature/i18n-locales

Conversation

@Luis85
Copy link
Copy Markdown
Owner

@Luis85 Luis85 commented May 27, 2026

P11 — i18n full locale set (claudian-reboot)

Adds the 8 missing locales to reach the charter §3.9 ten (de/en/es/fr/ja/ko/pt/ru/zh-CN/zh-TW). Spec: specs/i18n-locales/ (PRD-IL-001, DESIGN-IL-001, SPEC-IL-001..009, no new ADR, TASKS-IL-001 = 13 tasks). Mechanical + additive.

Delivered (T-IL-001..011)

  • 8 new locale catalogs src/ui/i18n/locales/{es,fr,ja,ko,pt,ru,zh-CN,zh-TW}.ts — each a full translation of en.ts, structurally matching en's 226-leaf keyset exactly, placeholders preserved verbatim, brand tokens intact, claudian wording reference. zh-CN ≠ zh-TW (Simplified vs Traditional).
  • Widened SupportedLocale / SUPPORTED_LOCALES / messages to the 10; toSupportedLocale body unchanged (auto-extends; narrows the 10 incl. zh-CN/zh-TW, unknown→en, fallback en).
  • Generalised the key-parity test to all-10-against-en (snapshot-at-load) + a placeholder-multiset test + the forbidden-terms guard over all 10 + narrowing/fallback coverage.

Gate (local, green)

vue-tsc 0 · eslint 0 · vitest 286 files / 2179 passed (0 errors) (incl. the all-10 parity/placeholder/forbidden-terms gates) · build + build:web + docs:api clean · npm audit --audit-level=high clean. Bundle: plugin main.js 1.91 MB (+~92 KB / gzip +~22 KB for the 8 catalogs); standalone 428 KB. Acceptable for the locale data (app-bundled, not externalized).

Parity self-review (Stage 9)

review.md APPROVE (0 blockers). All-10 automated gates green (reviewer-confirmed); additivity confirmed (en/de/manifest byte-identical; the index.ts widen = the 4 specced sites); fr/zh-CN spot-checked genuinely translated. The permission.plan all-caps-badge CJK rendering is a non-blocking script fact → folded into the deferred native-speaker polish.

Deferred — final epic gate

T-IL-012 — native-speaker / professional linguistic polish of the 8 machine-assisted translations (non-gating; accumulates for the final review).

🤖 Generated with Claude Code

Symprowire and others added 21 commits May 27, 2026 01:36
Cut feature/i18n-locales off next (P0-P10 merged). Scope = parity-charter §3.9 — add
the 8 missing locales (es/fr/ja/ko/pt/ru/zh-CN/zh-TW) matching en's keyset exactly;
widen SupportedLocale/SUPPORTED_LOCALES/messages/toSupportedLocale to 10; generalise
the en↔de key-parity test to all-10-against-en. Translate from our en.ts (claudian
JSONs = wording reference). Largely mechanical + additive. Autonomous; SPLIT the locale
impl into 2-3-locale chunks (timeout lesson). Next: /spec:requirements.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
12 REQ-IL + 9 NFR-IL (concise — mechanical phase). 10 locales registered/selectable;
all-10 leaf-keyset parity against en (generalise the en↔de test); toSupportedLocale
narrows the 10 incl. zh-CN/zh-TW (unknown→en, fallback en); placeholder multiset
preserved (CLAR-IL-001 → dedicated test); forbidden-terms guard green for all locales;
en/de byte-identical; missing key → en fallback no crash; build succeeds (note bundle
delta). Keyset = our en.ts; claudian JSONs = wording reference only.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Additive 2→10 widening: SupportedLocale union + SUPPORTED_LOCALES + messages
registration to all 10; toSupportedLocale body UNCHANGED (membership test auto-extends,
covers zh-CN/zh-TW, unknown→en). 8 new locales/<code>.ts mirror de.ts (en's exact keyset,
placeholders preserved, claudian wording). All-10 key-parity test (snapshot-at-load) +
placeholder-multiset test + forbidden-terms-all-10. en/de byte-identical; fallback→en.
EC-IL-001..010. Chunks: es/fr/pt · ja/ko · zh-CN/zh-TW/ru · wiring+tests. No new ADR/port.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
T-IL-001 baseline+guard-verify (NO new key/port — additive string-union widen);
locale-file chunks es/fr/pt · ja/ko · zh-CN/zh-TW/ru; wiring widen index.ts (4 sites);
test tasks all-10 key-parity (snapshot-at-load) + placeholder-multiset + forbidden-terms-
all-10 + narrowing/fallback; gate (full verify + bundle delta + draft PR). Native-speaker
polish deferred (non-gating). Orchestrator note: land the 8 locale FILES before the
index widen so typecheck stays green (importing absent files would break it), then
wiring+tests, then gate.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add Spanish (es) translation of en.ts under src/ui/i18n/locales/es.ts —
exact en keyset (226 leaves, 0 missing / 0 extra), every leaf an idiomatic
Spanish string, every {token} interpolation placeholder preserved verbatim.
Mirrors de.ts file shape; index.ts wiring deferred to T-IL-002.

SPEC-IL-002, SPEC-IL-003, REQ-IL-002, REQ-IL-007, REQ-IL-008. Language: Spanish.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add French (fr) translation of en.ts under src/ui/i18n/locales/fr.ts —
exact en keyset (226 leaves, 0 missing / 0 extra), every leaf an idiomatic
French string, every {token} interpolation placeholder preserved verbatim.
Mirrors de.ts file shape; index.ts wiring deferred to T-IL-002.

SPEC-IL-002, SPEC-IL-003, REQ-IL-002, REQ-IL-007, REQ-IL-008. Language: French.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add Portuguese (pt) translation of en.ts under src/ui/i18n/locales/pt.ts —
exact en keyset (226 leaves, 0 missing / 0 extra), every leaf an idiomatic
Portuguese string, every {token} interpolation placeholder preserved verbatim.
Mirrors de.ts file shape; index.ts wiring deferred to T-IL-002.

SPEC-IL-002, SPEC-IL-003, REQ-IL-002, REQ-IL-007, REQ-IL-008. Language: Portuguese.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Create specs/i18n-locales/implementation-log.md with the Romance-chunk entry
(es/fr/pt): 226-leaf parity vs en.ts, 0 placeholder mismatches, 0 forbidden-term
offenders, claudian wording reference, per-locale commit SHAs.

SPEC-IL-003, REQ-IL-002.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add the Japanese (ja) locale catalogue: a full `export default {…} as const`
mirror of `en.ts` with all 226 leaves translated. Placeholders preserved
verbatim per key; brand tokens (Specorator/Claude/Codex/Opencode/MCP) carried
through; "API キー" confined to the whitelisted settings./provider secret keys.

Trace: SPEC-IL-002, REQ-IL-002.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Add the Korean (ko) locale catalogue: a full `export default {…} as const`
mirror of `en.ts` with all 226 leaves translated. Placeholders preserved
verbatim per key; brand tokens (Specorator/Claude/Codex/Opencode/MCP) carried
through; "API 키" confined to the whitelisted settings./provider secret keys.

Trace: SPEC-IL-002, REQ-IL-002.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Append the T-IL-008 CJK section to the implementation log: per-locale commit
SHAs, 226-leaf parity, placeholder/forbidden-terms verification, claudian
wording reference.

Trace: SPEC-IL-002, REQ-IL-002.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Full Simplified Chinese (zh-Hans) translation of en.ts: 226-leaf keyset
exact match, every {placeholder} preserved verbatim, brand tokens and the
whitelisted "API key" strings carried per en.

Implements SPEC-IL-002. Traces REQ-IL-002.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Full Traditional Chinese (zh-Hant) translation of en.ts: 226-leaf keyset
exact match, every {placeholder} preserved verbatim, brand tokens and the
whitelisted "API key" strings carried per en. Diverges from zh-CN where
Simplified/Traditional and Taiwan UI idiom differ.

Implements SPEC-IL-002. Traces REQ-IL-002.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Full Russian translation of en.ts: 226-leaf keyset exact match, every
{placeholder} preserved verbatim, brand tokens and the whitelisted
"API key" strings carried per en.

Implements SPEC-IL-002. Traces REQ-IL-002.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Records the three CJK + Cyrillic catalogue commits with keyset-parity,
placeholder, forbidden-terms, and zh-CN/zh-TW divergence evidence.

Implements SPEC-IL-002. Traces REQ-IL-002.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Record the en.ts keyset (226 leaves), the placeholder inventory (35
interpolating leaves, 17 distinct tokens), the all-9-non-en parity +
placeholder + forbidden-terms baseline (0 missing/extra/mismatch/offenders),
the claudian WORDING-only reference + the deferred native-speaker-polish leg
(T-IL-012, P12), the two-locale bundle-baseline note (delta recorded by
T-IL-013), and the guard verdict: NO new InjectionKey/port, NO guard-relax,
en/de/manifest untouched. No src/ change.

Implements TEST-IL targets. SPEC-IL-003/004/005/006/007/009 §1-7.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Widen the four declaration sites in src/ui/i18n/index.ts from 2 → 10:
SupportedLocale union ('en'|'de'|'es'|'fr'|'ja'|'ko'|'pt'|'ru'|'zh-CN'|
'zh-TW'); SUPPORTED_LOCALES array (en first, de second, alphabetical, zh-*
last); the eight catalogue imports; the ten-entry messages map (quoted
'zh-CN'/'zh-TW' keys), keeping the `as unknown as Record<SupportedLocale,
MessageSchema>` cast and fallbackLocale: 'en'. toSupportedLocale body
byte-unchanged (narrows via SUPPORTED_LOCALES → auto-extends to all ten incl.
the regional tags; unknown → 'en'); the stale doc-comment example fr → it.

No new function/port/InjectionKey/composable; no obsidian/node:* import.

Implements SPEC-IL-001, SPEC-IL-002. REQ-IL-001/005/006, NFR-IL-005.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
…ests

Generalise tests/ui/i18n/index.test.ts from en↔de to all ten locales — these
three test legs are co-located in the one shared file per SPEC-IL spec:

- T-IL-003 (TEST-IL-003/004, SPEC-IL-004): replace the en↔de key-parity block
  with a table-driven all-ten-against-en assertion over
  SUPPORTED_LOCALES.filter(c => c !== 'en'); snapshot each locale's leafKeys at
  module load (dodging the i18nMerge mutation); assert missing/extra both [] with
  a locale+keys failure message.
- T-IL-004 (TEST-IL-008, SPEC-IL-005): placeholder-multiset test — per non-en
  locale, per en leaf key, value.match(/\{[^}]+\}/g) multiset === en's; failure
  names locale+key+diff; no-placeholder leaf passes trivially.
- T-IL-006 (TEST-IL-001/002/005/006/011, SPEC-IL-001/002/008): registration
  completeness (length 10 + SUPPORTED_LOCALES set deep-equals the messages-map
  key set + every entry non-empty), per-catalogue import shape, narrows-the-ten
  round-trip (incl. zh-CN/zh-TW), unknown→en (it/zh/''/EN/de-DE), and the
  synthetic missing-key fallback (en string, no throw).

The existing i18nMerge/flatToNested + agent.empty.placeholder tests are
unchanged. 51 tests green. REQ-IL-001..006/008/011, NFR-IL-001/002/004,
EC-IL-001..004/006..009.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Generalise tests/i18n/forbidden-terms.test.ts from the en-only scan to a
table-driven scan over all ten catalogues (SUPPORTED_LOCALES). Reuse the
unchanged FORBIDDEN (/\bAPI key\b/i, /\bsubprocess\b/i, /\bSDK\b/i), flatten,
and isAllowed helpers; ALLOWED_PREFIXES is byte-unchanged from P9. Each locale
asserts zero offenders outside the allow-list with a locale+key+value+pattern
failure message; a note records that any ALLOWED_PREFIXES extension is a
defect-escalation (EC-IL-005), not a default. 10 locales scanned, 0 offenders.

Implements TEST-IL-009. SPEC-IL-006, REQ-IL-009, NFR-IL-003, EC-IL-005.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Append Layer A implementation-log entries for T-IL-001 (baseline + guard
verdict), T-IL-002 (index widen), T-IL-003/004/006 (all-ten parity +
placeholder + registration/narrowing/fallback), T-IL-005 (forbidden-terms
all-ten) with their real commit SHAs; mark the prior catalogue entries'
"all-ten parity test does not exist yet" deviation note superseded. Tick the
T-IL-001..006 DoD boxes (the two-locale bundle baseline deferred to T-IL-013;
the RED-first boxes annotated GREEN-after-catalogues since T-IL-007..009 landed
first). Update workflow-state.md artifacts (implementation-log.md / test-plan.md
in-progress) + a Stage 7 hand-off note: vue-tsc 0, lint 0 errors, 61 i18n tests
green; gate chunk T-IL-010..013 remain.

SPEC-IL-001..009 §wiring+tests chunk.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
REVIEW-IL-001 verdict APPROVE (0 blockers). All-10 automated gates green (key-parity +
placeholder-multiset + forbidden-terms-all-10 + narrowing/fallback, 61 tests). Additivity
confirmed (en/de/manifest byte-identical; index widen = the 4 specced sites; toSupportedLocale
body unchanged). Spot-checked fr/zh-CN genuinely translated, brand tokens intact, zh-CN≠zh-TW.
permission.plan CJK-badge rendering non-blocking → native-polish (T-IL-012, deferred). TRACE-IL-001
all 12 REQ-IL chained. Native-speaker polish pending for the final epic gate.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copy link
Copy Markdown

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: e06984ccce

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/ui/i18n/index.ts
Comment on lines +31 to +35
export const SUPPORTED_LOCALES: SupportedLocale[] = [
'en',
'de',
'es',
'fr',
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Wire new locales into the settings selector

This commit registers eight additional locales in SUPPORTED_LOCALES, but users still cannot choose them from the plugin UI because the locale dropdown is still driven by the hard-coded settingsSchema options (en/de only in src/core/core-settings.ts) and rendered directly from those options in SpecoratorSettingTab.addControl (src/plugin/settings.ts). In practice, the new locales are only reachable by manually editing persisted settings, so the feature is incomplete for normal users.

Useful? React with 👍 / 👎.

@Luis85 Luis85 merged commit d473346 into next May 27, 2026
6 checks passed
@Luis85 Luis85 deleted the feature/i18n-locales branch May 27, 2026 00:43
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.

2 participants