262 lines
9.6 KiB
Markdown
262 lines
9.6 KiB
Markdown
# 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 in `packages/app/src/i18n/en.ts` and `packages/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`, `packages/app/src/components/session/session-new-view.tsx`, `packages/app/src/components/session-context-usage.tsx`, `packages/app/src/components/session/session-context-tab.tsx` (plus new keys added in both dictionaries).
|
|
- Dictionary parity check: `en.ts` and `zh.ts` currently contain the same key set (362 keys each; no missing or extra keys).
|
|
|
|
## Methodology
|
|
|
|
- Scanned `packages/app/src` (excluding `packages/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.
|
|
- 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 `PLACEHOLDERS` list with `prompt.example.*` keys.
|
|
- Localized toast titles/descriptions via `prompt.toast.*` and reused `common.requestFailed` for 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 `ESC` keycap 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.submit` and 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`
|
|
|
|
Completed (2026-01-20):
|
|
|
|
- Reused existing `command.session.new` for the heading.
|
|
- Localized worktree labels via `session.new.worktree.*` (main branch, main branch w/ branch name, create worktree).
|
|
- Localized "Last modified" via `session.new.lastModified` and used `language.locale()` for Luxon relative time.
|
|
|
|
### 6) Context Usage Tooltip
|
|
|
|
File: `packages/app/src/components/session-context-usage.tsx`
|
|
|
|
Completed (2026-01-20):
|
|
|
|
- Localized tooltip labels + CTA via `context.usage.*` keys.
|
|
- Switched currency and number formatting to the active locale (`language.locale()`).
|
|
|
|
### 7) Session Context Tab (Formatting)
|
|
|
|
File: `packages/app/src/components/session/session-context-tab.tsx`
|
|
|
|
Completed (2026-01-20):
|
|
|
|
- Switched currency formatting to the active locale (`language.locale()`).
|
|
- Also used `language.locale()` for number/date formatting.
|
|
- Note: "—" placeholders remain hardcoded; optional to localize.
|
|
|
|
### 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.tsx`
|
|
- `packages/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 `titleNumber` and 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
|
|
|
|
1. Small stragglers:
|
|
- `packages/app/src/components/session-lsp-indicator.tsx`
|
|
- `packages/app/src/components/session/session-sortable-tab.tsx`
|
|
- `packages/app/src/components/titlebar.tsx`
|
|
- `packages/app/src/components/dialog-select-model.tsx`
|
|
- `packages/app/src/components/dialog-select-server.tsx` (optional URL placeholder)
|
|
2. Context modules:
|
|
- `packages/app/src/context/notification.tsx`
|
|
- `packages/app/src/context/global-sync.tsx`
|
|
- `packages/app/src/context/file.tsx` + `packages/app/src/context/local.tsx`
|
|
- `packages/app/src/utils/prompt.ts`
|
|
3. 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 potentially `mcp.*` 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-lsp-indicator.tsx`
|
|
- `packages/app/src/components/session/session-sortable-tab.tsx`
|
|
- `packages/app/src/components/titlebar.tsx`
|
|
- `packages/app/src/components/dialog-select-model.tsx`
|
|
- `packages/app/src/components/dialog-select-server.tsx` (optional URL placeholder)
|
|
|
|
Context:
|
|
- `packages/app/src/context/notification.tsx`
|
|
- `packages/app/src/context/global-sync.tsx`
|
|
- `packages/app/src/context/file.tsx`
|
|
- `packages/app/src/context/local.tsx`
|
|
- `packages/app/src/context/terminal.tsx` (naming)
|
|
|
|
Utils:
|
|
- `packages/app/src/utils/prompt.ts`
|
|
- `packages/app/src/entry.tsx` (dev-only)
|