432 lines
19 KiB
Markdown
432 lines
19 KiB
Markdown
# UniApp 主应用国际化(i18n)实现计划
|
||
|
||
> **面向 AI 代理的工作者:** 必需子技能:使用 superpowers:subagent-driven-development(推荐)或 superpowers:executing-plans 逐任务实现此计划。步骤使用复选框(`- [ ]`)语法来跟踪进度。
|
||
|
||
**目标:** 为 UniApp 主应用引入 vue-i18n 国际化体系,支持 9 种语言,将所有硬编码中文 UI 文本替换为 `$t()` / `t()` 调用。
|
||
|
||
**架构:** 集中式翻译文件方案,所有翻译键值对按语言分文件存放于 `src/locales/`,通过 vue-i18n 实例注入 Vue 应用。领域术语保留中文原词不纳入翻译体系。
|
||
|
||
**技术栈:** vue-i18n@9, Vue 3 Composition API, UniApp, Vitest
|
||
|
||
**设计规格:** `docs/superpowers/specs/2026-04-28-uniapp-i18n-design.md`
|
||
|
||
---
|
||
|
||
## 整体架构流程
|
||
|
||
```mermaid
|
||
graph TD
|
||
A[用户启动 App] --> B{localStorage 有 preferred-locale?}
|
||
B -->|是| C[读取存储的 locale]
|
||
B -->|否| D{读取系统语言}
|
||
D -->|匹配支持语言| E[使用系统语言]
|
||
D -->|不匹配| F[回退 zh-CN]
|
||
C --> G[应用 vue-i18n locale]
|
||
E --> G
|
||
F --> G
|
||
G --> H[渲染页面 - $t 替换硬编码文本]
|
||
H --> I{用户切换系统语言?}
|
||
I -->|是| J[重启 App 重新检测]
|
||
I -->|否| H
|
||
```
|
||
|
||
## 组件改造流程
|
||
|
||
```mermaid
|
||
graph LR
|
||
subgraph 改造前
|
||
A1[模板硬编码中文] --> B1[Script 硬编码中文]
|
||
B1 --> C1[pages.json 硬编码中文]
|
||
end
|
||
subgraph 改造后
|
||
A2["模板: {{ $t('key') }}"] --> B2["Script: const { t } = useI18n(); t('key')"]
|
||
B2 --> C2["onShow: uni.setNavigationBarTitle"]
|
||
end
|
||
A1 -.->|替换| A2
|
||
B1 -.->|替换| B2
|
||
C1 -.->|运行时覆盖| C2
|
||
```
|
||
|
||
## Phase 依赖关系
|
||
|
||
```mermaid
|
||
graph TD
|
||
P1["Phase 1: 基础设施<br/>安装 vue-i18n + 创建核心模块"] --> P2["Phase 2: 翻译文件<br/>创建 9 种语言翻译"]
|
||
P2 --> P3["Phase 3: 页面改造<br/>3 个页面 + pages.json"]
|
||
P2 --> P4["Phase 4: 组件改造<br/>10 个组件"]
|
||
P3 --> P5["Phase 5: 测试与验证<br/>完整性 + 组件 + E2E"]
|
||
P4 --> P5
|
||
```
|
||
|
||
---
|
||
|
||
## 文件结构
|
||
|
||
### 新建文件
|
||
|
||
| 文件路径 | 职责 |
|
||
|---------|------|
|
||
| `src/locales/index.ts` | vue-i18n 实例创建、语言检测/切换/持久化 |
|
||
| `src/locales/zh-CN.ts` | 简体中文翻译(主翻译源) |
|
||
| `src/locales/zh-TW.ts` | 繁體中文翻译 |
|
||
| `src/locales/en.ts` | English 翻译 |
|
||
| `src/locales/ja.ts` | 日本語翻译 |
|
||
| `src/locales/ko.ts` | 한국어 翻译 |
|
||
| `src/locales/de.ts` | Deutsch 翻译 |
|
||
| `src/locales/fr.ts` | Français 翻译 |
|
||
| `src/locales/es.ts` | Español 翻译 |
|
||
| `src/locales/pt.ts` | Português 翻译 |
|
||
| `src/locales/__tests__/completeness.test.ts` | 翻译完整性校验测试 |
|
||
| `src/locales/__tests__/interpolation.test.ts` | 插值格式校验测试 |
|
||
|
||
### 修改文件
|
||
|
||
| 文件路径 | 改动说明 |
|
||
|---------|---------|
|
||
| `package.json` | 添加 vue-i18n 依赖 |
|
||
| `src/main.ts` | 挂载 i18n 实例 |
|
||
| `src/pages/almanac-search/index.vue` | 替换硬编码中文为 `$t()` / `t()` |
|
||
| `src/pages/ziwei/index.vue` | 替换硬编码中文为 `$t()` / `t()` |
|
||
| `src/pages/fortune/index.vue` | 替换硬编码中文为 `$t()` / `t()` |
|
||
| `src/components/BottomNavigation/BottomNavigation.vue` | 替换硬编码中文 |
|
||
| `src/components/EmptyState/index.vue` | 移除中文默认值 |
|
||
| `src/components/SearchConditionPanel/index.vue` | 替换硬编码中文 |
|
||
| `src/components/SearchConditionItem/index.vue` | 替换硬编码中文(领域术语保留) |
|
||
| `src/components/SearchResultList/index.vue` | 替换硬编码中文 |
|
||
| `src/components/SearchResultCard/index.vue` | 替换硬编码中文 |
|
||
| `src/components/SortSwitcher/index.vue` | 替换硬编码中文 |
|
||
| `src/components/ExportPanel/index.vue` | 替换硬编码中文 |
|
||
| `src/components/SearchHistoryPanel/index.vue` | 替换硬编码中文 |
|
||
| `src/components/TemplatePanel/index.vue` | 替换硬编码中文 |
|
||
|
||
---
|
||
|
||
## Phase 1:基础设施 — 安装 vue-i18n + 创建核心模块
|
||
|
||
**文件:**
|
||
- 修改:`package.json`
|
||
- 创建:`src/locales/index.ts`
|
||
- 创建:`src/locales/zh-CN.ts`
|
||
- 修改:`src/main.ts`
|
||
|
||
### 任务 1.1:安装 vue-i18n 依赖
|
||
|
||
- [ ] **步骤 1:安装 vue-i18n**
|
||
|
||
运行:`cd everything-is-suitable-uniapp && npm install vue-i18n@9`
|
||
|
||
预期:`package.json` 中出现 `"vue-i18n": "^9.x.x"` 依赖
|
||
|
||
- [ ] **步骤 2:验证安装**
|
||
|
||
运行:`cd everything-is-suitable-uniapp && node -e "const v = require('vue-i18n/package.json'); console.log(v.version)"`
|
||
|
||
预期:输出 `9.x.x` 版本号
|
||
|
||
- [ ] **步骤 3:Commit**
|
||
|
||
`cd everything-is-suitable-uniapp && git add package.json package-lock.json && git commit -m "chore: 安装 vue-i18n@9 依赖"`
|
||
|
||
### 任务 1.2:创建 zh-CN 主翻译源文件
|
||
|
||
- [ ] **步骤 1:创建 `src/locales/zh-CN.ts`** — 包含 common/nav/almanac/ziwei/fortune/search/template/export/history 共 9 个命名空间,约 80 个翻译键
|
||
|
||
- [ ] **步骤 2:Commit**
|
||
|
||
`cd everything-is-suitable-uniapp && git add src/locales/zh-CN.ts && git commit -m "feat(i18n): 创建简体中文主翻译源 zh-CN.ts"`
|
||
|
||
### 任务 1.3:创建 locales/index.ts 核心模块
|
||
|
||
- [ ] **步骤 1:创建 `src/locales/index.ts`** — 包含 createI18n 实例、detectLocale 语言检测、setLocale 切换持久化、getLocale 获取当前语言、SUPPORTED_LOCALES 常量、localeNames 映射
|
||
|
||
- [ ] **步骤 2:Commit**
|
||
|
||
`cd everything-is-suitable-uniapp && git add src/locales/index.ts && git commit -m "feat(i18n): 创建 vue-i18n 实例与语言检测/切换核心模块"`
|
||
|
||
### 任务 1.4:改造 main.ts 挂载 i18n
|
||
|
||
- [ ] **步骤 1:修改 `src/main.ts`** — 添加 `import { i18n } from './locales'` 和 `app.use(i18n)`
|
||
|
||
- [ ] **步骤 2:验证构建无报错**
|
||
|
||
运行:`cd everything-is-suitable-uniapp && npx vite build --mode development 2>&1 | head -20`
|
||
|
||
预期:构建成功,无模块解析错误
|
||
|
||
- [ ] **步骤 3:Commit**
|
||
|
||
`cd everything-is-suitable-uniapp && git add src/main.ts && git commit -m "feat(i18n): 在 main.ts 中挂载 vue-i18n 实例"`
|
||
|
||
---
|
||
|
||
## Phase 2:翻译文件 — 创建 8 种非中文翻译
|
||
|
||
**依赖:** Phase 1
|
||
|
||
每个任务结构相同:创建翻译文件 → Commit。翻译键结构必须与 zh-CN.ts 完全一致。
|
||
|
||
### 任务 2.1:创建繁體中文翻译 zh-TW.ts
|
||
|
||
- [ ] **步骤 1:创建 `src/locales/zh-TW.ts`** — 简转繁,保持相同键结构
|
||
- [ ] **步骤 2:Commit**
|
||
|
||
### 任务 2.2:创建英文翻译 en.ts
|
||
|
||
- [ ] **步骤 1:创建 `src/locales/en.ts`** — 领域术语保留拼音(如 Zi Wei Dou Shu)
|
||
- [ ] **步骤 2:Commit**
|
||
|
||
### 任务 2.3:创建日文翻译 ja.ts
|
||
|
||
- [ ] **步骤 1:创建 `src/locales/ja.ts`** — 命理术语保留汉字(如 紫微斗数、三方四正)
|
||
- [ ] **步骤 2:Commit**
|
||
|
||
### 任务 2.4:创建韩文翻译 ko.ts
|
||
|
||
- [ ] **步骤 1:创建 `src/locales/ko.ts`** — 命理术语保留汉字(如 자미두수)
|
||
- [ ] **步骤 2:Commit**
|
||
|
||
### 任务 2.5:创建德文翻译 de.ts
|
||
|
||
- [ ] **步骤 1:创建 `src/locales/de.ts`** — 领域术语保留拼音
|
||
- [ ] **步骤 2:Commit**
|
||
|
||
### 任务 2.6:创建法文翻译 fr.ts
|
||
|
||
- [ ] **步骤 1:创建 `src/locales/fr.ts`** — 领域术语保留拼音
|
||
- [ ] **步骤 2:Commit**
|
||
|
||
### 任务 2.7:创建西班牙文翻译 es.ts
|
||
|
||
- [ ] **步骤 1:创建 `src/locales/es.ts`** — 领域术语保留拼音
|
||
- [ ] **步骤 2:Commit**
|
||
|
||
### 任务 2.8:创建葡萄牙文翻译 pt.ts
|
||
|
||
- [ ] **步骤 1:创建 `src/locales/pt.ts`** — 领域术语保留拼音
|
||
- [ ] **步骤 2:Commit**
|
||
|
||
---
|
||
|
||
## Phase 3:页面改造 — 3 个页面 + pages.json
|
||
|
||
**依赖:** Phase 1, Phase 2
|
||
|
||
```mermaid
|
||
graph TD
|
||
P3A["任务 3.1: almanac-search"] --> P3D["任务 3.4: pages.json 确认"]
|
||
P3B["任务 3.2: ziwei"] --> P3D
|
||
P3C["任务 3.3: fortune"] --> P3D
|
||
```
|
||
|
||
### 任务 3.1:改造黄历搜索页 almanac-search/index.vue
|
||
|
||
**文件:** 修改 `src/pages/almanac-search/index.vue`
|
||
|
||
- [ ] **步骤 1:在 `<script setup>` 中添加 i18n 导入** — `import { useI18n } from 'vue-i18n'` + `const { t } = useI18n()`
|
||
- [ ] **步骤 2:替换模板硬编码中文** — `黄历搜索` → `{{ $t('almanac.pageTitle') }}`、`搜索中...` → `{{ $t('almanac.searching') }}`、`重试` → `{{ $t('common.retry') }}`
|
||
- [ ] **步骤 3:替换 script 硬编码中文** — `error.value = t('almanac.keywordHint')`、`error.value = t('almanac.noResult')`、`error.value = t('search.addConditionHint')`、`error.value = t('almanac.searchFailed')`
|
||
- [ ] **步骤 4:添加 onShow 动态设置导航栏标题** — `import { onShow } from '@dcloudio/uni-app'` + `onShow(() => { uni.setNavigationBarTitle({ title: t('almanac.pageTitle') }) })`
|
||
- [ ] **步骤 5:验证构建**
|
||
- [ ] **步骤 6:Commit**
|
||
|
||
### 任务 3.2:改造紫微斗数页 ziwei/index.vue
|
||
|
||
**文件:** 修改 `src/pages/ziwei/index.vue`
|
||
|
||
- [ ] **步骤 1:添加 i18n 导入**
|
||
- [ ] **步骤 2:替换模板硬编码中文** — `出生信息` → `{{ $t('ziwei.birthInfo') }}`、`出生日期` → `{{ $t('ziwei.birthDate') }}`、`请选择` → `{{ $t('ziwei.pleaseSelect') }}`、`出生时辰` → `{{ $t('ziwei.birthHour') }}`、`性别` → `{{ $t('ziwei.gender') }}`、`男` → `{{ $t('common.male') }}`、`女` → `{{ $t('common.female') }}`、`排盘中...` → `{{ $t('ziwei.generating') }}`、`排盘` → `{{ $t('ziwei.generate') }}`、`紫微斗数盘` → `{{ $t('ziwei.chartTitle') }}`、`三方四正分析` → `{{ $t('ziwei.sanFangAnalysis') }}`、`三方得分` → `{{ $t('ziwei.sanFangScore') }}`、`四正得分` → `{{ $t('ziwei.siZhengScore') }}`、`综合评价` → `{{ $t('ziwei.overallEval') }}`、`盘面概述` → `{{ $t('ziwei.summary') }}`、`分` → `{{ $t('ziwei.scoreUnit') }}`
|
||
- [ ] **步骤 3:添加 onShow 动态设置导航栏标题**
|
||
- [ ] **步骤 4:验证构建**
|
||
- [ ] **步骤 5:Commit**
|
||
|
||
### 任务 3.3:改造运势分析页 fortune/index.vue
|
||
|
||
**文件:** 修改 `src/pages/fortune/index.vue`
|
||
|
||
- [ ] **步骤 1:添加 i18n 导入**
|
||
- [ ] **步骤 2:替换模板硬编码中文** — `日运` → `{{ $t('fortune.daily') }}`、`月运` → `{{ $t('fortune.monthly') }}`、`选择日期` → `{{ $t('fortune.selectDate') }}`、`选择月份` → `{{ $t('fortune.selectMonth') }}`、`综合运势:` → `{{ $t('fortune.overallFortune') }}:`、`分` → `{{ $t('ziwei.scoreUnit') }}`、`事业:` → `{{ $t('fortune.career') }}:`、`财运:` → `{{ $t('fortune.wealth') }}:`、`感情:` → `{{ $t('fortune.relationship') }}:`、`健康:` → `{{ $t('fortune.health') }}:`、`幸运色:` → `{{ $t('fortune.luckyColor') }}:`、`幸运数字:` → `{{ $t('fortune.luckyNumber') }}:`、`幸运方位:` → `{{ $t('fortune.luckyDirection') }}:`、`请先在紫微斗数页面完成排盘` → `{{ $t('fortune.noChart') }}`
|
||
- [ ] **步骤 3:添加 onShow 动态设置导航栏标题**
|
||
- [ ] **步骤 4:验证构建**
|
||
- [ ] **步骤 5:Commit**
|
||
|
||
### 任务 3.4:pages.json 保持中文初始值
|
||
|
||
**文件:** `src/pages.json`(无需修改)
|
||
|
||
`pages.json` 中的 `navigationBarTitleText` 保持现有中文值作为首次渲染前的兜底,运行时由各页面 `onShow` 生命周期动态覆盖。
|
||
|
||
---
|
||
|
||
## Phase 4:组件改造 — 10 个组件
|
||
|
||
**依赖:** Phase 1, Phase 2
|
||
|
||
```mermaid
|
||
graph TD
|
||
C1["BottomNavigation"] --> CV["验证构建"]
|
||
C2["EmptyState"] --> CV
|
||
C3["SearchConditionPanel"] --> CV
|
||
C4["SearchConditionItem"] --> CV
|
||
C5["SearchResultList"] --> CV
|
||
C6["SearchResultCard"] --> CV
|
||
C7["SortSwitcher"] --> CV
|
||
C8["ExportPanel"] --> CV
|
||
C9["SearchHistoryPanel"] --> CV
|
||
C10["TemplatePanel"] --> CV
|
||
```
|
||
|
||
### 任务 4.1:改造 BottomNavigation
|
||
|
||
**文件:** 修改 `src/components/BottomNavigation/BottomNavigation.vue`
|
||
|
||
- [ ] **步骤 1:添加 i18n 导入** — `import { useI18n } from 'vue-i18n'` + `const { t } = useI18n()`
|
||
- [ ] **步骤 2:将 tabs 数组中的 label 改为 computed** — `label: t('nav.almanac')`、`label: t('nav.ziwei')`、`label: t('nav.fortune')`
|
||
- [ ] **步骤 3:Commit**
|
||
|
||
### 任务 4.2:改造 EmptyState
|
||
|
||
**文件:** 修改 `src/components/EmptyState/index.vue`
|
||
|
||
- [ ] **步骤 1:移除 withDefaults 中的中文默认值** — 移除 `title`、`description`、`actionText` 的默认值,由调用方通过 `$t()` 传入
|
||
- [ ] **步骤 2:Commit**
|
||
|
||
### 任务 4.3:改造 SearchConditionPanel
|
||
|
||
**文件:** 修改 `src/components/SearchConditionPanel/index.vue`
|
||
|
||
- [ ] **步骤 1:添加 i18n 导入并替换硬编码中文** — `搜索条件` → `{{ $t('search.conditions') }}`、`添加条件` → `{{ $t('search.addCondition') }}`、`请添加搜索条件` → `{{ $t('search.addConditionEmpty') }}`、`搜索天数` → `{{ $t('search.days') }}`、`天` → `{{ $t('search.dayUnit') }}`、`搜索` → `{{ $t('common.search') }}`
|
||
- [ ] **步骤 2:Commit**
|
||
|
||
### 任务 4.4:改造 SearchConditionItem
|
||
|
||
**文件:** 修改 `src/components/SearchConditionItem/index.vue`
|
||
|
||
- [ ] **步骤 1:添加 i18n 导入并替换硬编码中文** — `事项` → `{{ $t('search.items') }}`、`逻辑运算符` → `{{ $t('search.operator') }}`、`排除条件` → `{{ $t('search.excludeCondition') }}`
|
||
- [ ] **步骤 2:将 typeOptions 和 operatorOptions 改为 computed** — `{ label: t('search.typeSuitable'), value: 'suitable' }`、`{ label: t('search.typeUnsuitable'), value: 'unsuitable' }`、`{ label: t('search.operatorAnd'), value: 'and' }`、`{ label: t('search.operatorOr'), value: 'or' }`
|
||
- [ ] **步骤 3:Commit** — 注意:`suitableActivities` 和 `avoidActivities` 数组保持中文硬编码(领域术语策略)
|
||
|
||
### 任务 4.5:改造 SearchResultList
|
||
|
||
**文件:** 修改 `src/components/SearchResultList/index.vue`
|
||
|
||
- [ ] **步骤 1:添加 i18n 导入并替换硬编码中文** — `搜索结果` → `{{ $t('search.searchResult') }}`、`共{results.length}条结果` → `{{ $t('search.resultCount', { count: results.length }) }}`、`加载中...` → `{{ $t('common.loading') }}`
|
||
- [ ] **步骤 2:Commit**
|
||
|
||
### 任务 4.6:改造 SearchResultCard
|
||
|
||
**文件:** 修改 `src/components/SearchResultCard/index.vue`
|
||
|
||
- [ ] **步骤 1:添加 i18n 导入并替换硬编码中文** — `宜` → `{{ $t('search.typeSuitable') }}`、`忌` → `{{ $t('search.typeUnsuitable') }}`、`匹配度:` → `{{ $t('search.matchCount', { count: result.matchCount }) }}`
|
||
- [ ] **步骤 2:Commit**
|
||
|
||
### 任务 4.7:改造 SortSwitcher
|
||
|
||
**文件:** 修改 `src/components/SortSwitcher/index.vue`
|
||
|
||
- [ ] **步骤 1:添加 i18n 导入并替换硬编码中文** — `排序` → `{{ $t('search.sort') }}`、`日期` → `{{ $t('search.sortByDate') }}`、`匹配度` → `{{ $t('search.sortByMatch') }}`
|
||
- [ ] **步骤 2:Commit**
|
||
|
||
### 任务 4.8:改造 ExportPanel
|
||
|
||
**文件:** 修改 `src/components/ExportPanel/index.vue`
|
||
|
||
- [ ] **步骤 1:添加 i18n 导入并替换硬编码中文** — `导出搜索结果` → `{{ $t('export.title') }}`、`选择导出格式` → `{{ $t('export.selectFormat') }}`、`选择导出内容` → `{{ $t('export.selectContent') }}`、`取消` → `{{ $t('common.cancel') }}`、`导出` → `{{ $t('common.confirm') }}`
|
||
- [ ] **步骤 2:将 contentOptions 改为 computed** — `{ label: t('export.date'), value: 'date' }`、`{ label: t('export.lunarDate'), value: 'lunarDate' }`、`{ label: t('export.weekday'), value: 'weekday' }`、`{ label: t('export.matchedItems'), value: 'matchedItems' }`、`{ label: t('export.matchCount'), value: 'matchCount' }`
|
||
- [ ] **步骤 3:Commit**
|
||
|
||
### 任务 4.9:改造 SearchHistoryPanel
|
||
|
||
**文件:** 修改 `src/components/SearchHistoryPanel/index.vue`
|
||
|
||
- [ ] **步骤 1:添加 i18n 导入并替换硬编码中文** — `搜索历史` → `{{ $t('history.title') }}`、`清除历史` → `{{ $t('history.clear') }}`、`确认清除` → `{{ $t('history.clearConfirm') }}`、`确定要清除所有搜索历史吗?` → `{{ $t('history.clearConfirmMsg') }}`、`暂无搜索历史` → `{{ $t('history.empty') }}`、`执行搜索后,搜索条件将显示在这里` → `{{ $t('history.emptyDesc') }}`
|
||
- [ ] **步骤 2:将 formatTime 函数中的中文改为 t() 调用** — `刚刚` → `t('history.justNow')`、`小时前` → `t('history.hoursAgo', { count })`、`天前` → `t('history.daysAgo', { count })`
|
||
- [ ] **步骤 3:Commit**
|
||
|
||
### 任务 4.10:改造 TemplatePanel
|
||
|
||
**文件:** 修改 `src/components/TemplatePanel/index.vue`
|
||
|
||
- [ ] **步骤 1:添加 i18n 导入并替换硬编码中文** — `搜索模板` → `{{ $t('template.title') }}`、搜索框占位 → `{{ $t('template.searchPlaceholder') }}`、`暂无模板` → `{{ $t('template.empty') }}`、`没有找到符合条件的模板` → `{{ $t('template.emptyDesc') }}`、`全部` → `{{ $t('template.all') }}`
|
||
- [ ] **步骤 2:Commit**
|
||
|
||
---
|
||
|
||
## Phase 5:测试与验证
|
||
|
||
**依赖:** Phase 3, Phase 4
|
||
|
||
```mermaid
|
||
graph TD
|
||
T1["任务 5.1: 翻译完整性测试"] --> T4["任务 5.4: 全量构建验证"]
|
||
T2["任务 5.2: 插值格式测试"] --> T4
|
||
T3["任务 5.3: 组件 i18n 集成测试"] --> T4
|
||
T4 --> T5["任务 5.5: 运行全量测试"]
|
||
T5 --> T6["任务 5.6: 最终 Commit"]
|
||
```
|
||
|
||
### 任务 5.1:创建翻译完整性测试
|
||
|
||
**文件:** 创建 `src/locales/__tests__/completeness.test.ts`
|
||
|
||
- [ ] **步骤 1:编写测试** — 校验所有 9 种语言的翻译键与 zh-CN 完全一致(嵌套 key 逐层比对)
|
||
- [ ] **步骤 2:运行测试验证通过**
|
||
|
||
运行:`cd everything-is-suitable-uniapp && npx vitest run src/locales/__tests__/completeness.test.ts`
|
||
|
||
预期:PASS
|
||
|
||
- [ ] **步骤 3:Commit**
|
||
|
||
### 任务 5.2:创建插值格式测试
|
||
|
||
**文件:** 创建 `src/locales/__tests__/interpolation.test.ts`
|
||
|
||
- [ ] **步骤 1:编写测试** — 校验所有语言的插值变量名一致(如 `{count}` 在所有语言中均存在)
|
||
- [ ] **步骤 2:运行测试验证通过**
|
||
- [ ] **步骤 3:Commit**
|
||
|
||
### 任务 5.3:创建组件 i18n 集成测试
|
||
|
||
**文件:** 修改现有组件测试文件
|
||
|
||
- [ ] **步骤 1:在 vitest 配置中添加 vue-i18n 插件** — 确保 `@vue/test-utils` 的 `mount` 能正确注入 i18n
|
||
- [ ] **步骤 2:为 BottomNavigation 编写 i18n 测试** — 验证渲染文本来自翻译键
|
||
- [ ] **步骤 3:运行测试验证通过**
|
||
- [ ] **步骤 4:Commit**
|
||
|
||
### 任务 5.4:全量构建验证
|
||
|
||
- [ ] **步骤 1:运行 vite build**
|
||
|
||
运行:`cd everything-is-suitable-uniapp && npx vite build 2>&1 | tail -10`
|
||
|
||
预期:构建成功,无错误
|
||
|
||
- [ ] **步骤 2:运行 H5 开发服务器验证页面渲染**
|
||
|
||
运行:`cd everything-is-suitable-uniapp && npm run dev:h5`
|
||
|
||
预期:页面正常渲染,导航栏标题为中文(默认 locale),底部导航显示中文
|
||
|
||
### 任务 5.5:运行全量测试
|
||
|
||
- [ ] **步骤 1:运行所有测试**
|
||
|
||
运行:`cd everything-is-suitable-uniapp && npx vitest run`
|
||
|
||
预期:所有测试通过
|
||
|
||
### 任务 5.6:最终 Commit
|
||
|
||
- [ ] **步骤 1:Commit**
|
||
|
||
`cd everything-is-suitable-uniapp && git add -A && git commit -m "feat(i18n): 完成 UniApp 国际化改造 — 9 种语言支持"`
|
||
|
||
---
|
||
|
||
## 自检清单
|
||
|
||
1. **规格覆盖度:** 设计规格中的 9 种语言 ✅、集中式翻译文件 ✅、vue-i18n ✅、领域术语保留 ✅、pages.json 运行时覆盖 ✅、3 个页面改造 ✅、10 个组件改造 ✅、翻译完整性测试 ✅
|
||
2. **占位符扫描:** 无 TODO/待定/后续实现 ✅
|
||
3. **类型一致性:** 所有翻译键名在 zh-CN.ts 定义,其他语言文件保持一致 ✅
|