|
| 1 | +--- |
| 2 | +id: BACK-478 |
| 3 | +title: Web UI i18n support |
| 4 | +status: Done |
| 5 | +assignee: |
| 6 | + - Kimi |
| 7 | +created_date: '2026-05-16 15:20' |
| 8 | +updated_date: '2026-05-16 18:37' |
| 9 | +labels: |
| 10 | + - feature |
| 11 | + - web-ui |
| 12 | + - i18n |
| 13 | + - browser |
| 14 | +dependencies: [] |
| 15 | +priority: medium |
| 16 | +ordinal: 7600 |
| 17 | +--- |
| 18 | + |
| 19 | +## Description |
| 20 | + |
| 21 | +<!-- SECTION:DESCRIPTION:BEGIN --> |
| 22 | +Add internationalization (i18n) support to the Web UI. |
| 23 | + |
| 24 | +Currently, all user-facing text in the Web UI is hardcoded in English across ~20+ React components (Board, TaskList, Settings, Milestones, Navigation, Modal, etc.). This task extracts all hardcoded strings into a type-safe translation dictionary and allows users to switch languages via Settings. |
| 25 | + |
| 26 | +**Scope:** Web UI only. CLI and TUI are out of scope. |
| 27 | +**Languages:** English (`en`), Japanese (`ja`), Chinese Simplified (`zh-CN`), Chinese Traditional (`zh-TW`). Default to `en`. |
| 28 | +**Approach:** Zero-dependency lightweight i18n (custom React Context + hook), avoiding heavy libraries like i18next to keep the compiled binary small. |
| 29 | +<!-- SECTION:DESCRIPTION:END --> |
| 30 | + |
| 31 | +## Implementation Plan |
| 32 | + |
| 33 | +<!-- SECTION:PLAN:BEGIN --> |
| 34 | +### 1. Infrastructure |
| 35 | + |
| 36 | +Create a lightweight i18n layer under `src/web/`: |
| 37 | + |
| 38 | +``` |
| 39 | +src/web/ |
| 40 | +├── locales/ |
| 41 | +│ ├── index.ts # Locale union type, loader, and fallback logic |
| 42 | +│ ├── en.ts # English dictionary (default) |
| 43 | +│ ├── ja.ts # Japanese dictionary |
| 44 | +│ ├── zh-CN.ts # Chinese Simplified dictionary |
| 45 | +│ └── zh-TW.ts # Chinese Traditional dictionary |
| 46 | +├── contexts/ |
| 47 | +│ └── I18nContext.tsx # Provides locale state and t() function |
| 48 | +└── hooks/ |
| 49 | + └── useI18n.ts # Hook for consuming translations |
| 50 | +``` |
| 51 | + |
| 52 | +Requirements: |
| 53 | +- Full TypeScript type safety: accessing a missing key should be a compile-time error. |
| 54 | +- Support simple string interpolation (e.g., `t.tasks.assignedTo(name)`). |
| 55 | +- Compile-time embedding: import translation files as modules so they are inlined into the single-file binary by `bun build --compile`. |
| 56 | + |
| 57 | +### 2. Config Integration |
| 58 | + |
| 59 | +- Add `locale?: string` to `BacklogConfig` in `src/types/index.ts`. |
| 60 | +- Expose the field through the existing `/config` API (no backend changes needed if the field is passed through JSON). |
| 61 | +- In `Settings.tsx`, add a language selector dropdown (`English` / `日本語` / `简体中文` / `繁體中文`). |
| 62 | +- Default behavior: if `locale` is unset, fall back to `en` (or optionally detect `navigator.language`). |
| 63 | + |
| 64 | +### 3. Text Extraction & Replacement |
| 65 | + |
| 66 | +Systematically replace hardcoded English strings in all Web UI components. Key components to cover: |
| 67 | + |
| 68 | +- `Board.tsx` / `BoardPage.tsx` — "Kanban Board", "Loading tasks...", filter labels, swimlane titles |
| 69 | +- `TaskList.tsx` — column headers, empty states, search placeholder |
| 70 | +- `TaskCard.tsx` / `TaskColumn.tsx` — status labels, priority labels, button tooltips |
| 71 | +- `TaskDetailsModal.tsx` — form labels, section headers, action buttons |
| 72 | +- `Settings.tsx` — all setting labels, validation messages, success toasts |
| 73 | +- `MilestonesPage.tsx` — milestone labels, pool titles, archive section |
| 74 | +- `Navigation.tsx` / `SideNavigation.tsx` — nav item labels |
| 75 | +- `DocumentationDetail.tsx` / `DecisionDetail.tsx` — editor labels, metadata labels |
| 76 | +- `DraftsList.tsx` — page title, empty state |
| 77 | +- `Statistics.tsx` — chart labels, metric names |
| 78 | +- `CleanupModal.tsx` / `FilePreviewModal.tsx` / `InitializationScreen.tsx` — titles, descriptions, buttons |
| 79 | +- `ErrorBoundary.tsx` — error messages |
| 80 | +- `SuccessToast.tsx` — toast messages |
| 81 | + |
| 82 | +**Estimated translation keys:** ~300 (4 languages). |
| 83 | + |
| 84 | +### 4. Testing & Validation |
| 85 | + |
| 86 | +- Verify `bunx tsc --noEmit` passes (type-safe keys prevent typos). |
| 87 | +- Run `bun run check .` for formatting/linting. |
| 88 | +- Manual QA: switch language in Settings and verify all visible text updates without page reload. |
| 89 | +- Ensure fallback works when `locale` is missing or invalid. |
| 90 | + |
| 91 | +### 5. Build Verification |
| 92 | + |
| 93 | +- Confirm `bun run build` still produces a working single-file binary. |
| 94 | +- Confirm translation dictionaries are embedded (no runtime filesystem reads). |
| 95 | +<!-- SECTION:PLAN:END --> |
| 96 | + |
| 97 | +## Implementation Notes |
| 98 | + |
| 99 | +<!-- SECTION:NOTES:BEGIN --> |
| 100 | +### Terminology Decisions |
| 101 | +- **Definition of Done** → **完成检查项** (Chinese): renamed from "完成定义" to be more intuitive for non-Agile users. |
| 102 | +- **poweredBy** → kept as "Powered by" in Chinese (Traditional) to match common UI conventions. |
| 103 | + |
| 104 | +### Challenges |
| 105 | +- **C disk space (ENOSPC)**: `bun build --compile` requires large temp space. Resolved by clearing `%TEMP%` and old `dist/` builds before compiling. |
| 106 | +- **Locale persistence**: `locale` field is stored in `BacklogConfig` and serialized to `backlog.config.yml` via `parseConfig`/`serializeConfig`. |
| 107 | +- **Settings page i18n lag**: initially only the language selector was i18n'd; all remaining hardcoded labels (project name, port, editor, DoD, etc.) were converted in a follow-up pass. |
| 108 | +- **Wiki detail page parity**: `Cancel`/`Edit` buttons and placeholder text were aligned to use the same `t.common.*` keys as the document detail page. |
| 109 | + |
| 110 | +### Components Fully Internationalized |
| 111 | +Board, TaskList, TaskDetailsModal, TaskCard, TaskColumn, SideNavigation, Navigation, Settings, Statistics, CleanupModal, InitializationScreen, MilestonesPage, DraftsList, WikiDetail, DocumentationDetail, DecisionDetail, Modal, Toast, ErrorBoundary, HealthIndicator, LabelFilter, AcceptanceCriteria, DependencyInput, FilePreview, PasteAwareMDEditor, MermaidMarkdown. |
| 112 | +<!-- DOD:END --> |
| 113 | +<!-- SECTION:NOTES:END --> |
| 114 | + |
| 115 | +## Definition of Done |
| 116 | + |
| 117 | +<!-- DOD:BEGIN --> |
| 118 | +- [x] #1 Lightweight i18n infrastructure exists (`locales/`, `I18nContext`, `useI18n`) with full TS type safety |
| 119 | +- [x] #2 `BacklogConfig` includes optional `locale` field; Settings page has language selector |
| 120 | +- [x] #3 All user-facing text in `src/web/components/` is extracted into translation dictionaries |
| 121 | +- [x] #4 Default language is English; Japanese, Simplified Chinese and Traditional Chinese are selectable and fully translated |
| 122 | +- [x] #5 `bunx tsc --noEmit` passes |
| 123 | +- [x] #6 `bun run check .` passes |
| 124 | +- [x] #7 `bun run build` produces a working binary with embedded translations |
0 commit comments