238 lines
5.8 KiB
Markdown
238 lines
5.8 KiB
Markdown
# 国际化
|
||
|
||
<!-- Copyright (c) 2021-2026 小蚂蚁云团队 版权所有 -->
|
||
|
||
:::tip 说明
|
||
当前项目仅支持中文界面,NaiveUI 使用中文语言包(`zhCN`),所有界面文本直接硬编码在组件中。如需扩展多语言支持,可基于 vue-i18n 实现。
|
||
:::
|
||
|
||
## 当前状态
|
||
|
||
项目当前为中文单语言版本:
|
||
|
||
- NaiveUI 通过 ConfigProvider 配置中文语言包:`<n-config-provider :locale="zhCN" :date-locale="dateZhCN">`
|
||
- 所有界面文本直接硬编码在组件中:`<n-button>添加岗位</n-button>`
|
||
- 后端返回的 `msg` 字段为中文:`"操作成功"`、`"岗位名称不能重复"`
|
||
|
||
```vue
|
||
<template>
|
||
<n-button type="primary">添加岗位</n-button>
|
||
<!-- 表格列通过 columns.ts 配置,使用 title/key -->
|
||
</template>
|
||
```
|
||
|
||
## NaiveUI 中文配置
|
||
|
||
项目通过 NaiveUI 的 ConfigProvider 配置中文语言包:
|
||
|
||
```typescript
|
||
// App.vue 或入口组件
|
||
import { zhCN, dateZhCN } from 'naive-ui';
|
||
```
|
||
|
||
```vue
|
||
<template>
|
||
<n-config-provider :locale="zhCN" :date-locale="dateZhCN">
|
||
<App />
|
||
</n-config-provider>
|
||
</template>
|
||
```
|
||
|
||
配置后,NaiveUI 组件的默认文本(如分页、日期选择器、表格空数据等)自动显示中文。
|
||
|
||
## 扩展方案
|
||
|
||
如需支持多语言,推荐使用 vue-i18n:
|
||
|
||
### 安装依赖
|
||
|
||
```bash
|
||
pnpm add vue-i18n
|
||
```
|
||
|
||
### 配置 i18n
|
||
|
||
```typescript
|
||
// src/i18n/index.ts
|
||
import { createI18n } from 'vue-i18n';
|
||
import zhCN from './locales/zh-CN.json';
|
||
import enUS from './locales/en-US.json';
|
||
|
||
const i18n = createI18n({
|
||
legacy: false,
|
||
locale: localStorage.getItem('lang') || 'zh-CN',
|
||
fallbackLocale: 'zh-CN',
|
||
messages: { 'zh-CN': zhCN, 'en-US': enUS },
|
||
});
|
||
|
||
export default i18n;
|
||
```
|
||
|
||
### 语言文件结构
|
||
|
||
```json
|
||
// src/i18n/locales/zh-CN.json
|
||
{
|
||
"common": {
|
||
"add": "新增",
|
||
"edit": "编辑",
|
||
"delete": "删除",
|
||
"search": "搜索",
|
||
"reset": "重置",
|
||
"confirm": "确定",
|
||
"cancel": "取消",
|
||
"success": "操作成功",
|
||
"failed": "操作失败",
|
||
"loading": "加载中..."
|
||
},
|
||
"position": {
|
||
"name": "岗位名称",
|
||
"status": "状态",
|
||
"sort": "排序",
|
||
"addTitle": "新增岗位",
|
||
"editTitle": "编辑岗位"
|
||
},
|
||
"user": {
|
||
"username": "用户名",
|
||
"realname": "真实姓名",
|
||
"email": "邮箱",
|
||
"phone": "手机号"
|
||
}
|
||
}
|
||
```
|
||
|
||
```json
|
||
// src/i18n/locales/en-US.json
|
||
{
|
||
"common": {
|
||
"add": "Add",
|
||
"edit": "Edit",
|
||
"delete": "Delete",
|
||
"search": "Search",
|
||
"reset": "Reset",
|
||
"confirm": "Confirm",
|
||
"cancel": "Cancel",
|
||
"success": "Success",
|
||
"failed": "Failed",
|
||
"loading": "Loading..."
|
||
},
|
||
"position": {
|
||
"name": "Position Name",
|
||
"status": "Status",
|
||
"sort": "Sort",
|
||
"addTitle": "Add Position",
|
||
"editTitle": "Edit Position"
|
||
}
|
||
}
|
||
```
|
||
|
||
### 组件中使用
|
||
|
||
```vue
|
||
<template>
|
||
<n-button type="primary">{{ $t('common.add') }}</n-button>
|
||
<!-- 表格列通过 columns.ts 配置,使用 title/key -->
|
||
</template>
|
||
|
||
<script setup>
|
||
import { useI18n } from 'vue-i18n';
|
||
const { t } = useI18n();
|
||
</script>
|
||
```
|
||
|
||
### NaiveUI 国际化联动
|
||
|
||
```typescript
|
||
// 动态切换 NaiveUI 语言
|
||
import { zhCN, dateZhCN, enUS, dateEnUS } from 'naive-ui';
|
||
|
||
const locale = computed(() => {
|
||
return i18n.global.locale.value === 'zh-CN' ? zhCN : enUS;
|
||
});
|
||
|
||
const dateLocale = computed(() => {
|
||
return i18n.global.locale.value === 'zh-CN' ? dateZhCN : dateEnUS;
|
||
});
|
||
```
|
||
|
||
```vue
|
||
<template>
|
||
<n-config-provider :locale="locale" :date-locale="dateLocale">
|
||
<App />
|
||
</n-config-provider>
|
||
</template>
|
||
```
|
||
|
||
### 语言切换
|
||
|
||
```typescript
|
||
// 切换语言
|
||
function changeLanguage(lang: string) {
|
||
i18n.global.locale.value = lang;
|
||
localStorage.setItem('lang', lang);
|
||
// 同步切换 NaiveUI 语言
|
||
}
|
||
```
|
||
|
||
## 后端国际化
|
||
|
||
后端返回的 `msg` 字段也需要国际化处理。有两种方案:
|
||
|
||
### 方案 1:前端映射(推荐)
|
||
|
||
前端根据错误码映射为多语言文本:
|
||
|
||
```typescript
|
||
// src/i18n/error-messages.ts
|
||
const errorMessages: Record<string, Record<string, string>> = {
|
||
'zh-CN': {
|
||
'操作成功': '操作成功',
|
||
'岗位名称不能重复': '岗位名称不能重复',
|
||
},
|
||
'en-US': {
|
||
'操作成功': 'Operation successful',
|
||
'岗位名称不能重复': 'Position name already exists',
|
||
}
|
||
};
|
||
```
|
||
|
||
### 方案 2:后端返回错误码
|
||
|
||
后端返回错误码,前端根据错误码翻译:
|
||
|
||
```python
|
||
# 后端返回错误码而非文本
|
||
R.failed(code="DUPLICATE_NAME", msg="岗位名称不能重复")
|
||
```
|
||
|
||
```typescript
|
||
// 前端根据错误码翻译
|
||
const errorMap = {
|
||
'DUPLICATE_NAME': t('position.error.duplicateName'),
|
||
};
|
||
```
|
||
|
||
:::warning 注意事项
|
||
1. NaiveUI 内置组件的文本(如"暂无数据"、"请选择")通过 `locale` 属性自动切换
|
||
2. 后端返回的 `msg` 字段需要额外处理
|
||
3. 日期格式、数字格式也需要考虑国际化
|
||
:::
|
||
|
||
## 改造工作量评估
|
||
|
||
```
|
||
1. 安装 vue-i18n:✅ 简单
|
||
2. 创建语言文件:⚠️ 需要提取所有硬编码文本
|
||
3. 组件改造:⚠️ 工作量较大,每个组件都需要替换文本
|
||
4. 后端改造:❌ 需要统一错误码体系
|
||
5. 测试验证:⚠️ 每种语言都需要完整测试
|
||
```
|
||
|
||
:::tip 温馨提示
|
||
国际化改造工作量较大,建议在项目初期规划。如仅需中文,当前硬编码方式即可满足需求。改造时需要同时处理前端文本和后端返回的 `msg` 字段。
|
||
:::
|
||
|
||
## 总结
|
||
|
||
当前项目为中文单语言版本,NaiveUI 使用中文语言包。如需扩展多语言支持,可基于 vue-i18n 实现前端国际化,配合 NaiveUI 内置语言包和后端消息 code 实现全链路多语言。改造需考虑前端文本、NaiveUI 组件、后端消息三个维度的国际化。
|