You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: CLAUDE.md
+15Lines changed: 15 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -98,6 +98,16 @@ Check for updates to external repos we build from or depend on:
98
98
-[ ] Manifest includes `llamaServerTurbo` field
99
99
-[ ]`src-tauri/src/lib.rs` sets `CHAOSENGINE_LLAMA_SERVER_TURBO` env var
100
100
101
+
### 6. Localization (i18n)
102
+
-[ ]`npm run i18n:validate` passes — every locale parity check + ICU syntax compile + orphan key scan
103
+
-[ ] No hardcoded user-facing strings introduced in this release (extraction script `npm run i18n:extract` reports zero new keys with empty `en` values)
104
+
-[ ] All 10 shipping locales (`en`, `zh-CN`, `zh-TW`, `ja`, `de`, `ru`, `ko`, `fr`, `es`, `pt-BR`) reach ≥95 % coverage; missing keys auto-fall back to `en` at runtime
105
+
-[ ]`backend_service/locales/*/LC_MESSAGES/messages.mo` compiled via `pybabel compile`
106
+
-[ ]`src-tauri/locales/*.ftl` regenerated for any new menu / tray strings
107
+
-[ ] Pseudo-locale `en-XA` smoke-tested for layout clipping on Setup + Diagnostics tabs (widest text surface)
108
+
-[ ] CJK font fallback stack present in `styles.css` (Apple Silicon + Windows + Linux paths)
109
+
-[ ] Per-feature translation workflow followed: new en-only strings ship with `null` placeholders in other locales (runtime falls back to `en`); follow-up PR fills translations (see FU-042+ tracker rows for cadence)
110
+
101
111
---
102
112
103
113
## Follow-Ups Tracker
@@ -147,6 +157,11 @@ no longer relevant.
147
157
| ~~FU-038~~ | ~~Diagnostics cleanup: `_free_bytes` import, MallocStackLogging spam, Qwen3.6-27B alias~~ | **Shipped 2026-05-10.** | Three bugs surfaced by the live ``/api/diagnostics/snapshot`` payload from a Coder-Next + Tools repro. (1) ``backend_service/routes/diagnostics.py`` imported ``_free_bytes`` from ``backend_service.routes.setup``, but the setup package's ``__init__.py`` did not re-export it from ``gpu_bundle.py`` — the snapshot's ``extras`` section reported ``ImportError: cannot import name '_free_bytes'``. Added the re-export. (2) macOS hardened-runtime spawned every Python subprocess with three lines of ``MallocStackLogging: can't turn off malloc stack logging because it was not enabled.`` spam (we ship ``bundle.macOS.hardenedRuntime: true``). Hundreds per minute under the metrics poll, drowning out real INFO/ERROR lines. Fixed at source by ``command.env_remove("MallocStackLogging" / "MallocStackLoggingNoCompact" / "MallocScribble")`` in ``src-tauri/src/backend.rs`` so new builds don't produce the spam. Also added a regex filter (``_LOG_NOISE_PATTERNS`` + ``_filter_log_noise``) in ``diagnostics.py`` so the ``/api/diagnostics/log-tail`` and snapshot endpoints strip the spam from logs produced by older builds too — existing installs see a clean diagnostic surface without rebuilding. Filter reads 4× the requested line window so 200 useful lines survive even when the raw log is 50% spam. (3) Qwen3-Coder-Next was rebranded ``Qwen3.6-27B`` upstream; lmstudio-community MLX conversion's HF metadata reports ``mlx-community/Qwen3.6-27B-4bit`` as the canonical repo. ``model_resolution.resolve_dflash_target_ref`` prefers canonical, so ``DRAFT_MODEL_MAP`` missed and the runtimeNote said *DFLASH unavailable for 'mlx-community/Qwen3.6-27B-4bit': no compatible draft model is registered.* Aliased the three quant variants (4bit / bf16 / 8bit) back to ``Qwen/Qwen3-Coder-Next`` so the existing ``z-lab/Qwen3-Coder-Next-DFlash`` drafter resolves. New unit test pins the mapping. |
148
158
| ~~FU-037~~ | ~~Per-tab ErrorBoundary + Tauri devtools in release builds~~ | **Shipped 2026-05-10.** | A tool-call in the Chat tab against `Qwen3-Coder-Next` blanked the entire packaged macOS app — webview reload returned the user to the Dashboard, and any subsequent Chat navigation crashed again. Root cause: the React tree had no error boundary, so a single uncaught render error in one tab tore down the whole `<main>` content frame. Release builds also did not ship the WebKit inspector, so the user could not pull a stack trace without rebuilding via `cargo tauri dev`. (1) New [src/components/ErrorBoundary.tsx](src/components/ErrorBoundary.tsx) — `getDerivedStateFromError` + `componentDidCatch` capture the error, render an inline fallback with the error message, JS stack, component stack, "Try again" reset, and "Copy details" clipboard button. Wrapped around `{content}` in [src/App.tsx](src/App.tsx) keyed by `activeTab` so switching tabs is its own recovery path. (2) `src-tauri/Cargo.toml` `tauri` dep gains the `devtools` Cargo feature so right-click → Inspect Element opens WebKit devtools in release builds. (3) CSS for `.error-boundary` lives next to the existing notice banners in [src/styles.css](src/styles.css) — same colour vocabulary. Unit tests in [src/components/__tests__/ErrorBoundary.test.ts](src/components/__tests__/ErrorBoundary.test.ts) pin the static-derive contract so the boundary cannot silently stop catching errors. Frontend errors land in the webview console; backend errors land in the Diagnostics tab + the in-memory `app.state.chaosengine` log buffer. |
149
159
| ~~FU-034~~ | ~~Hide unrecoverable launch-modal options instead of greying them out~~ | **Shipped 2026-05-10.** | The launch settings panel ([src/components/RuntimeControls.tsx](src/components/RuntimeControls.tsx)) used to render every cache-strategy card and the DFlash speculative-decoding toggle for every model + engine combo, with disabled checkboxes + "N/A" badges when an option could not run. That taught users the wrong thing — a disabled card with no install button suggests something they could fix, when the only fix lived outside the app or did not exist at all. New rule: **hide options the user has no in-app path to recover.** (1) Cache-strategy cards now skip render when the strategy is engine-incompatible (e.g. TriAttention selected on the MLX engine — engine mismatch is fundamental, no install button helps) or when the strategy needs the turbo binary on a GGUF backend without `llama-server-turbo` present (only fix is `scripts/build-llama-turbo.sh` outside the app). (2) The DFlash toggle hides entirely when the selected model has no draft in [`DRAFT_MODEL_MAP`](dflash/__init__.py) or the engine is GGUF (DFlash needs MLX/vLLM). The "DFlash package not installed but model would be supported" case stays visible — the install button gets the user to ready in one click. ``native`` always survives. Hardcoded `f825ffb` install hint string in the DFlash help panel was the same drift bug from FU-033 — fixed alongside (now `fada1eb`). The popover-side filter ([src/components/kvStrategyFilter.ts](src/components/kvStrategyFilter.ts)) already followed this rule, so the modal now matches. |
160
+
| FU-042 | i18n Phase 0 — infra scaffold + IME composition fix | **In progress (started 2026-05-11).** | Foundation work for full-stack localization. Adds `react-i18next` + `i18next-icu` + `i18next-browser-languagedetector` (FE), `Babel` (Py), `rust-i18n` + `fluent-bundle` (Rs). Creates `src/locales/`, `backend_service/locales/`, `src-tauri/locales/` directory trees with namespaced JSON / `.po` / `.ftl` files. Wires `i18n/index.ts` provider in `src/main.tsx`, FastAPI `Accept-Language` middleware in `backend_service/i18n.py`, `rust-i18n!` macro in `src-tauri/src/i18n.rs`. Adds `locale` field to settings (TS + Py + Rs). Builds Settings → Language dropdown rendering endonyms. Builds first-launch banner that detects OS lang ≠ en and prompts user. Adds `<html lang="…">` sync + CJK font-fallback CSS stack. Writes `scripts/i18n-extract.mjs` / `i18n-validate.mjs` / `i18n-pseudo.mjs` (pseudo-locales `en-XA` + `en-XB` dev-only). Hooks `i18n-validate` into `pre-build-check.sh` + `.mjs`. Fixes IME `e.isComposing` guard on prompt textarea Enter-to-send (latent bug breaking JP/CN/KR IME users). Audits `src/utils/format.ts` to thread `locale` arg into `Intl.NumberFormat` / `Intl.DateTimeFormat` helpers. Per CLAUDE.md §6, en-only feature commits ship with `null` placeholders in other locales — runtime falls back to `en`. Adds `THIRD_PARTY_NOTICES.md` rows for all 5 new deps (MIT × 3, Apache-2.0 × 1, BSD-3 × 1). Coverage gate is warn-only v1 with dashboard panel in Diagnostics tab. Wraps with FU-043 Phase 1 translations. |
161
+
| FU-043 | i18n Phase 1 — anchor locales (en + zh-CN + ja) | Follows FU-042 | First user-visible localization: ships English baseline + Simplified Chinese (Qwen / DeepSeek / GLM author origin) + Japanese (Sakana AI / ELYZA / heavy Apple-Silicon-tinkerer cohort). Highest-leverage trio given Hugging Face + r/LocalLLaMA demographics. AI-translated (Claude) against a pre-locked `GLOSSARY.md` per locale pinning tech terms (`KV cache`, `tokens/sec`, `quantization`, `inference`, `cache strategy`, etc.) so phrasing stays consistent across 200+ keys. Layout audit pass for CJK glyph density (CJK runs ~30 % narrower than en; verify no fixed-width buttons clip). Live QA matrix: 5 tabs × {happy path, error path, empty state} per locale = ~30 cells. |
162
+
| FU-044 | i18n Phase 2 — EU tier (de + fr + es + ru) | Follows FU-043 | Adds German (DiscoLM / LeoLM origin, privacy-first crowd), French (Mistral / CroissantLLM homeland), Spanish (LatAm + Iberia, Salamandra / RigoChat), Russian (Saiga / Vikhr / IlyaGusev — strong r/LocalLLaMA presence). Wide-string layout pass critical for `de` (30–50 % wider than `en`, especially in Setup install descriptions). Slavic 4-form plural pass for `ru` via ICU MessageFormat (one / few / many / other — different rules than the en `plural`). Tauri window minimum width may need bump after `de` audit. |
163
+
| FU-045 | i18n Phase 3 — completion tier (ko + pt-BR + zh-TW) | Follows FU-044 | Closes the top-10 locale set: Korean (Upstage Solar / LG EXAONE / Kakao crowd, heavy benchmark scene), Brazilian Portuguese (large maker base, separate from `pt-PT` — both vocab + diacritics differ), Traditional Chinese (Taiwan / Hong Kong; TAIDE / Breeze authors, distinct vocab + idiom from `zh-CN` so it's a separate locale not a variant). Opens contributor PR flow with `GLOSSARY.md` lock + README contributor docs. Diagnostics tab gets a coverage panel showing per-locale `%`. |
164
+
| FU-046 | i18n Phase 4 — long tail + RTL prep | Opportunistic / community-driven | Stretch locales as community PRs land ≥80 % coverage: `pl` (Bielik / SpeakLeash), `it` (Camoscio / Minerva), `uk` (DragoMan), `tr` (Trendyol-LLM), `vi` (VinaLlama / PhoGPT), `nl` / `sv` / `cs` (smaller but loud cohorts). RTL infrastructure prep for future `ar` (Jais / Fanar) + `he`: convert remaining `margin-left` / `padding-right` to logical properties (`margin-inline-start` / `padding-inline-end`); add `dir="auto"` to root + per-locale override; rehearse bidi flow via pseudo-locale `en-XB`. Don't ship `ar` / `he` until logical-property migration verified end-to-end. |
0 commit comments