初始化

This commit is contained in:
2026-03-05 21:27:11 +08:00
commit 130de0fd5d
140 changed files with 21972 additions and 0 deletions

View File

@@ -0,0 +1,253 @@
---
name: i18n
version: 3.0.0
description: "使用 vue-i18n 管理 Vue 3 应用的国际化。当需要添加多语言支持或管理翻译时使用。含语言包管理和路由国际化。"
---
> ⚠️ 核心执行流程已在 `.cursor/rules/skill-i18n.mdc` 中由 Cursor 自动注入。
> 本文件提供完整模板、代码示例和边缘场景处理,供 Agent 按需深入 Read。
# Internationalization (i18n) — Vue 3 + vue-i18n
## 触发条件
用户要求添加多语言支持、翻译内容、配置国际化路由。
## 执行流程
### 1. 检测现有 i18n 方案
```bash
# 检查是否已有 i18n 库
grep -E "vue-i18n|@intlify" package.json 2>/dev/null
ls src/i18n* src/locales* 2>/dev/null
```
### 2. 初始化 i18n如未配置
推荐方案:`vue-i18n`Vue 3 官方国际化方案)
```bash
npm install vue-i18n@9
```
创建目录结构:
```
src/locales/
├── index.ts # i18n 实例配置
├── zh-CN.ts # 中文(简体)— 使用 JS 扁平对象格式
├── en.ts # 英文 — 使用 JS 扁平对象格式
└── modules/ # 按模块拆分(大型项目,同样使用 JS 格式)
├── common.zh-CN.ts
└── common.en.ts
```
> **格式选择**:统一使用 `.ts` 文件(`export default { 'key': 'value' }`
> 而非 `.json`。原因JS 格式支持注释、支持函数(复数规则)、支持扁平键名中的特殊字符,
> 且与 vue-i18n v9 的 Composition API 配合更灵活。
> 若项目已使用 `.json`,保持现有格式,不强制迁移。
### 3. i18n 配置
```typescript
// src/locales/index.ts
import { createI18n } from 'vue-i18n'
import zhCN from './zh-CN.ts'
import en from './en.ts'
const i18n = createI18n({
legacy: false,
locale: localStorage.getItem('locale') || 'zh-CN',
fallbackLocale: 'en',
messages: {
'zh-CN': zhCN,
en,
},
})
export default i18n
```
```typescript
// src/main.ts
import i18n from './locales'
app.use(i18n)
```
### 4. 翻译键命名规范
**使用扁平 dot notation**(不使用嵌套对象),避免深层路径冲突:
```typescript
// ✅ 扁平 dot notation — 清晰、无歧义、工具友好
export default {
'common.action.save': '保存',
'common.action.cancel': '取消',
'common.action.delete': '删除',
'common.status.loading': '加载中...',
'auth.action.login': '登录',
'auth.action.logout': '退出登录',
'auth.action.signUp': '注册',
'home.hero.title': '欢迎',
'home.hero.description': '...',
}
// ❌ 嵌套对象 — 容易产生路径冲突
export default {
common: { save: '保存' },
pages: { home: { title: '...' } },
}
```
**命名公式**`{feature}.{context}.{action|status|label}`
| 段 | 含义 | 示例 |
|---|---|---|
| `feature` | 业务功能/模块 | `order``user``common` |
| `context` | 所在 UI 区域 | `list``form``dialog``action` |
| `action\|status\|label` | 具体语义 | `submit``loading``title` |
```typescript
// 示例
'order.list.title': '订单列表',
'order.form.submit': '提交订单',
'order.status.pending': '待处理',
'order.dialog.deleteConfirm': '确认删除该订单?',
'user.profile.edit': '编辑资料',
```
**键冲突预防**
```typescript
// ❌ 冲突:'order.edit' 同时是叶子节点和父节点前缀
'order.edit': '编辑',
'order.edit.title': '编辑订单',
// ✅ 修正:给叶子节点加上语义后缀
'order.edit.action': '编辑',
'order.edit.title': '编辑订单',
```
**参数化翻译**
```typescript
// 语言包
'order.total': '共 {count} 件商品,合计 {amount}',
'user.greeting': '你好,{name}',
// 组件中使用
t('order.total', { count: 5, amount: '¥100.00' })
t('user.greeting', { name: user.name })
```
**标准命名空间**(根据项目模块预定义,禁止随意创建):
| 命名空间 | 用途 | 文件 |
|----------|------|------|
| `common` | 通用 UI按钮、状态、提示 | `common.ts` |
| `auth` | 登录/注册/权限 | `auth.ts` |
| `menu` | 侧边栏/导航菜单 | `menu.ts` |
| `validation` | 表单校验提示 | `validation.ts` |
| `error` | 错误码/错误提示 | `error.ts` |
| `{module}` | 各业务模块 (order/user/...) | `{module}.ts` |
新增命名空间时必须在此表中登记。
### 5. 组件中使用
```vue
<script setup>
import { useI18n } from 'vue-i18n'
const { t, locale } = useI18n()
function switchLanguage(lang) {
locale.value = lang
localStorage.setItem('locale', lang)
}
</script>
<template>
<!-- 管理端 -->
<el-button @click="switchLanguage('en')">English</el-button>
<el-button @click="switchLanguage('zh-CN')">中文</el-button>
<!-- 用户端禁止 Element Plus -->
<button class="px-3 py-1 rounded border" @click="switchLanguage('en')">English</button>
<button class="px-3 py-1 rounded border" @click="switchLanguage('zh-CN')">中文</button>
<!-- 基础用法 -->
<p>{{ t('common.action.save') }}</p>
<!-- 参数化翻译 -->
<p>{{ t('order.total', { count: orderCount, amount: totalAmount }) }}</p>
<!-- 管理端 Element Plus 组件中使用 -->
<el-button type="primary">{{ t('common.action.save') }}</el-button>
<el-input :placeholder="t('order.form.searchPlaceholder')" />
<!-- 用户端 Tailwind 组件中使用 -->
<button class="bg-blue-600 text-white px-4 py-2 rounded-lg">{{ t('common.action.save') }}</button>
<input class="border rounded-lg px-3 py-2" :placeholder="t('order.form.searchPlaceholder')" />
</template>
```
### 6. Element Plus 国际化(仅管理端)
> 以下内容仅适用于 `Case-Database-Frontend-admin/`,用户端无需配置 Element Plus 国际化。
`main.ts` 不在 setup 上下文中,无法使用 `computed` 做响应式切换。正确方案:`main.ts` 静态初始化,`App.vue` 中通过 `computed` + `ElConfigProvider` 动态响应:
```typescript
// src/main.ts
import ElementPlus from 'element-plus'
import zhCn from 'element-plus/es/locale/lang/zh-cn'
import en from 'element-plus/es/locale/lang/en'
// 初始化时根据 locale 选择语言包
const elLocaleMap = { 'zh-CN': zhCn, en }
const initLocale = localStorage.getItem('locale') || 'zh-CN'
app.use(ElementPlus, { locale: elLocaleMap[initLocale] ?? zhCn })
```
```vue
<!-- 在根组件 App.vue 中动态响应语言切换 -->
<script setup>
import { useI18n } from 'vue-i18n'
import { computed } from 'vue'
import zhCn from 'element-plus/es/locale/lang/zh-cn'
import en from 'element-plus/es/locale/lang/en'
const { locale } = useI18n()
const elLocaleMap = { 'zh-CN': zhCn, en }
// 通过 ElConfigProvider 的 locale prop 动态切换
const elLocale = computed(() => elLocaleMap[locale.value] ?? zhCn)
</script>
<template>
<el-config-provider :locale="elLocale">
<router-view />
</el-config-provider>
</template>
```
### 7. 添加新语言
1.`src/locales/` 下创建新的 locale JS 文件(如 `fr.ts`
2.`src/locales/index.ts` 中注册新语言
3. 翻译所有已有 key
4. 管理端:同步 Element Plus 对应的 locale用户端跳过此步
## 验证
1. [ ] 所有 locale 文件的 key 结构一致(无遗漏)
2. [ ] 切换语言后页面正确翻译
3. [ ] 管理端Element Plus 组件语言同步切换(用户端不适用)
4. [ ] 日期/数字格式随 locale 变化
5. [ ] 键命名遵循 `{feature}.{context}.{action|status|label}` 公式
6. [ ] 使用扁平 dot notation不使用嵌套对象
7. [ ] 无键冲突(同一前缀不同时作为叶子节点和父节点前缀)
8. [ ] 参数化翻译使用 `{variableName}` 语法
9. [ ] 新命名空间已在标准命名空间表中登记