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
The Chinese tech Twitter audience is a real userbase right now. We already have:
`crates/tui/src/localization.rs` — Chinese-Simplified (`zh-Hans`) translations for 27 `MessageId` constants (composer placeholder, history search, config modal, help modal). Full coverage for the surface that's wired through `MessageId`.
`README.zh-CN.md` — Chinese README, kept in sync with English.
`Settings.locale` accepts `zh-Hans`, with `zh-CN` as an alias (`localization.rs:536`).
What's not translated yet — most of what a Chinese-speaking user actually sees during a session:
Slash command descriptions and `usage:` strings — `crates/tui/src/commands/mod.rs:109-375` has ~50 `CommandInfo` entries with English-only `description` and `usage` fields. `/help` renders these directly.
Status messages and toasts — `app.status_message = Some("...".to_string())` call sites are English-only. Same for `StatusToast`.
Error messages surfaced to the user — `anyhow!` contexts (`failed to read directory`, `shell manager lock poisoned`, …), `ToolError` (`path_escape`, `missing_field`), and `format_tool_error` in the engine.
Doctor / setup / onboarding output — `deepseek doctor`, the first-run setup wizard, the missing-companion-binary error message (`bb88ab91`, English-only).
Footer text and labels — mode indicators ("AGENT", "YOLO", "PLAN"), mode hints ("Tab to switch mode"), and the cost/context summary line.
Why this is worth a milestone-sized effort
Without this expansion, a `zh-Hans`-locale user gets a Chinese composer hint and a Chinese config modal, then English everything else once they actually start working. The locale switch is currently more cosmetic than functional. Two consequences:
Bug reports won't translate. Error messages like "path escapes workspace" are unreadable to a non-English speaker, so they screenshot and we need to translate by hand.
Pointless first-impression cost. A Chinese-speaking user runs `deepseek` for the first time, gets a localized welcome, and then sees "Token Usage: ─── Active context: ~123 / 1000000" — sets the expectation that the rest of the tool is half-translated.
Scope of this issue
Concrete scope to land in v0.8.5 (or later — pick your milestone):
Phase 1 — high-traffic user-facing surfaces
Slash command help text — add `description_id: MessageId` next to `description: &str` in `CommandInfo`. Render via `tr(locale, id)`. Affects ~50 entries; mostly mechanical.
`/tokens`, `/cost`, `/cache` (the debug commands) — these are paste-into-bug-report surfaces. Translate the labels ("Active context", "Last API input", "Cache hit/miss", "Approx session cost", "Σ in", "avg hit ratio", …). Numbers stay numeric.
`/help` — already routes through MessageId; verify the Chinese strings match the new command set after Phase 1 lands.
Footer mode labels — "AGENT/YOLO/PLAN" can stay (they're capitalized acronyms now and a recognizable brand), but the hint strings ("Tab=switch mode", etc.) should localize.
Doctor output — `deepseek doctor` is the first thing a frustrated user runs. Translate the section headings and the verdict lines.
Missing-companion-binary error (`bb88ab91`) — already a long localized message in English, deserves zh-Hans.
`deepseek init` prompts — the project-context initialization wizard.
Phase 3 — error messages
`format_tool_error` (`core/engine.rs`) — every tool failure that surfaces to the user.
Sandbox-denial messages (`SandboxManager::denial_message`) — the macOS Seatbelt / Linux Landlock / Windows messages.
`approval_*` messages — what users see when the approval prompt fires.
Out of scope intentionally
Tool descriptions sent to the model (`tool.description()`) — these stay English so DeepSeek's training data alignment isn't disturbed and the prefix cache doesn't fork into per-locale variants.
The base system prompt — same reason. The model speaks the user's language because `zh-Hans` users ask in Chinese, not because we translated the prompt.
Implementation notes
Add MessageIds in alphabetical groups so the diff stays reviewable.
Add a CI test that asserts every locale function returns `Some(_)` for every `MessageId` in `ALL_MESSAGE_IDS` — there's already a partial check in `localization.rs:524+`; tighten it to fail on any missing id.
Consider hiring a native zh-Hans speaker for review pass after the mechanical translation. The current 27 strings are clean (verified by reading them), but the 200-300 strings this expansion adds are too many to vibe-check without a native speaker.
Context
The Chinese tech Twitter audience is a real userbase right now. We already have:
What's not translated yet — most of what a Chinese-speaking user actually sees during a session:
Why this is worth a milestone-sized effort
Without this expansion, a `zh-Hans`-locale user gets a Chinese composer hint and a Chinese config modal, then English everything else once they actually start working. The locale switch is currently more cosmetic than functional. Two consequences:
Scope of this issue
Concrete scope to land in v0.8.5 (or later — pick your milestone):
Phase 1 — high-traffic user-facing surfaces
Phase 2 — onboarding and setup
Phase 3 — error messages
Out of scope intentionally
Implementation notes
Related