chore: 添加文档、资源与测试输出
- assets/ 静态资源 - docs/superpowers/ 技能文档 - dogfood-output/ 测试验证输出
This commit is contained in:
@@ -0,0 +1,91 @@
|
||||
{
|
||||
"plan": {
|
||||
"id": "uniapp-i18n",
|
||||
"name": "UniApp 主应用国际化(i18n)实现计划",
|
||||
"version": "1.0.0",
|
||||
"date": "2026-04-29",
|
||||
"designDoc": "docs/superpowers/specs/2026-04-28-uniapp-i18n-design.md",
|
||||
"goal": "为 UniApp 主应用引入 vue-i18n 国际化体系,支持 9 种语言,将所有硬编码中文 UI 文本替换为 $t() / t() 调用",
|
||||
"architecture": "集中式翻译文件方案,所有翻译键值对按语言分文件存放于 src/locales/,通过 vue-i18n 实例注入 Vue 应用。领域术语保留中文原词不纳入翻译体系",
|
||||
"techStack": [
|
||||
"vue-i18n@9",
|
||||
"Vue 3 Composition API",
|
||||
"UniApp",
|
||||
"Vitest"
|
||||
],
|
||||
"executionMode": "sequential",
|
||||
"phases": [
|
||||
{
|
||||
"id": "phase-1",
|
||||
"name": "基础设施 — 安装 vue-i18n + 创建核心模块",
|
||||
"file": "phase-1-infrastructure.json",
|
||||
"status": "pending"
|
||||
},
|
||||
{
|
||||
"id": "phase-2",
|
||||
"name": "翻译文件 — 创建 8 种非中文翻译",
|
||||
"file": "phase-2-translation-files.json",
|
||||
"status": "pending"
|
||||
},
|
||||
{
|
||||
"id": "phase-3",
|
||||
"name": "页面改造 — 3 个页面 + pages.json",
|
||||
"file": "phase-3-page-migration.json",
|
||||
"status": "pending"
|
||||
},
|
||||
{
|
||||
"id": "phase-4",
|
||||
"name": "组件改造 — 10 个组件",
|
||||
"file": "phase-4-component-migration.json",
|
||||
"status": "pending"
|
||||
},
|
||||
{
|
||||
"id": "phase-5",
|
||||
"name": "测试与验证",
|
||||
"file": "phase-5-testing-and-verification.json",
|
||||
"status": "pending"
|
||||
}
|
||||
],
|
||||
"fileStructure": {
|
||||
"create": [
|
||||
"src/locales/index.ts",
|
||||
"src/locales/zh-CN.ts",
|
||||
"src/locales/zh-TW.ts",
|
||||
"src/locales/en.ts",
|
||||
"src/locales/ja.ts",
|
||||
"src/locales/ko.ts",
|
||||
"src/locales/de.ts",
|
||||
"src/locales/fr.ts",
|
||||
"src/locales/es.ts",
|
||||
"src/locales/pt.ts",
|
||||
"src/locales/__tests__/completeness.test.ts",
|
||||
"src/locales/__tests__/interpolation.test.ts"
|
||||
],
|
||||
"modify": [
|
||||
"package.json",
|
||||
"src/main.ts",
|
||||
"src/pages/almanac-search/index.vue",
|
||||
"src/pages/ziwei/index.vue",
|
||||
"src/pages/fortune/index.vue",
|
||||
"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"
|
||||
],
|
||||
"delete": []
|
||||
},
|
||||
"qualityGates": {
|
||||
"translationKeyConsistency": "所有 9 种语言翻译键与 zh-CN 完全一致",
|
||||
"interpolationConsistency": "所有语言的插值变量名一致",
|
||||
"buildSuccess": "vite build 无错误",
|
||||
"allTestsPass": "npx vitest run 全部通过",
|
||||
"noHardcodedChinese": "页面和组件中无硬编码中文 UI 文本(领域术语除外)"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
{
|
||||
"phase": {
|
||||
"id": "phase-1",
|
||||
"name": "基础设施 — 安装 vue-i18n + 创建核心模块",
|
||||
"description": "安装 vue-i18n 依赖,创建翻译核心模块(index.ts + zh-CN.ts),改造 main.ts 挂载 i18n",
|
||||
"dependencies": [],
|
||||
"tasks": [
|
||||
{
|
||||
"id": "1.1",
|
||||
"name": "安装 vue-i18n 依赖",
|
||||
"status": "pending",
|
||||
"description": "通过 npm 安装 vue-i18n@9 并验证版本",
|
||||
"files": {
|
||||
"modify": ["package.json", "package-lock.json"]
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"id": "1.1.1",
|
||||
"action": "install",
|
||||
"description": "安装 vue-i18n@9",
|
||||
"runCommand": "cd everything-is-suitable-uniapp && npm install vue-i18n@9",
|
||||
"expectedResult": "package.json 中出现 vue-i18n 依赖"
|
||||
},
|
||||
{
|
||||
"id": "1.1.2",
|
||||
"action": "verify",
|
||||
"description": "验证安装版本",
|
||||
"runCommand": "cd everything-is-suitable-uniapp && node -e \"const v = require('vue-i18n/package.json'); console.log(v.version)\"",
|
||||
"expectedResult": "输出 9.x.x 版本号"
|
||||
},
|
||||
{
|
||||
"id": "1.1.3",
|
||||
"action": "commit",
|
||||
"message": "chore: 安装 vue-i18n@9 依赖"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "1.2",
|
||||
"name": "创建 zh-CN 主翻译源文件",
|
||||
"status": "pending",
|
||||
"description": "创建 src/locales/zh-CN.ts,包含 common/nav/almanac/ziwei/fortune/search/template/export/history 共 9 个命名空间约 80 个翻译键",
|
||||
"files": {
|
||||
"create": ["src/locales/zh-CN.ts"]
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"id": "1.2.1",
|
||||
"action": "write_implementation",
|
||||
"description": "创建 zh-CN.ts 翻译源文件",
|
||||
"translationNamespaces": ["common", "nav", "almanac", "ziwei", "fortune", "search", "template", "export", "history"],
|
||||
"sourceRef": "设计规格翻译键清单"
|
||||
},
|
||||
{
|
||||
"id": "1.2.2",
|
||||
"action": "commit",
|
||||
"message": "feat(i18n): 创建简体中文主翻译源 zh-CN.ts"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "1.3",
|
||||
"name": "创建 locales/index.ts 核心模块",
|
||||
"status": "pending",
|
||||
"description": "创建 vue-i18n 实例、语言检测、切换、持久化逻辑",
|
||||
"files": {
|
||||
"create": ["src/locales/index.ts"]
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"id": "1.3.1",
|
||||
"action": "write_implementation",
|
||||
"description": "创建 index.ts 核心模块,包含 createI18n/detectLocale/setLocale/getLocale/SUPPORTED_LOCALES/localeNames",
|
||||
"exports": ["i18n", "setLocale", "getLocale", "SUPPORTED_LOCALES", "localeNames"],
|
||||
"sourceRef": "设计规格核心模块设计"
|
||||
},
|
||||
{
|
||||
"id": "1.3.2",
|
||||
"action": "commit",
|
||||
"message": "feat(i18n): 创建 vue-i18n 实例与语言检测/切换核心模块"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "1.4",
|
||||
"name": "改造 main.ts 挂载 i18n",
|
||||
"status": "pending",
|
||||
"description": "在 main.ts 中导入 i18n 并通过 app.use() 挂载",
|
||||
"files": {
|
||||
"modify": ["src/main.ts"]
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"id": "1.4.1",
|
||||
"action": "write_implementation",
|
||||
"description": "修改 main.ts:添加 import { i18n } from './locales' 和 app.use(i18n)",
|
||||
"sourceRef": "设计规格 main.ts 改造"
|
||||
},
|
||||
{
|
||||
"id": "1.4.2",
|
||||
"action": "verify",
|
||||
"description": "验证构建无报错",
|
||||
"runCommand": "cd everything-is-suitable-uniapp && npx vite build --mode development 2>&1 | head -20",
|
||||
"expectedResult": "构建成功,无模块解析错误"
|
||||
},
|
||||
{
|
||||
"id": "1.4.3",
|
||||
"action": "commit",
|
||||
"message": "feat(i18n): 在 main.ts 中挂载 vue-i18n 实例"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
{
|
||||
"phase": {
|
||||
"id": "phase-2",
|
||||
"name": "翻译文件 — 创建 8 种非中文翻译",
|
||||
"description": "创建 zh-TW/en/ja/ko/de/fr/es/pt 共 8 种语言翻译文件,键结构必须与 zh-CN.ts 完全一致",
|
||||
"dependencies": ["phase-1"],
|
||||
"tasks": [
|
||||
{
|
||||
"id": "2.1",
|
||||
"name": "创建繁體中文翻译 zh-TW.ts",
|
||||
"status": "pending",
|
||||
"description": "简转繁,保持相同键结构",
|
||||
"files": { "create": ["src/locales/zh-TW.ts"] },
|
||||
"steps": [
|
||||
{ "id": "2.1.1", "action": "write_implementation", "description": "创建 zh-TW.ts,简转繁" },
|
||||
{ "id": "2.1.2", "action": "commit", "message": "feat(i18n): 添加繁體中文翻譯 zh-TW.ts" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "2.2",
|
||||
"name": "创建英文翻译 en.ts",
|
||||
"status": "pending",
|
||||
"description": "领域术语保留拼音(如 Zi Wei Dou Shu)",
|
||||
"files": { "create": ["src/locales/en.ts"] },
|
||||
"steps": [
|
||||
{ "id": "2.2.1", "action": "write_implementation", "description": "创建 en.ts,领域术语保留拼音" },
|
||||
{ "id": "2.2.2", "action": "commit", "message": "feat(i18n): 添加英文翻譯 en.ts" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "2.3",
|
||||
"name": "创建日文翻译 ja.ts",
|
||||
"status": "pending",
|
||||
"description": "命理术语保留汉字(如 紫微斗数、三方四正)",
|
||||
"files": { "create": ["src/locales/ja.ts"] },
|
||||
"steps": [
|
||||
{ "id": "2.3.1", "action": "write_implementation", "description": "创建 ja.ts,命理术语保留汉字" },
|
||||
{ "id": "2.3.2", "action": "commit", "message": "feat(i18n): 添加日文翻譯 ja.ts" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "2.4",
|
||||
"name": "创建韩文翻译 ko.ts",
|
||||
"status": "pending",
|
||||
"description": "命理术语保留汉字(如 자미두수)",
|
||||
"files": { "create": ["src/locales/ko.ts"] },
|
||||
"steps": [
|
||||
{ "id": "2.4.1", "action": "write_implementation", "description": "创建 ko.ts" },
|
||||
{ "id": "2.4.2", "action": "commit", "message": "feat(i18n): 添加韩文翻譯 ko.ts" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "2.5",
|
||||
"name": "创建德文翻译 de.ts",
|
||||
"status": "pending",
|
||||
"description": "领域术语保留拼音",
|
||||
"files": { "create": ["src/locales/de.ts"] },
|
||||
"steps": [
|
||||
{ "id": "2.5.1", "action": "write_implementation", "description": "创建 de.ts" },
|
||||
{ "id": "2.5.2", "action": "commit", "message": "feat(i18n): 添加德文翻譯 de.ts" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "2.6",
|
||||
"name": "创建法文翻译 fr.ts",
|
||||
"status": "pending",
|
||||
"description": "领域术语保留拼音",
|
||||
"files": { "create": ["src/locales/fr.ts"] },
|
||||
"steps": [
|
||||
{ "id": "2.6.1", "action": "write_implementation", "description": "创建 fr.ts" },
|
||||
{ "id": "2.6.2", "action": "commit", "message": "feat(i18n): 添加法文翻譯 fr.ts" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "2.7",
|
||||
"name": "创建西班牙文翻译 es.ts",
|
||||
"status": "pending",
|
||||
"description": "领域术语保留拼音",
|
||||
"files": { "create": ["src/locales/es.ts"] },
|
||||
"steps": [
|
||||
{ "id": "2.7.1", "action": "write_implementation", "description": "创建 es.ts" },
|
||||
{ "id": "2.7.2", "action": "commit", "message": "feat(i18n): 添加西班牙文翻譯 es.ts" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "2.8",
|
||||
"name": "创建葡萄牙文翻译 pt.ts",
|
||||
"status": "pending",
|
||||
"description": "领域术语保留拼音",
|
||||
"files": { "create": ["src/locales/pt.ts"] },
|
||||
"steps": [
|
||||
{ "id": "2.8.1", "action": "write_implementation", "description": "创建 pt.ts" },
|
||||
{ "id": "2.8.2", "action": "commit", "message": "feat(i18n): 添加葡萄牙文翻譯 pt.ts" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
{
|
||||
"phase": {
|
||||
"id": "phase-3",
|
||||
"name": "页面改造 — 3 个页面 + pages.json",
|
||||
"description": "改造 almanac-search/ziwei/fortune 三个页面,替换硬编码中文为 $t()/t() 调用,添加 onShow 动态导航栏标题",
|
||||
"dependencies": ["phase-1", "phase-2"],
|
||||
"tasks": [
|
||||
{
|
||||
"id": "3.1",
|
||||
"name": "改造黄历搜索页 almanac-search/index.vue",
|
||||
"status": "pending",
|
||||
"description": "替换模板和 script 中的硬编码中文,添加 onShow 导航栏标题",
|
||||
"files": { "modify": ["src/pages/almanac-search/index.vue"] },
|
||||
"steps": [
|
||||
{
|
||||
"id": "3.1.1",
|
||||
"action": "write_implementation",
|
||||
"description": "添加 i18n 导入:import { useI18n } from 'vue-i18n' + const { t } = useI18n()"
|
||||
},
|
||||
{
|
||||
"id": "3.1.2",
|
||||
"action": "write_implementation",
|
||||
"description": "替换模板硬编码中文:黄历搜索→$t('almanac.pageTitle')、搜索中...→$t('almanac.searching')、重试→$t('common.retry')"
|
||||
},
|
||||
{
|
||||
"id": "3.1.3",
|
||||
"action": "write_implementation",
|
||||
"description": "替换 script 硬编码中文:error.value = t('almanac.keywordHint')、t('almanac.noResult')、t('search.addConditionHint')、t('almanac.searchFailed')"
|
||||
},
|
||||
{
|
||||
"id": "3.1.4",
|
||||
"action": "write_implementation",
|
||||
"description": "添加 onShow:import { onShow } from '@dcloudio/uni-app' + onShow(() => { uni.setNavigationBarTitle({ title: t('almanac.pageTitle') }) })"
|
||||
},
|
||||
{
|
||||
"id": "3.1.5",
|
||||
"action": "verify",
|
||||
"description": "验证构建",
|
||||
"runCommand": "cd everything-is-suitable-uniapp && npx vite build --mode development 2>&1 | tail -5",
|
||||
"expectedResult": "构建成功"
|
||||
},
|
||||
{
|
||||
"id": "3.1.6",
|
||||
"action": "commit",
|
||||
"message": "feat(i18n): 改造黄历搜索页,替换硬编码中文为 $t() 调用"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "3.2",
|
||||
"name": "改造紫微斗数页 ziwei/index.vue",
|
||||
"status": "pending",
|
||||
"description": "替换模板和 script 中的硬编码中文,添加 onShow 导航栏标题",
|
||||
"files": { "modify": ["src/pages/ziwei/index.vue"] },
|
||||
"replacements": [
|
||||
{ "from": "出生信息", "to": "$t('ziwei.birthInfo')" },
|
||||
{ "from": "出生日期", "to": "$t('ziwei.birthDate')" },
|
||||
{ "from": "请选择", "to": "$t('ziwei.pleaseSelect')" },
|
||||
{ "from": "出生时辰", "to": "$t('ziwei.birthHour')" },
|
||||
{ "from": "性别", "to": "$t('ziwei.gender')" },
|
||||
{ "from": "男", "to": "$t('common.male')" },
|
||||
{ "from": "女", "to": "$t('common.female')" },
|
||||
{ "from": "排盘中...", "to": "$t('ziwei.generating')" },
|
||||
{ "from": "排盘", "to": "$t('ziwei.generate')" },
|
||||
{ "from": "紫微斗数盘", "to": "$t('ziwei.chartTitle')" },
|
||||
{ "from": "三方四正分析", "to": "$t('ziwei.sanFangAnalysis')" },
|
||||
{ "from": "三方得分", "to": "$t('ziwei.sanFangScore')" },
|
||||
{ "from": "四正得分", "to": "$t('ziwei.siZhengScore')" },
|
||||
{ "from": "综合评价", "to": "$t('ziwei.overallEval')" },
|
||||
{ "from": "盘面概述", "to": "$t('ziwei.summary')" },
|
||||
{ "from": "分", "to": "$t('ziwei.scoreUnit')" }
|
||||
],
|
||||
"steps": [
|
||||
{ "id": "3.2.1", "action": "write_implementation", "description": "添加 i18n 导入" },
|
||||
{ "id": "3.2.2", "action": "write_implementation", "description": "替换模板硬编码中文(16 处)" },
|
||||
{ "id": "3.2.3", "action": "write_implementation", "description": "添加 onShow 动态导航栏标题" },
|
||||
{ "id": "3.2.4", "action": "verify", "description": "验证构建", "runCommand": "cd everything-is-suitable-uniapp && npx vite build --mode development 2>&1 | tail -5", "expectedResult": "构建成功" },
|
||||
{ "id": "3.2.5", "action": "commit", "message": "feat(i18n): 改造紫微斗数页,替换硬编码中文为 $t() 调用" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "3.3",
|
||||
"name": "改造运势分析页 fortune/index.vue",
|
||||
"status": "pending",
|
||||
"description": "替换模板和 script 中的硬编码中文,添加 onShow 导航栏标题",
|
||||
"files": { "modify": ["src/pages/fortune/index.vue"] },
|
||||
"replacements": [
|
||||
{ "from": "日运", "to": "$t('fortune.daily')" },
|
||||
{ "from": "月运", "to": "$t('fortune.monthly')" },
|
||||
{ "from": "选择日期", "to": "$t('fortune.selectDate')" },
|
||||
{ "from": "选择月份", "to": "$t('fortune.selectMonth')" },
|
||||
{ "from": "综合运势:", "to": "$t('fortune.overallFortune'):" },
|
||||
{ "from": "事业:", "to": "$t('fortune.career'):" },
|
||||
{ "from": "财运:", "to": "$t('fortune.wealth'):" },
|
||||
{ "from": "感情:", "to": "$t('fortune.relationship'):" },
|
||||
{ "from": "健康:", "to": "$t('fortune.health'):" },
|
||||
{ "from": "幸运色:", "to": "$t('fortune.luckyColor'):" },
|
||||
{ "from": "幸运数字:", "to": "$t('fortune.luckyNumber'):" },
|
||||
{ "from": "幸运方位:", "to": "$t('fortune.luckyDirection'):" },
|
||||
{ "from": "请先在紫微斗数页面完成排盘", "to": "$t('fortune.noChart')" }
|
||||
],
|
||||
"steps": [
|
||||
{ "id": "3.3.1", "action": "write_implementation", "description": "添加 i18n 导入" },
|
||||
{ "id": "3.3.2", "action": "write_implementation", "description": "替换模板硬编码中文(13 处)" },
|
||||
{ "id": "3.3.3", "action": "write_implementation", "description": "添加 onShow 动态导航栏标题" },
|
||||
{ "id": "3.3.4", "action": "verify", "description": "验证构建", "runCommand": "cd everything-is-suitable-uniapp && npx vite build --mode development 2>&1 | tail -5", "expectedResult": "构建成功" },
|
||||
{ "id": "3.3.5", "action": "commit", "message": "feat(i18n): 改造运势分析页,替换硬编码中文为 $t() 调用" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "3.4",
|
||||
"name": "pages.json 保持中文初始值",
|
||||
"status": "pending",
|
||||
"description": "pages.json 中的 navigationBarTitleText 保持现有中文值作为首次渲染前的兜底,运行时由各页面 onShow 生命周期动态覆盖。无需改动此文件",
|
||||
"files": {},
|
||||
"steps": [
|
||||
{ "id": "3.4.1", "action": "verify", "description": "确认 pages.json 无需修改,中文初始值作为兜底" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,183 @@
|
||||
{
|
||||
"phase": {
|
||||
"id": "phase-4",
|
||||
"name": "组件改造 — 10 个组件",
|
||||
"description": "改造 10 个组件,替换硬编码中文为 $t()/t() 调用。领域术语(如 suitableActivities/avoidActivities 数组)保留中文不翻译",
|
||||
"dependencies": ["phase-1", "phase-2"],
|
||||
"tasks": [
|
||||
{
|
||||
"id": "4.1",
|
||||
"name": "改造 BottomNavigation",
|
||||
"status": "pending",
|
||||
"description": "将 tabs 数组中的 label 改为 computed,使用 t() 调用",
|
||||
"files": { "modify": ["src/components/BottomNavigation/BottomNavigation.vue"] },
|
||||
"replacements": [
|
||||
{ "from": "黄历", "to": "t('nav.almanac')" },
|
||||
{ "from": "紫微", "to": "t('nav.ziwei')" },
|
||||
{ "from": "运势", "to": "t('nav.fortune')" }
|
||||
],
|
||||
"steps": [
|
||||
{ "id": "4.1.1", "action": "write_implementation", "description": "添加 i18n 导入 + 将 tabs 改为 computed" },
|
||||
{ "id": "4.1.2", "action": "commit", "message": "feat(i18n): 改造 BottomNavigation 组件" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "4.2",
|
||||
"name": "改造 EmptyState",
|
||||
"status": "pending",
|
||||
"description": "移除 withDefaults 中的中文默认值,由调用方通过 $t() 传入",
|
||||
"files": { "modify": ["src/components/EmptyState/index.vue"] },
|
||||
"steps": [
|
||||
{ "id": "4.2.1", "action": "write_implementation", "description": "移除 title/description/actionText 的中文默认值" },
|
||||
{ "id": "4.2.2", "action": "commit", "message": "feat(i18n): 改造 EmptyState 组件,移除中文默认值" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "4.3",
|
||||
"name": "改造 SearchConditionPanel",
|
||||
"status": "pending",
|
||||
"description": "替换搜索条件面板中的硬编码中文",
|
||||
"files": { "modify": ["src/components/SearchConditionPanel/index.vue"] },
|
||||
"replacements": [
|
||||
{ "from": "搜索条件", "to": "$t('search.conditions')" },
|
||||
{ "from": "添加条件", "to": "$t('search.addCondition')" },
|
||||
{ "from": "请添加搜索条件", "to": "$t('search.addConditionEmpty')" },
|
||||
{ "from": "搜索天数", "to": "$t('search.days')" },
|
||||
{ "from": "天", "to": "$t('search.dayUnit')" },
|
||||
{ "from": "搜索", "to": "$t('common.search')" }
|
||||
],
|
||||
"steps": [
|
||||
{ "id": "4.3.1", "action": "write_implementation", "description": "添加 i18n 导入 + 替换 6 处硬编码中文" },
|
||||
{ "id": "4.3.2", "action": "commit", "message": "feat(i18n): 改造 SearchConditionPanel 组件" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "4.4",
|
||||
"name": "改造 SearchConditionItem",
|
||||
"status": "pending",
|
||||
"description": "替换硬编码中文,将 typeOptions/operatorOptions 改为 computed。领域术语保留中文",
|
||||
"files": { "modify": ["src/components/SearchConditionItem/index.vue"] },
|
||||
"replacements": [
|
||||
{ "from": "事项", "to": "$t('search.items')" },
|
||||
{ "from": "逻辑运算符", "to": "$t('search.operator')" },
|
||||
{ "from": "排除条件", "to": "$t('search.excludeCondition')" },
|
||||
{ "from": "宜", "to": "t('search.typeSuitable')" },
|
||||
{ "from": "忌", "to": "t('search.typeUnsuitable')" },
|
||||
{ "from": "与(AND)", "to": "t('search.operatorAnd')" },
|
||||
{ "from": "或(OR)", "to": "t('search.operatorOr')" }
|
||||
],
|
||||
"note": "suitableActivities 和 avoidActivities 数组保持中文硬编码(领域术语策略)",
|
||||
"steps": [
|
||||
{ "id": "4.4.1", "action": "write_implementation", "description": "添加 i18n 导入 + 替换模板中文 + 将 typeOptions/operatorOptions 改为 computed" },
|
||||
{ "id": "4.4.2", "action": "commit", "message": "feat(i18n): 改造 SearchConditionItem 组件(领域术语保留中文)" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "4.5",
|
||||
"name": "改造 SearchResultList",
|
||||
"status": "pending",
|
||||
"description": "替换搜索结果列表中的硬编码中文",
|
||||
"files": { "modify": ["src/components/SearchResultList/index.vue"] },
|
||||
"replacements": [
|
||||
{ "from": "搜索结果", "to": "$t('search.searchResult')" },
|
||||
{ "from": "共{results.length}条结果", "to": "$t('search.resultCount', { count: results.length })" },
|
||||
{ "from": "加载中...", "to": "$t('common.loading')" }
|
||||
],
|
||||
"steps": [
|
||||
{ "id": "4.5.1", "action": "write_implementation", "description": "添加 i18n 导入 + 替换 3 处硬编码中文" },
|
||||
{ "id": "4.5.2", "action": "commit", "message": "feat(i18n): 改造 SearchResultList 组件" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "4.6",
|
||||
"name": "改造 SearchResultCard",
|
||||
"status": "pending",
|
||||
"description": "替换搜索结果卡片中的硬编码中文",
|
||||
"files": { "modify": ["src/components/SearchResultCard/index.vue"] },
|
||||
"replacements": [
|
||||
{ "from": "宜", "to": "$t('search.typeSuitable')" },
|
||||
{ "from": "忌", "to": "$t('search.typeUnsuitable')" },
|
||||
{ "from": "匹配度:", "to": "$t('search.matchCount', { count: result.matchCount })" }
|
||||
],
|
||||
"steps": [
|
||||
{ "id": "4.6.1", "action": "write_implementation", "description": "添加 i18n 导入 + 替换 3 处硬编码中文" },
|
||||
{ "id": "4.6.2", "action": "commit", "message": "feat(i18n): 改造 SearchResultCard 组件" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "4.7",
|
||||
"name": "改造 SortSwitcher",
|
||||
"status": "pending",
|
||||
"description": "替换排序切换器中的硬编码中文",
|
||||
"files": { "modify": ["src/components/SortSwitcher/index.vue"] },
|
||||
"replacements": [
|
||||
{ "from": "排序", "to": "$t('search.sort')" },
|
||||
{ "from": "日期", "to": "$t('search.sortByDate')" },
|
||||
{ "from": "匹配度", "to": "$t('search.sortByMatch')" }
|
||||
],
|
||||
"steps": [
|
||||
{ "id": "4.7.1", "action": "write_implementation", "description": "添加 i18n 导入 + 替换 3 处硬编码中文" },
|
||||
{ "id": "4.7.2", "action": "commit", "message": "feat(i18n): 改造 SortSwitcher 组件" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "4.8",
|
||||
"name": "改造 ExportPanel",
|
||||
"status": "pending",
|
||||
"description": "替换导出面板中的硬编码中文,将 contentOptions 改为 computed",
|
||||
"files": { "modify": ["src/components/ExportPanel/index.vue"] },
|
||||
"replacements": [
|
||||
{ "from": "导出搜索结果", "to": "$t('export.title')" },
|
||||
{ "from": "选择导出格式", "to": "$t('export.selectFormat')" },
|
||||
{ "from": "选择导出内容", "to": "$t('export.selectContent')" },
|
||||
{ "from": "取消", "to": "$t('common.cancel')" },
|
||||
{ "from": "导出", "to": "$t('common.confirm')" }
|
||||
],
|
||||
"steps": [
|
||||
{ "id": "4.8.1", "action": "write_implementation", "description": "添加 i18n 导入 + 替换模板中文 + 将 contentOptions 改为 computed" },
|
||||
{ "id": "4.8.2", "action": "commit", "message": "feat(i18n): 改造 ExportPanel 组件" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "4.9",
|
||||
"name": "改造 SearchHistoryPanel",
|
||||
"status": "pending",
|
||||
"description": "替换搜索历史面板中的硬编码中文,将 formatTime 中的中文改为 t() 调用",
|
||||
"files": { "modify": ["src/components/SearchHistoryPanel/index.vue"] },
|
||||
"replacements": [
|
||||
{ "from": "搜索历史", "to": "$t('history.title')" },
|
||||
{ "from": "清除历史", "to": "$t('history.clear')" },
|
||||
{ "from": "确认清除", "to": "$t('history.clearConfirm')" },
|
||||
{ "from": "确定要清除所有搜索历史吗?", "to": "$t('history.clearConfirmMsg')" },
|
||||
{ "from": "暂无搜索历史", "to": "$t('history.empty')" },
|
||||
{ "from": "执行搜索后,搜索条件将显示在这里", "to": "$t('history.emptyDesc')" },
|
||||
{ "from": "刚刚", "to": "t('history.justNow')" },
|
||||
{ "from": "小时前", "to": "t('history.hoursAgo', { count })" },
|
||||
{ "from": "天前", "to": "t('history.daysAgo', { count })" }
|
||||
],
|
||||
"steps": [
|
||||
{ "id": "4.9.1", "action": "write_implementation", "description": "添加 i18n 导入 + 替换模板中文 + 改造 formatTime 函数" },
|
||||
{ "id": "4.9.2", "action": "commit", "message": "feat(i18n): 改造 SearchHistoryPanel 组件" }
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "4.10",
|
||||
"name": "改造 TemplatePanel",
|
||||
"status": "pending",
|
||||
"description": "替换搜索模板面板中的硬编码中文",
|
||||
"files": { "modify": ["src/components/TemplatePanel/index.vue"] },
|
||||
"replacements": [
|
||||
{ "from": "搜索模板", "to": "$t('template.title')" },
|
||||
{ "from": "搜索模板(占位符)", "to": "$t('template.searchPlaceholder')" },
|
||||
{ "from": "暂无模板", "to": "$t('template.empty')" },
|
||||
{ "from": "没有找到符合条件的模板", "to": "$t('template.emptyDesc')" },
|
||||
{ "from": "全部", "to": "$t('template.all')" }
|
||||
],
|
||||
"steps": [
|
||||
{ "id": "4.10.1", "action": "write_implementation", "description": "添加 i18n 导入 + 替换 5 处硬编码中文" },
|
||||
{ "id": "4.10.2", "action": "commit", "message": "feat(i18n): 改造 TemplatePanel 组件" }
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,145 @@
|
||||
{
|
||||
"phase": {
|
||||
"id": "phase-5",
|
||||
"name": "测试与验证",
|
||||
"description": "创建翻译完整性测试、插值格式测试、组件 i18n 集成测试,运行全量构建和测试验证",
|
||||
"dependencies": ["phase-3", "phase-4"],
|
||||
"tasks": [
|
||||
{
|
||||
"id": "5.1",
|
||||
"name": "创建翻译完整性测试",
|
||||
"status": "pending",
|
||||
"description": "校验所有 9 种语言的翻译键与 zh-CN 完全一致(嵌套 key 逐层比对)",
|
||||
"files": {
|
||||
"create": ["src/locales/__tests__/completeness.test.ts"]
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"id": "5.1.1",
|
||||
"action": "write_test",
|
||||
"description": "编写翻译完整性测试:导入所有 9 种语言翻译,递归比对键结构,报告缺失/多余键"
|
||||
},
|
||||
{
|
||||
"id": "5.1.2",
|
||||
"action": "run_test_verify_pass",
|
||||
"description": "运行测试验证通过",
|
||||
"runCommand": "cd everything-is-suitable-uniapp && npx vitest run src/locales/__tests__/completeness.test.ts",
|
||||
"expectedResult": "PASS — 所有语言键结构一致"
|
||||
},
|
||||
{
|
||||
"id": "5.1.3",
|
||||
"action": "commit",
|
||||
"message": "test(i18n): 添加翻译完整性校验测试"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "5.2",
|
||||
"name": "创建插值格式测试",
|
||||
"status": "pending",
|
||||
"description": "校验所有语言的插值变量名一致(如 {count} 在所有语言中均存在)",
|
||||
"files": {
|
||||
"create": ["src/locales/__tests__/interpolation.test.ts"]
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"id": "5.2.1",
|
||||
"action": "write_test",
|
||||
"description": "编写插值格式测试:提取所有 {variable} 占位符,比对各语言一致性"
|
||||
},
|
||||
{
|
||||
"id": "5.2.2",
|
||||
"action": "run_test_verify_pass",
|
||||
"description": "运行测试验证通过",
|
||||
"runCommand": "cd everything-is-suitable-uniapp && npx vitest run src/locales/__tests__/interpolation.test.ts",
|
||||
"expectedResult": "PASS — 所有语言插值变量一致"
|
||||
},
|
||||
{
|
||||
"id": "5.2.3",
|
||||
"action": "commit",
|
||||
"message": "test(i18n): 添加插值格式校验测试"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "5.3",
|
||||
"name": "创建组件 i18n 集成测试",
|
||||
"status": "pending",
|
||||
"description": "在 vitest 配置中添加 vue-i18n 插件,为 BottomNavigation 编写 i18n 测试",
|
||||
"files": {
|
||||
"modify": ["src/components/BottomNavigation/__tests__/BottomNavigation.test.ts"]
|
||||
},
|
||||
"steps": [
|
||||
{
|
||||
"id": "5.3.1",
|
||||
"action": "write_implementation",
|
||||
"description": "在 vitest 配置中添加 vue-i18n 插件,确保 @vue/test-utils 的 mount 能正确注入 i18n"
|
||||
},
|
||||
{
|
||||
"id": "5.3.2",
|
||||
"action": "write_test",
|
||||
"description": "为 BottomNavigation 编写 i18n 测试:验证渲染文本来自翻译键"
|
||||
},
|
||||
{
|
||||
"id": "5.3.3",
|
||||
"action": "run_test_verify_pass",
|
||||
"description": "运行测试验证通过",
|
||||
"runCommand": "cd everything-is-suitable-uniapp && npx vitest run src/components/BottomNavigation/__tests__/",
|
||||
"expectedResult": "PASS"
|
||||
},
|
||||
{
|
||||
"id": "5.3.4",
|
||||
"action": "commit",
|
||||
"message": "test(i18n): 添加 BottomNavigation i18n 集成测试"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "5.4",
|
||||
"name": "全量构建验证",
|
||||
"status": "pending",
|
||||
"description": "运行 vite build 确认构建成功",
|
||||
"files": {},
|
||||
"steps": [
|
||||
{
|
||||
"id": "5.4.1",
|
||||
"action": "verify",
|
||||
"description": "运行 vite build",
|
||||
"runCommand": "cd everything-is-suitable-uniapp && npx vite build 2>&1 | tail -10",
|
||||
"expectedResult": "构建成功,无错误"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "5.5",
|
||||
"name": "运行全量测试",
|
||||
"status": "pending",
|
||||
"description": "运行所有测试确认无回归",
|
||||
"files": {},
|
||||
"steps": [
|
||||
{
|
||||
"id": "5.5.1",
|
||||
"action": "verify",
|
||||
"description": "运行所有测试",
|
||||
"runCommand": "cd everything-is-suitable-uniapp && npx vitest run",
|
||||
"expectedResult": "所有测试通过"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "5.6",
|
||||
"name": "最终 Commit",
|
||||
"status": "pending",
|
||||
"description": "提交所有剩余变更",
|
||||
"files": {},
|
||||
"steps": [
|
||||
{
|
||||
"id": "5.6.1",
|
||||
"action": "commit",
|
||||
"message": "feat(i18n): 完成 UniApp 国际化改造 — 9 种语言支持"
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,431 @@
|
||||
# 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 定义,其他语言文件保持一致 ✅
|
||||
Reference in New Issue
Block a user