Initial commit

This commit is contained in:
2026-01-28 20:44:34 +08:00
commit 500e8b74a7
236 changed files with 29886 additions and 0 deletions

309
webapp/doc/i18n_guide.md Normal file
View File

@@ -0,0 +1,309 @@
# 国际化 (i18n) 使用指南
本文档说明如何在项目中新增语言支持和使用国际化功能。
## 目录结构
```
src/
├── i18n/
│ ├── index.ts # i18n 配置入口
│ ├── languages.ts # 语言配置文件(集中管理所有支持的语言)
│ └── locales/ # 翻译文件目录
│ ├── zh-CN.ts # 简体中文翻译
│ └── en-US.ts # 英文翻译
├── composables/
│ └── useI18n.ts # i18n Composable 封装
└── components/
└── ui/
└── LanguageSwitcher.vue # 语言切换组件
```
## 新增语言支持
### 步骤 1: 添加语言配置
编辑 `src/i18n/languages.ts`,在 `languages` 数组中添加新语言:
```typescript
export const languages: Language[] = [
{
code: 'zh-CN',
name: '简体中文',
flag: '🇨🇳',
englishName: 'Simplified Chinese',
},
{
code: 'en-US',
name: 'English',
flag: '🇺🇸',
englishName: 'English',
},
// 新增日语
{
code: 'ja-JP',
name: '日本語',
flag: '🇯🇵',
englishName: 'Japanese',
},
]
```
**字段说明:**
- `code`: 语言代码BCP 47 标准),如 `ja-JP``zh-TW``fr-FR`
- `name`: 用该语言自身的文字显示的名称(如日语用 "日本語"
- `flag`: 对应的旗帜 Emoji可选用于视觉识别
- `englishName`: 英文名称(可选,用于文档和调试)
### 步骤 2: 创建翻译文件
`src/i18n/locales/` 目录下创建新的翻译文件,如 `ja-JP.ts`
```typescript
export default {
// 通用文本
common: {
submit: '送信',
cancel: 'キャンセル',
confirm: '確認',
// ... 其他翻译
},
// 站点信息
site: {
title: 'ファイル中継ステーション',
description: '安全で便利なファイル一時保管サービス',
// ... 其他翻译
},
// 导航栏
nav: {
pickup: '受取',
upload: 'アップロード',
// ... 其他翻译
},
// 更多模块...
}
```
**💡 提示:** 可以参考 `zh-CN.ts``en-US.ts` 的结构,确保所有 key 保持一致。
### 步骤 3: 注册翻译文件
编辑 `src/i18n/index.ts`,导入并注册新的翻译文件:
```typescript
import zhCN from './locales/zh-CN'
import enUS from './locales/en-US'
import jaJP from './locales/ja-JP' // 导入新语言
const messages = {
'zh-CN': zhCN,
'en-US': enUS,
'ja-JP': jaJP, // 注册新语言
}
```
### 步骤 4: 测试
完成以上步骤后,语言切换器会自动显示新语言选项。切换语言后,检查所有页面的翻译是否正确显示。
## 使用国际化
### 在 Vue 组件中使用
```vue
<script setup lang="ts">
import { useI18n } from '@/composables/useI18n'
const { t, locale, setLocale } = useI18n()
</script>
<template>
<div>
<!-- 使用翻译 -->
<h1>{{ t('site.title') }}</h1>
<p>{{ t('site.description') }}</p>
<!-- 带默认值的翻译 -->
<button>{{ t('common.submit', '提交') }}</button>
<!-- 显示当前语言 -->
<p>Current locale: {{ locale }}</p>
<!-- 切换语言 -->
<button @click="setLocale('en-US')">Switch to English</button>
</div>
</template>
```
### API 说明
- `t(key: string, defaultValue?: string)`: 获取翻译文本
- `key`: 翻译的键名(如 `'common.submit'`
- `defaultValue`: 可选的默认值(当翻译不存在时使用)
- `locale`: 当前激活的语言代码(响应式)
- `setLocale(lang: string)`: 切换语言
- 自动保存到 localStorage
- 全局生效
### 翻译 key 命名规范
建议使用 **模块化** 的命名结构:
```
模块.子模块.具体项
```
示例:
- `common.submit` - 通用模块的"提交"按钮
- `nav.pickup` - 导航栏的"取件"链接
- `admin.dashboard.title` - 管理后台仪表板标题
- `upload.dragHint` - 上传页面的拖拽提示
## 语言切换器
项目包含一个独立的语言切换组件 `LanguageSwitcher.vue`,可以在任何页面中使用:
```vue
<template>
<LanguageSwitcher />
</template>
<script setup lang="ts">
import LanguageSwitcher from '@/components/ui/LanguageSwitcher.vue'
</script>
```
**已集成位置:**
- 用户前台导航栏 (`NavBar.vue`) - 右上角
- 管理后台导航栏 (`AdminNavBar.vue`) - 右上角
语言切换器会自动:
- 读取 `languages.ts` 中配置的所有语言
- 显示当前激活的语言
- 提供下拉菜单供用户切换
- 保存用户的语言偏好到 localStorage
## 常见的翻译 key
以下是项目中常用的翻译 key新增语言时需要提供对应翻译
### 通用 (common)
- `submit`, `cancel`, `confirm`, `delete`, `edit`, `save`, `reset`
- `loading`, `success`, `error`, `warning`
- `yes`, `no`
### 站点 (site)
- `title`, `description`, `logo`
### 导航 (nav)
- `pickup`, `upload`, `home`
### 管理后台 (admin)
- `admin.nav.*` - 导航栏各项
- `admin.dashboard.*` - 仪表板
- `admin.batches.*` - 批次管理
- `admin.tokens.*` - Token 管理
- `admin.config.*` - 系统配置
### 上传 (upload)
- `upload.title`, `upload.selectFile`, `upload.dragHint`
### 取件 (pickup)
- `pickup.title`, `pickup.enterCode`, `pickup.download`
## 最佳实践
1. **保持 key 一致性**
所有语言的翻译文件必须包含相同的 key 结构,否则会导致部分语言缺失翻译。
2. **使用有意义的 key 名称**
避免使用 `text1``label2` 这样的名称,应该使用描述性的名称如 `uploadButton``successMessage`
3. **提供默认值**
在调用 `t()` 时提供默认值,可以在翻译缺失时有更好的用户体验:
```vue
{{ t('some.key', '默认文本') }}
```
4. **模块化组织**
按照功能模块组织翻译文件,便于维护:
```typescript
export default {
common: { /* 通用翻译 */ },
nav: { /* 导航翻译 */ },
admin: {
dashboard: { /* 仪表板翻译 */ },
config: { /* 配置翻译 */ },
},
}
```
5. **注释复杂翻译**
对于有特殊含义或上下文的翻译,添加注释说明:
```typescript
export default {
upload: {
// 提示用户拖拽文件到上传区域
dragHint: '拖拽文件到此处,或点击选择文件',
},
}
```
6. **测试所有语言**
新增或修改翻译后,切换到每种语言测试,确保显示正确。
## 技术实现
项目使用 [vue-i18n v9](https://vue-i18n.intlify.dev/) 作为国际化框架,采用 **Composition API** 模式。
### 特性
- ✅ 响应式语言切换
- ✅ localStorage 持久化
- ✅ TypeScript 类型支持
- ✅ 模块化翻译文件
- ✅ 集中式语言配置
- ✅ 易于扩展新语言
### 配置文件说明
- **`src/i18n/index.ts`**
vue-i18n 配置入口,设置默认语言、回退语言、翻译消息等。
- **`src/i18n/languages.ts`**
语言配置文件,集中管理所有支持的语言信息(代码、名称、旗帜等)。新增语言首先在此配置。
- **`src/composables/useI18n.ts`**
封装了 vue-i18n 的 Composable提供简化的 API`t`、`locale`、`setLocale`)。
## 常见问题
**Q: 新增语言后,语言切换器没有显示新语言?**
A: 检查 `src/i18n/languages.ts` 是否正确添加了语言配置,确保 `code`、`name` 和 `flag` 字段都已填写。
**Q: 切换语言后,部分内容没有翻译?**
A: 检查新语言的翻译文件是否包含所有必需的 key。可以对比 `zh-CN.ts` 确保结构一致。
**Q: 如何修改默认语言?**
A: 编辑 `src/i18n/languages.ts`,修改 `DEFAULT_LANGUAGE` 常量的值。
**Q: 语言偏好保存在哪里?**
A: 保存在浏览器的 localStorage 中key 为 `'locale'`。
**Q: 如何在 JavaScript 代码中使用翻译?**
A: 在 `<script setup>` 中通过 `useI18n()` 获取 `t` 函数,然后调用 `t('key')`。
## 参考资源
- [Vue I18n 官方文档](https://vue-i18n.intlify.dev/)
- [BCP 47 语言标签](https://www.rfc-editor.org/rfc/bcp/bcp47.txt)
- [Unicode CLDR 语言数据](https://cldr.unicode.org/)
- [Emoji 国旗列表](https://emojipedia.org/flags/)
---
**维护者注意:** 新增或修改语言配置后,请更新本文档。