diff --git a/.trellis/tasks/04-19-desktop-gui-i18n-ux-refresh/check.jsonl b/.trellis/tasks/04-19-desktop-gui-i18n-ux-refresh/check.jsonl new file mode 100644 index 0000000..310b03c --- /dev/null +++ b/.trellis/tasks/04-19-desktop-gui-i18n-ux-refresh/check.jsonl @@ -0,0 +1,2 @@ +{"file": ".opencode/commands/trellis/finish-work.md", "reason": "Finish work checklist"} +{"file": ".opencode/commands/trellis/check.md", "reason": "Code quality check spec"} diff --git a/.trellis/tasks/04-19-desktop-gui-i18n-ux-refresh/copy-inventory.md b/.trellis/tasks/04-19-desktop-gui-i18n-ux-refresh/copy-inventory.md new file mode 100644 index 0000000..e05f053 --- /dev/null +++ b/.trellis/tasks/04-19-desktop-gui-i18n-ux-refresh/copy-inventory.md @@ -0,0 +1,127 @@ +# GUI 文案收口规划 + +## 目的 + +这份文件不是最终翻译稿,而是为后续“人工精细翻译”做结构准备。 + +本轮建议先把所有可见文案按命名空间收口到 i18n 资源中,再由人工直接维护 `en.json` / `zh-CN.json`。 + +## 建议命名空间 + +### app + +- 应用标题 +- 副标题 +- 版本 / shell / 配置路径说明 + +### nav + +- 左侧 tab 名称 +- tab 简短描述 + +### overview + +- 概览标题 +- 代理状态 +- 统计卡标题 +- 主操作按钮 +- 调试详情标题 + +### providers + +- provider 列表空态 +- 创建 / 编辑表单标签 +- 导入区文案 +- 列表项操作按钮 +- 保存 / 删除 / 启停状态消息 + +### aliases + +- alias 列表空态 +- alias 表单标签 +- target 绑定表单标签 +- target 行操作按钮 +- 绑定 / 解绑 / 启停状态消息 + +### sync + +- sync 标题 +- target path / model / small_model 标签 +- preview / apply 按钮 +- preview 结果摘要 +- apply 结果摘要 + +### doctor + +- doctor 标题 +- 检查中 / 成功 / 失败状态 +- 问题列表 +- 空态与说明文案 + +### settings + +- 主题设置 +- 语言设置 +- 桌面行为设置 +- 关于信息 + +### actions + +- refresh +- save +- reset +- edit +- delete +- enable +- disable +- preview +- apply +- runDoctor + +### messages + +- refreshing +- saving +- saved +- applying +- previewing +- importing +- loading +- noData + +### errors + +- requestFailed +- bridgeUnavailable +- invalidHeader + +## 需要纳入翻译的文案类型 + +1. 页面标题与模块标题 +2. 按钮文本 +3. 表单标签 +4. placeholder +5. 空态提示 +6. 成功 / 失败 / 进行中状态文案 +7. 折叠区标题与说明性文字 + +## 不建议翻译的内容 + +1. provider id +2. alias 原始值 +3. model id +4. 文件路径 +5. URL +6. 原始技术错误详情 + +## 初始覆盖源文件 + +- `frontend/src/App.tsx` +- `frontend/src/api.ts` + +## 实施建议 + +1. 先把现有硬编码文案替换为 key +2. `en.json` 先完整收口 +3. `zh-CN.json` 先给出可用翻译 +4. 人工精修阶段只改 locale 文件,不再回头搜 JSX diff --git a/.trellis/tasks/04-19-desktop-gui-i18n-ux-refresh/debug.jsonl b/.trellis/tasks/04-19-desktop-gui-i18n-ux-refresh/debug.jsonl new file mode 100644 index 0000000..5b204df --- /dev/null +++ b/.trellis/tasks/04-19-desktop-gui-i18n-ux-refresh/debug.jsonl @@ -0,0 +1 @@ +{"file": ".opencode/commands/trellis/check.md", "reason": "Code quality check spec"} diff --git a/.trellis/tasks/04-19-desktop-gui-i18n-ux-refresh/implement.jsonl b/.trellis/tasks/04-19-desktop-gui-i18n-ux-refresh/implement.jsonl new file mode 100644 index 0000000..4752e3d --- /dev/null +++ b/.trellis/tasks/04-19-desktop-gui-i18n-ux-refresh/implement.jsonl @@ -0,0 +1 @@ +{"file": ".trellis/workflow.md", "reason": "Project workflow and conventions"} diff --git a/.trellis/tasks/04-19-desktop-gui-i18n-ux-refresh/prd.md b/.trellis/tasks/04-19-desktop-gui-i18n-ux-refresh/prd.md new file mode 100644 index 0000000..2f984da --- /dev/null +++ b/.trellis/tasks/04-19-desktop-gui-i18n-ux-refresh/prd.md @@ -0,0 +1,563 @@ +# Desktop GUI i18n / UI-UX / Theme Refresh + +## 概要 + +当前桌面 GUI 已具备可用的基础功能,但前端还停留在“单文件控制台”形态: + +- `frontend/src/App.tsx` 单文件承载全部模块和交互,页面信息密度高但层次弱 +- 当前所有主内容都堆在一个长页面里,模块边界不清晰 +- 文案基本为英文硬编码,尚未建立 i18n 机制 +- `frontend/src/styles.css` 仅支持一套暗色视觉,缺少主题切换能力 +- 桌面偏好当前只包含 `launchAtLogin` / `minimizeToTray` / `notifications` + +本任务的目标不是直接做完全部 GUI 重构,而是输出一版可以直接进入实现阶段的方案设计,并把范围、分层、数据契约、实施顺序和验收标准先固定下来。 + +## 产品目标 + +这轮 GUI 优化聚焦三个结果: + +1. 建立正式的 i18n 基础设施,至少支持 `zh-CN` 与 `en-US` +2. 将当前单页大杂烩改为左侧纵向 tab 的模块化信息架构 +3. 支持 `system / light / dark` 三档主题切换 + +同时满足以下使用体验要求: + +- 桌面主窗口默认信息组织清晰,不需要依赖通篇向下滚动来完成主要操作 +- 尽量实现“页面不滚动、局部区域滚动” +- 保持 Wails 桌面壳与浏览器 fallback 共用同一套前端 +- 不重写现有 Go 侧业务逻辑,只补齐桌面偏好与前端展示能力 + +## 当前事实与约束 + +### 现有前端事实 + +- 前端入口很轻:`frontend/src/main.tsx` 仅挂载 `App` +- 当前无路由库、无全局状态库、无 i18n 依赖 +- 当前 API 通过 `frontend/src/api.ts` 在 Wails bridge 与 HTTP fallback 间切换 +- 当前页面结构全部写在 `frontend/src/App.tsx`,内容包含:概览、桌面偏好、OpenCode 同步、Doctor、Providers、Aliases +- 当前视觉完全由 `frontend/src/styles.css` 管理,且根节点声明为暗色 `color-scheme: dark` + +### 现有跨层契约事实 + +- `internal/config/config.go` 中 `config.Desktop` 只有三个布尔字段 +- `internal/app/types.go` 中 `DesktopPrefsView` / `DesktopPrefsInput` 同样只有三个布尔字段 +- `internal/app/service.go` 的 `SaveDesktopPrefs()` 目前直接把这三个字段写回配置文件 +- `internal/app/service_test.go` 与 `internal/desktop/http_test.go` 已覆盖桌面偏好保存路径,适合作为后续扩展 `theme` / `language` 的回归测试入口 + +### 现有窗口约束 + +- `internal/desktop/wails.go` 当前窗口尺寸为 `1280 x 880` +- 最小尺寸为 `980 x 720` + +这个尺寸对“左侧纵向 tab + 主内容双栏”是偏紧的,尤其是 Providers / Aliases 两个高密度模块,因此布局方案需要同时考虑: + +- 默认窗口尺寸下尽量不出现整页纵向滚动 +- 窄窗口时允许局部折叠或内部滚动,但仍保持结构稳定 + +## 非目标 + +1. 不引入新的后端业务层或重写 `internal/app`、`internal/config`、`internal/opencode`、`internal/proxy` 的业务归属 +2. 不为了 tab 导航引入完整路由系统,除非 hash 方案无法满足需要 +3. 不在这一轮引入大型 UI 框架或设计系统迁移 +4. 不在这一轮扩展日志分析、历史记录、远程控制等新产品面 +5. 不在这一轮做复杂动画、图标系统或品牌视觉重塑 + +## 核心设计决策 + +### 1. i18n 方案 + +推荐使用:`i18next + react-i18next` + +选择原因: + +- 对 React 生态成熟,后续扩展语言成本低 +- 支持命名空间、fallback、插值、运行时切换 +- 比手写 context 字典更适合后续“人工精细翻译”与增量维护 +- 与当前前端体量相匹配,不需要引入更重的国际化平台 + +推荐落地结构: + +```text +frontend/src/i18n/ + index.ts + locales/ + en.json + zh-CN.json +``` + +推荐规则: + +- `en.json` 作为 source of truth +- `zh-CN.json` 先提供可用翻译,后续再人工精修 +- 所有可见文案统一改为 key,不再直接在 JSX 中写死英文 +- 所有状态文案、按钮文案、空态文案、表单标签、placeholder、错误提示都纳入翻译 +- 不翻译配置路径、provider id、model id、URL、技术错误原文等数据性内容 + +推荐 key 命名方式: + +```text +app.title +nav.overview +overview.proxyRunning +providers.form.baseUrl +aliases.empty +sync.previewChanges +settings.theme.system +messages.refreshing +errors.bridgeUnavailable +``` + +### 2. 语言偏好持久化 + +推荐把语言偏好纳入桌面偏好,而不是只放前端本地状态。 + +建议新增字段: + +- `language`: `system | en-US | zh-CN` + +对应变更位置: + +- `internal/config/config.go` 的 `config.Desktop` +- `internal/app/types.go` 的 `DesktopPrefsView` / `DesktopPrefsInput` +- `internal/app/service.go` 的读写映射 +- `frontend/src/types.ts` + +语言决议顺序: + +1. 用户显式选择的 `language` +2. 若为 `system`,使用 `navigator.language` +3. 若系统语言不在支持列表,则回退到 `en-US` + +这样做的原因: + +- 桌面应用重启后保留用户偏好 +- 浏览器 fallback 与 Wails 行为一致 +- 后续新增日语等语言时不需要重构偏好模型 + +### 3. 主题方案 + +推荐继续使用原生 CSS,不引入 Tailwind 或 CSS-in-JS 重构。 + +建议新增字段: + +- `theme`: `system | light | dark` + +实现原则: + +- 前端只维护一个“用户选择主题”字段 +- 运行时计算一个 `resolvedTheme`,结果为 `light` 或 `dark` +- 把结果写到 `document.documentElement.dataset.theme` +- 用 CSS 变量承载所有颜色 token + +推荐样式组织: + +```css +:root { + --bg: ...; + --panel: ...; + --text: ...; + --muted: ...; + --border: ...; + --accent: ...; +} + +html[data-theme='dark'] { ... } +html[data-theme='light'] { ... } +``` + +注意事项: + +- 现在的 `:root { color-scheme: dark; }` 需要改为按主题动态切换 +- 表单控件、滚动条、badge、panel、背景渐变都需要转为 token 化 +- 不要在各组件里散落 `if (theme === 'dark')` 之类分支,主题只通过 CSS token 生效 + +### 4. 导航与信息架构 + +推荐使用左侧纵向 tab,且 tab 状态优先使用 hash 管理,而不是新增路由依赖。 + +推荐 tab: + +1. `overview` 概览 +2. `providers` 提供商 +3. `aliases` 别名路由 +4. `sync` 同步与体检 +5. `settings` 设置 + +推荐原因: + +- 这 5 个模块正好对应当前功能边界 +- hash 方案足够轻量,Wails 与 HTTP fallback 都可直接工作 +- 可支持 `#providers` 这类深链接,便于问题定位与后续文档引用 + +不建议保留当前结构: + +- 概览、设置、同步、Doctor、Providers、Aliases 在单页堆叠 +- 大量 `pre` 原始 JSON 长块直接暴露在主流程中 + +### 5. 页面滚动策略 + +目标不是“任何情况下零滚动”,而是: + +- 主页面整体尽量不产生纵向长滚动 +- 长列表和明细列表在局部 pane 内滚动 +- 表单和操作区域尽量固定在视口中 + +推荐布局原则: + +- 应用根容器使用接近全高布局 +- 左侧 sidebar 固定宽度 +- 右侧内容区使用 tab 面板切换 +- Providers / Aliases 使用左右 split-pane +- 列表区独立 `overflow: auto` +- 原始 JSON / 诊断详情放入折叠区或次级详情区,不占主操作流 + +## 推荐信息架构 + +### Overview Tab + +目标:进入应用后 5 秒内看懂当前状态,并完成最常见的启停操作。 + +推荐内容: + +- 顶部状态卡:代理状态、provider 数、alias 数、可路由 alias 数 +- 主操作区:`Refresh`、`Start proxy`、`Stop proxy`、`Run doctor` +- 环境信息:版本、shell、配置路径 +- 简版健康摘要:最近一次 doctor 状态或提示入口 + +不推荐继续保留: + +- 默认展示完整 `overview` JSON 大块文本 + +建议: + +- 原始 JSON 仅在“调试详情”折叠区显示 + +### Providers Tab + +目标:高频管理 provider,避免当前“左边长表单 + 右边长列表 + 整页继续往下”的阅读负担。 + +推荐结构: + +- 左侧:provider 列表、搜索、状态筛选、`新建 provider` +- 右侧:当前选中 provider 的编辑表单 +- 右上或右下:导入 OpenCode provider 的辅助卡片 + +交互原则: + +- “创建”与“编辑”共用同一表单 +- 点击列表项进入编辑态 +- 删除、启用、禁用作为列表项级操作 +- `Headers` 与 `Models` 属于细节信息,不要默认铺得过长 + +列表过长时: + +- 仅让左侧列表内部滚动 +- 右侧表单固定显示 + +### Aliases Tab + +目标:把“别名编辑”和“target 绑定管理”从当前混排状态拆开。 + +推荐结构: + +- 左侧:alias 列表、状态摘要、`新建 alias` +- 右侧上半区:alias 基本信息编辑 +- 右侧下半区:targets 表格或卡片列表 + +交互原则: + +- `Bind target` 不再作为全局独立表单漂浮存在,而是明确附着到当前 alias +- 当未选中 alias 时,右侧给出“请选择或新建 alias”空态 +- target 的启用/停用/解绑应靠近 target 行,不要再依赖跨区域操作 + +### Sync Tab + +目标:把 OpenCode 同步与 Doctor 合并成“维护与诊断”模块,但在视觉上清楚分区。 + +推荐结构: + +- 左列:OpenCode sync 表单与 preview / apply 结果 +- 右列:Doctor 摘要、问题列表、重新检查按钮 + +展示方式: + +- preview / apply 结果先展示结构化摘要 +- 原始结果放在折叠详情中 +- doctor 结果优先展示 `OK / 有问题`、问题数量和核心问题列表 + +### Settings Tab + +目标:把“桌面偏好”和“外观语言偏好”统一收口。 + +推荐内容: + +- Appearance +- Language +- Desktop behavior +- About / debug info + +建议顺序: + +1. 主题选择:`跟随系统 / 浅色 / 深色` +2. 语言选择:`跟随系统 / 中文 / English` +3. 桌面行为:开机启动、最小化到托盘、通知 +4. 应用信息:版本、shell、配置路径 + +这会把原本散落在首页的桌面偏好移到更符合用户心智的位置。 + +## 推荐前端结构调整 + +当前 `App.tsx` 已达到必须拆分的规模。推荐最小可控拆分如下: + +```text +frontend/src/ + App.tsx + api.ts + main.tsx + types.ts + styles.css + i18n/ + index.ts + locales/ + en.json + zh-CN.json + app/ + tabs.ts + useDesktopPreferences.ts + useResolvedTheme.ts + features/ + overview/OverviewTab.tsx + providers/ProvidersTab.tsx + aliases/AliasesTab.tsx + sync/SyncTab.tsx + settings/SettingsTab.tsx + shared/ + AppSidebar.tsx + AppHeader.tsx + Panel.tsx +``` + +拆分原则: + +- API 访问仍保留在 `api.ts` +- 跨模块共享状态仍由 `App.tsx` 统一拥有 +- tab 组件只接收明确 props,不私自重复请求数据 +- theme / language 的解析逻辑抽到 hook 或 util,避免每个 tab 重复判断 + +## 跨层数据契约变更 + +### 配置层 + +`internal/config/config.go` + +建议将: + +```go +type Desktop struct { + LaunchAtLogin bool + MinimizeToTray bool + Notifications bool +} +``` + +扩展为: + +```go +type Desktop struct { + LaunchAtLogin bool `json:"launch_at_login,omitempty"` + MinimizeToTray bool `json:"minimize_to_tray,omitempty"` + Notifications bool `json:"notifications,omitempty"` + Theme string `json:"theme,omitempty"` + Language string `json:"language,omitempty"` +} +``` + +允许值建议: + +- `Theme`: `system | light | dark` +- `Language`: `system | en-US | zh-CN` + +### 应用层 DTO + +`internal/app/types.go` + +- `DesktopPrefsView` +- `DesktopPrefsInput` +- 如需保证兼容性,可继续让 `DesktopPrefsSaveResult` 结构不变,只扩展 `prefs` 内容 + +### 应用层服务 + +`internal/app/service.go` + +需要新增: + +- 对 `theme` / `language` 的合法值归一化 +- 对未知值回退到 `system` +- `desktopPrefsView()` 的新字段映射 + +建议不要把合法性校验放到前端单独维护,前后端都应该认同同一套枚举语义。 + +### 前端类型 + +`frontend/src/types.ts` + +需要扩展: + +- `DesktopPrefsView` +- `DesktopPrefsSaveResult` + +建议新增: + +- `type ThemePreference = 'system' | 'light' | 'dark'` +- `type LanguagePreference = 'system' | 'en-US' | 'zh-CN'` + +## 实施顺序 + +推荐拆成 4 个小阶段,按风险从低到高推进。 + +### Phase 1: 补齐桌面偏好契约 + +目标:先把 `theme` / `language` 变成可保存、可读取、可测试的数据。 + +涉及: + +- `internal/config/config.go` +- `internal/app/types.go` +- `internal/app/service.go` +- `internal/app/service_test.go` +- `internal/desktop/http_test.go` +- `frontend/src/types.ts` + +验收: + +- 保存桌面偏好时可写入 `theme` / `language` +- 旧配置不报错,缺省值按 `system` 处理 +- 现有桌面偏好测试继续通过,并增加新字段断言 + +### Phase 2: 搭 i18n 与主题基础设施 + +目标:先把底座搭起来,再替换可见文案。 + +涉及: + +- 新增 i18n 初始化 +- 新增中英文资源文件 +- 把现有根样式改为 token 化 +- 新增主题解析与 DOM 同步逻辑 +- Settings 中先提供主题 / 语言切换控件 + +验收: + +- 应用启动后可按配置或系统语言切换文案 +- 应用启动后可按配置或系统主题切换样式 +- Wails 与 HTTP fallback 行为一致 + +### Phase 3: 重构为左侧纵向 tab 布局 + +目标:把当前单页拆成清晰模块,不改变业务能力。 + +涉及: + +- 提炼 `Sidebar` 与 tab metadata +- 将当前大页面拆为 5 个 tab 内容区 +- 将 Provider / Alias 改为 split-pane 布局 +- 将 JSON 大块输出收进折叠区或调试区 + +验收: + +- 默认视图下无需整页向下滚动才能完成主要操作 +- 大部分高频操作都能在当前 tab 内完成 +- hash 切换 tab 正常,可直接进入某个模块 + +### Phase 4: 文案收口与中文首轮翻译 + +目标:把所有硬编码文案收口到资源文件,并提供首轮中文。 + +涉及: + +- 清理残余硬编码字符串 +- 生成文案清单供人工精修 +- 完成 `zh-CN` 首轮翻译 + +验收: + +- 主界面无裸露英文硬编码 +- 翻译 key 命名稳定、按模块组织 +- 人工精修时只需要维护 locale 文件,不需要再搜 JSX + +## 测试与验证建议 + +### Go 侧 + +- `go test ./internal/app` +- `go test ./internal/desktop` + +重点校验: + +- 旧配置读取兼容 +- 新偏好字段保存正确 +- HTTP 接口序列化包含新字段 + +### 前端侧 + +当前仓库未引入测试框架,本轮至少应保留: + +- `npm run build` + +手动验证清单: + +- 语言切换后 tab、表单、状态文案、空态是否同步变化 +- 主题切换后按钮、输入框、badge、panel、背景是否都正确 +- 窗口宽度在默认值与最小值附近时,布局是否稳定 +- hash 切换 tab 与刷新后定位是否符合预期 +- Wails / 浏览器 fallback 两种壳下切换行为是否一致 + +## 风险与缓解 + +### 风险 1: `App.tsx` 一次性重构过大 + +缓解: + +- 先抽 tab 壳与 shared 组件 +- 每拆一个 tab 就保留原有业务处理函数,不同时改业务与 UI + +### 风险 2: i18n key 粒度不稳定,后续翻译返工 + +缓解: + +- 先按模块命名空间统一 key +- 避免把整句状态文案拼接在多个地方 +- 动态文案尽量通过插值模板统一 + +### 风险 3: 主题切换改动大,容易出现漏色 + +缓解: + +- 先把当前样式中的颜色集中成 token +- 搜索所有十六进制颜色和 `rgba()`,逐步收口 + +### 风险 4: 窄窗口下 tab 布局拥挤 + +缓解: + +- 默认保持左侧 tab +- 在低于阈值时允许 sidebar 收缩 +- 若验证后仍过于拥挤,再上调 `MinWidth`,建议目标区间为 `1100-1120` + +## 验收标准 + +1. `DesktopPrefs` 契约中包含 `theme` 与 `language`,并可在配置中持久化 +2. 前端引入正式 i18n 机制,至少可在 `en-US` 与 `zh-CN` 间切换 +3. 主界面切换为左侧纵向 tab,至少包含概览、提供商、别名路由、同步与体检、设置五个模块 +4. 主题支持 `system / light / dark` +5. 主流程页面不再依赖整页长滚动;长列表改为局部 pane 内滚动 +6. 主要可见文案已从 JSX 抽离到翻译资源文件 +7. 构建与现有相关测试路径不回归 + +## 建议的下一步 + +1. 先实现 Phase 1,补齐 `theme` / `language` 跨层契约 +2. 再实现 Phase 2,搭建 i18n 与 CSS token 底座 +3. 最后进入 tab 布局重构,避免同时改数据层与视觉层 + +这是当前仓库里风险最低、可持续迭代的推进顺序。 diff --git a/.trellis/tasks/04-19-desktop-gui-i18n-ux-refresh/task.json b/.trellis/tasks/04-19-desktop-gui-i18n-ux-refresh/task.json new file mode 100644 index 0000000..52b5e5d --- /dev/null +++ b/.trellis/tasks/04-19-desktop-gui-i18n-ux-refresh/task.json @@ -0,0 +1,87 @@ +{ + "id": "desktop-gui-i18n-ux-refresh", + "name": "desktop-gui-i18n-ux-refresh", + "title": "Plan desktop GUI i18n and UX refresh", + "description": "Produce an execution-ready design for desktop GUI i18n, left-side tab information architecture, and light/dark theme support based on the current Wails + React implementation.", + "status": "completed", + "dev_type": "docs", + "scope": "desktop", + "package": null, + "priority": "P1", + "creator": "OpenCode", + "assignee": "OpenCode", + "createdAt": "2026-04-19", + "completedAt": "2026-04-19", + "branch": "master", + "base_branch": "master", + "worktree_path": null, + "current_phase": 6, + "next_action": [ + { + "phase": 1, + "action": "brainstorm" + }, + { + "phase": 2, + "action": "research" + }, + { + "phase": 3, + "action": "implement" + }, + { + "phase": 4, + "action": "check" + }, + { + "phase": 5, + "action": "update-spec" + }, + { + "phase": 6, + "action": "record-session" + } + ], + "commit": null, + "pr_url": null, + "subtasks": [], + "children": [], + "parent": null, + "relatedFiles": [ + ".trellis/tasks/04-19-desktop-gui-i18n-ux-refresh/prd.md", + ".trellis/tasks/04-19-desktop-gui-i18n-ux-refresh/copy-inventory.md", + "frontend/src/App.tsx", + "frontend/src/main.tsx", + "frontend/src/api.ts", + "frontend/src/types.ts", + "frontend/src/styles.css", + "internal/app/types.go", + "internal/app/service.go", + "internal/app/service_test.go", + "internal/config/config.go", + "internal/desktop/http_test.go", + "internal/desktop/wails.go" + ], + "notes": "完成桌面 GUI 后续改造方案设计,明确了 i18n、左侧纵向 tab 信息架构、system/light/dark 主题切换、DesktopPrefs 新增 theme/language 契约、阶段化实施顺序与测试策略。当前建议先实现偏好契约与 i18n/theme 底座,再进入页面拆 tab。", + "meta": { + "i18nFramework": "i18next + react-i18next", + "navigationModel": "left-side vertical tabs with hash state", + "themeModes": [ + "system", + "light", + "dark" + ], + "languageModes": [ + "system", + "en-US", + "zh-CN" + ], + "primaryTabs": [ + "overview", + "providers", + "aliases", + "sync", + "settings" + ] + } +}