9.8 KiB
App i18n Audit (Remaining Work)
Scope: packages/app/
Date: 2026-01-20
This report documents the remaining user-facing strings in packages/app/src that are still hardcoded (not routed through useLanguage().t(...) / translation keys), plus i18n-adjacent issues like locale-sensitive formatting.
Current State
- The app uses
useLanguage().t("...")with dictionaries inpackages/app/src/i18n/en.tsandpackages/app/src/i18n/zh.ts. - Recent progress (already translated):
packages/app/src/pages/home.tsx,packages/app/src/pages/layout.tsx,packages/app/src/pages/session.tsx,packages/app/src/components/prompt-input.tsx,packages/app/src/components/dialog-connect-provider.tsx,packages/app/src/components/session/session-header.tsx,packages/app/src/pages/error.tsx(plus new keys added in both dictionaries). - Dictionary parity check:
en.tsandzh.tscurrently contain the same key set (354 keys each; no missing or extra keys).
Methodology
- Scanned
packages/app/src(excludingpackages/app/src/i18n/*and tests). - Grepped for:
- Hardcoded JSX text nodes (e.g.
>Some text<) - Hardcoded prop strings (e.g.
title="...",placeholder="...",label="...",description="...",Tooltip value="...") - Toast/notification strings, default fallbacks, and error message templates.
- Hardcoded JSX text nodes (e.g.
- Manually reviewed top hits to distinguish:
- User-facing UI copy (needs translation)
- Developer-only logs (
console.*) (typically does not need translation) - Technical identifiers (e.g.
MCP,LSP, URLs) (may remain untranslated by choice).
Highest Priority: Pages
1) Error Page
File: packages/app/src/pages/error.tsx
Completed (2026-01-20):
- Localized page UI copy via
error.page.*keys (title, description, buttons, report text, version label). - Localized error chain framing and common init error templates via
error.chain.*keys. - Kept raw server/provider error messages as-is when provided (only localizing labels and structure).
Highest Priority: Components
2) Prompt Input
File: packages/app/src/components/prompt-input.tsx
Completed (2026-01-20):
- Localized placeholder examples by replacing the hardcoded
PLACEHOLDERSlist withprompt.example.*keys. - Localized toast titles/descriptions via
prompt.toast.*and reusedcommon.requestFailedfor fallback error text. - Localized popover empty states and drag/drop overlay copy (
prompt.popover.*,prompt.dropzone.label). - Localized smaller labels (slash "custom" badge, attach button tooltip, Send/Stop tooltip labels).
- Kept the
ESCkeycap itself untranslated (key label).
3) Provider Connection / Auth Flow
File: packages/app/src/components/dialog-connect-provider.tsx
Completed (2026-01-20):
- Localized all user-visible copy via
provider.connect.*keys (titles, statuses, validations, instructions, OpenCode Zen onboarding). - Added
common.submitand used it for both API + OAuth submit buttons. - Localized the success toast via
provider.connect.toast.connected.*.
4) Session Header (Share/Publish UI)
File: packages/app/src/components/session/session-header.tsx
Completed (2026-01-20):
- Localized search placeholder via
session.header.search.placeholder. - Localized share/publish UI via
session.share.*keys (popover title/description, button states, copy tooltip). - Reused existing command keys for toggle/share tooltips (
command.review.toggle,command.terminal.toggle,command.session.share).
Medium Priority: Components
5) New Session View
File: packages/app/src/components/session/session-new-view.tsx
Untranslated strings
- "New session"
- "Main branch" / "Main branch ({branch})"
- "Create new worktree"
- "Last modified"
6) Context Usage Tooltip
File: packages/app/src/components/session-context-usage.tsx
Untranslated tooltip labels
- "Tokens", "Usage", "Cost"
- "Click to view context"
Locale formatting issue
- Uses
new Intl.NumberFormat("en-US", { style: "currency", currency: "USD" }). - Recommendation: format using the active locale (e.g.
language.locale()), or at leastnavigator.language.
7) Session Context Tab (Formatting)
File: packages/app/src/components/session/session-context-tab.tsx
- Already uses many translation keys for labels (e.g.
context.breakdown.system). - Still forces
Intl.NumberFormat("en-US", ...)for currency. - Has some non-translated fallback symbols like "--" and "-" style output (e.g. "---" / "-" / "--" equivalent "--" is used as "—" in code).
- If you want fully localized punctuation, these should become keys as well.
8) LSP Indicator
File: packages/app/src/components/session-lsp-indicator.tsx
Untranslated strings
- Tooltip: "No LSP servers"
- Label suffix: "{connected} LSP" (acronym likely fine; the framing text should be localized)
9) Session Tab Close Tooltip
File: packages/app/src/components/session/session-sortable-tab.tsx
Untranslated strings
- Tooltip: "Close tab"
Note: you already have common.closeTab.
10) Titlebar Tooltip
File: packages/app/src/components/titlebar.tsx
Untranslated strings
- "Toggle sidebar"
Note: can likely reuse command.sidebar.toggle.
11) Model Selection "Recent" Group
File: packages/app/src/components/dialog-select-model.tsx
Untranslated / fragile string
- Hardcoded category name comparisons against "Recent".
Recommendation: introduce a key (e.g. model.group.recent) and ensure both the grouping label and the comparator use the localized label, or replace the comparator with an internal enum.
12) Select Server Dialog Placeholder (Optional)
File: packages/app/src/components/dialog-select-server.tsx
- Placeholder:
http://localhost:4096
This is an example URL; you may choose to keep it as-is even after translating surrounding labels.
Medium Priority: Context Modules
13) OS/Desktop Notifications
File: packages/app/src/context/notification.tsx
Untranslated notification titles / fallback copy
- "Response ready"
- "Session error"
- Fallback description: "An error occurred"
Recommendation: notification.session.* namespace (separate from the permission/question notifications already added).
14) Global Sync (Bootstrap Errors + Toast)
File: packages/app/src/context/global-sync.tsx
Untranslated toast title
Failed to load sessions for ${project}
Untranslated fatal init error
Could not connect to server. Is there a server running at \${globalSDK.url}`?`
15) File Load Failure Toast (Duplicate)
Files:
packages/app/src/context/file.tsxpackages/app/src/context/local.tsx
Untranslated toast title
- "Failed to load file"
Recommendation: create one shared key (e.g. toast.file.loadFailed.title) and reuse it in both contexts.
16) Terminal Naming (Tricky)
File: packages/app/src/context/terminal.tsx
- User-visible terminal titles are generated as "Terminal" and "Terminal N".
- There is parsing logic
^Terminal (\d+)$to compute the next number.
Recommendation:
- Either keep these English intentionally (stable internal naming), OR
- Change the data model to store a stable numeric
titleNumberand render the localized display label separately.
Low Priority: Utils / Dev-Only Copy
17) Default Attachment Filename
File: packages/app/src/utils/prompt.ts
- Default filename fallback: "attachment"
Recommendation: common.attachment or prompt.attachment.defaultFilename.
18) Dev-only Root Mount Error
File: packages/app/src/entry.tsx
- Dev-only error string: "Root element not found..."
This is only thrown in DEV and is more of a developer diagnostic. Optional to translate.
Prioritized Implementation Plan
packages/app/src/components/session/session-new-view.tsxpackages/app/src/components/session-context-usage.tsx+ locale formatting improvements (alsopackages/app/src/components/session/session-context-tab.tsx)- Small stragglers:
packages/app/src/components/session-lsp-indicator.tsxpackages/app/src/components/session/session-sortable-tab.tsxpackages/app/src/components/titlebar.tsxpackages/app/src/components/dialog-select-model.tsxpackages/app/src/context/notification.tsxpackages/app/src/context/global-sync.tsxpackages/app/src/context/file.tsx+packages/app/src/context/local.tsxpackages/app/src/utils/prompt.ts
- Decide on the terminal naming approach (
packages/app/src/context/terminal.tsx).
Suggested Key Naming Conventions
To keep the dictionaries navigable, prefer grouping by surface:
error.page.*,error.chain.*prompt.*(including examples, tooltips, empty states, toasts)provider.connect.*(auth flow UI + validation + success)session.share.*(publish/unpublish/copy link)context.usage.*(Tokens/Usage/Cost + call to action)lsp.*(and potentiallymcp.*if expanded)notification.session.*toast.file.*,toast.session.*
Also reuse existing command keys for tooltip titles whenever possible (e.g. command.sidebar.toggle, command.review.toggle, command.terminal.toggle).
Appendix: Remaining Files At-a-Glance
Pages:
- (none)
Components:
packages/app/src/components/session/session-new-view.tsxpackages/app/src/components/session-context-usage.tsxpackages/app/src/components/session/session-context-tab.tsx(formatting locale)packages/app/src/components/session-lsp-indicator.tsxpackages/app/src/components/session/session-sortable-tab.tsxpackages/app/src/components/titlebar.tsxpackages/app/src/components/dialog-select-model.tsxpackages/app/src/components/dialog-select-server.tsx(optional URL placeholder)
Context:
packages/app/src/context/notification.tsxpackages/app/src/context/global-sync.tsxpackages/app/src/context/file.tsxpackages/app/src/context/local.tsxpackages/app/src/context/terminal.tsx(naming)
Utils:
packages/app/src/utils/prompt.tspackages/app/src/entry.tsx(dev-only)