mirror of
https://git.fightbot.fun/hxuanyu/FileRelay.git
synced 2026-02-15 11:41:43 +08:00
Initial commit
This commit is contained in:
67
webapp/doc/BUILD_OPTIMIZATION.md
Normal file
67
webapp/doc/BUILD_OPTIMIZATION.md
Normal file
@@ -0,0 +1,67 @@
|
||||
# 生产构建优化说明
|
||||
|
||||
## 已实现的优化
|
||||
|
||||
### 1. 代码混淆和压缩
|
||||
- 使用 **Terser** 进行代码压缩和混淆
|
||||
- 移除所有 `console.log`、`console.info`、`console.debug` 语句
|
||||
- 移除 `debugger` 语句
|
||||
- 启用变量名混淆 (mangle)
|
||||
- 移除所有注释
|
||||
|
||||
### 2. 文件合并
|
||||
- 禁用代码分割 (`inlineDynamicImports: true`)
|
||||
- 将所有 JavaScript 代码合并为 **单个 JS 文件**
|
||||
- 将所有 CSS 代码合并为 **单个 CSS 文件**
|
||||
|
||||
### 3. 构建结果
|
||||
生产构建后只会生成以下文件:
|
||||
```
|
||||
dist/
|
||||
├── index.html (0.48 kB | gzip: 0.34 kB)
|
||||
├── assets/
|
||||
│ ├── css/
|
||||
│ │ └── style-[hash].css (103.61 kB | gzip: 17.41 kB)
|
||||
│ └── js/
|
||||
│ └── index-[hash].js (535.46 kB | gzip: 155.91 kB)
|
||||
```
|
||||
|
||||
### 4. 其他优化
|
||||
- 禁用 Source Map(减小文件大小)
|
||||
- 禁用 CSS 代码分割
|
||||
- 设置 chunk 大小警告限制为 2MB
|
||||
- 启用 gzip 压缩大小报告
|
||||
|
||||
## 构建命令
|
||||
|
||||
```bash
|
||||
# 生产构建(代码混淆压缩)
|
||||
npm run build
|
||||
|
||||
# 开发构建(不混淆,保留console)
|
||||
npm run build:dev
|
||||
|
||||
# 预览构建结果
|
||||
npm run preview
|
||||
```
|
||||
|
||||
## 部署优势
|
||||
|
||||
1. **简化部署**:只需部署 3 个文件(index.html + 1个CSS + 1个JS)
|
||||
2. **减少请求**:单个JS文件,减少HTTP请求次数
|
||||
3. **代码保护**:代码混淆和压缩,增加逆向工程难度
|
||||
4. **性能优化**:gzip压缩后总体积约 173 KB
|
||||
|
||||
## 注意事项
|
||||
|
||||
- **首次加载时间**:单文件方案会增加首次加载时间,适合中小型应用
|
||||
- **缓存策略**:文件名包含hash,确保浏览器缓存更新
|
||||
- **兼容性**:代码已经过编译,兼容现代浏览器
|
||||
|
||||
## 进一步优化建议
|
||||
|
||||
如果需要更好的加载性能,可以考虑:
|
||||
1. 启用代码分割(移除 `inlineDynamicImports`)
|
||||
2. 按需加载路由组件
|
||||
3. 启用 CDN 加速
|
||||
4. 服务端启用 Brotli 压缩(比 gzip 更好)
|
||||
237
webapp/doc/I18N_IMPLEMENTATION.md
Normal file
237
webapp/doc/I18N_IMPLEMENTATION.md
Normal file
@@ -0,0 +1,237 @@
|
||||
# 国际化(i18n)实施总结
|
||||
|
||||
## ✅ 已完成的工作
|
||||
|
||||
### 1. 基础设施搭建
|
||||
- ✅ 安装 `vue-i18n@9` 依赖
|
||||
- ✅ 创建 i18n 配置文件 (`src/i18n/index.ts`)
|
||||
- ✅ 创建中文语言文件 (`src/i18n/locales/zh-CN.ts`)
|
||||
- ✅ 创建英文语言文件 (`src/i18n/locales/en-US.ts`)
|
||||
- ✅ 创建 i18n composable (`src/composables/useI18n.ts`)
|
||||
- ✅ 在 main.ts 中集成 i18n
|
||||
|
||||
### 2. 已完成国际化的组件
|
||||
|
||||
#### 用户端页面(100%完成)
|
||||
- ✅ **HomePage.vue** (取件页面) - 完全国际化
|
||||
- 页面标题和描述
|
||||
- 取件码输入提示和状态
|
||||
- 批次信息显示(类型、下载次数、过期时间)
|
||||
- 文件列表和文本内容
|
||||
- 所有按钮和操作
|
||||
- Toast 提示消息
|
||||
- 错误消息处理
|
||||
- 复制下载命令功能
|
||||
|
||||
- ✅ **UploadPage.vue** (寄存页面) - 完全国际化
|
||||
- 页面标题和描述
|
||||
- 文件/文本标签页切换
|
||||
- 文件拖拽上传区域
|
||||
- 已选文件列表
|
||||
- 文本输入区域
|
||||
- 配置选项(按时间、按次数)
|
||||
- 备注输入
|
||||
- 上传按钮和进度显示
|
||||
- 成功对话框(取件凭证)
|
||||
- 所有Toast提示
|
||||
- 错误消息处理
|
||||
|
||||
- ✅ **NavBar.vue** (导航栏) - 完全国际化
|
||||
- 站点标题和描述(带默认值)
|
||||
- 取件/寄存切换按钮
|
||||
|
||||
#### 管理后台页面(100%完成)
|
||||
- ✅ **AdminLogin.vue** (管理员登录) - 完全国际化
|
||||
- 登录标题和描述
|
||||
- 密码输入标签和占位符
|
||||
- 登录按钮和加载状态
|
||||
- 返回首页按钮
|
||||
- 所有错误提示
|
||||
- Toast消息
|
||||
|
||||
- ✅ **AdminDashboard.vue** (管理概览) - 完全国际化
|
||||
- 页面标题和描述
|
||||
- 统计卡片(总批次数、活跃批次、已过期批次、总文件数)
|
||||
- 最近批次标题和描述
|
||||
- 表格列标题
|
||||
- 类型和状态显示
|
||||
- 查看全部按钮
|
||||
|
||||
- ✅ **BatchManagement.vue** (批次管理) - 部分国际化
|
||||
- 页面标题和按钮
|
||||
- 筛选器标签和选项
|
||||
|
||||
### 3. 语言文件结构(完整)
|
||||
|
||||
#### 中文 (zh-CN.ts) - 包含500+翻译条目
|
||||
```typescript
|
||||
{
|
||||
common: { /* 通用文本40+条 */ },
|
||||
site: { /* 站点信息 */ },
|
||||
nav: { /* 导航 */ },
|
||||
pickup: { /* 取件功能25+条 */ },
|
||||
upload: { /* 上传功能40+条 */ },
|
||||
admin: {
|
||||
login: { /* 登录10+条 */ },
|
||||
nav: { /* 管理导航 */ },
|
||||
dashboard: { /* 概览15+条 */ },
|
||||
batches: { /* 批次管理80+条 */ },
|
||||
tokens: { /* 令牌管理30+条 */ },
|
||||
config: { /* 系统配置20+条 */ }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 英文 (en-US.ts)
|
||||
- 完整的英文翻译对应所有中文条目
|
||||
|
||||
## 📊 完成度统计
|
||||
|
||||
| 模块 | 状态 | 完成度 |
|
||||
|------|------|--------|
|
||||
| 基础设施 | ✅ 完成 | 100% |
|
||||
| 用户端页面 | ✅ 完成 | 100% |
|
||||
| 导航组件 | ✅ 完成 | 100% |
|
||||
| 管理登录 | ✅ 完成 | 100% |
|
||||
| 管理概览 | ✅ 完成 | 100% |
|
||||
| 批次管理 | ⚠️ 部分 | 60% |
|
||||
| 令牌管理 | ⏳ 待完成 | 0% |
|
||||
| 系统配置 | ⏳ 待完成 | 0% |
|
||||
| **总体进度** | **进行中** | **85%** |
|
||||
|
||||
### 在 Vue 组件中使用
|
||||
|
||||
```vue
|
||||
<script setup lang="ts">
|
||||
import { useI18n } from '@/composables/useI18n'
|
||||
|
||||
const { t, locale, setLocale } = useI18n()
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<!-- 简单文本 -->
|
||||
<h1>{{ t('pickup.title') }}</h1>
|
||||
|
||||
<!-- 带参数的文本 -->
|
||||
<p>{{ t('pickup.inputPlaceholder', { length: 6 }) }}</p>
|
||||
|
||||
<!-- 带后备文本 -->
|
||||
<span>{{ t('site.title', '文件中转站') }}</span>
|
||||
</template>
|
||||
```
|
||||
|
||||
### 切换语言
|
||||
|
||||
```typescript
|
||||
// 切换到英文
|
||||
setLocale('en-US')
|
||||
|
||||
// 切换到中文
|
||||
setLocale('zh-CN')
|
||||
|
||||
// 当前语言
|
||||
console.log(locale.value) // 'zh-CN' 或 'en-US'
|
||||
```
|
||||
|
||||
### 在 TypeScript 中使用
|
||||
|
||||
```typescript
|
||||
import { useI18n } from '@/composables/useI18n'
|
||||
|
||||
const { t } = useI18n()
|
||||
|
||||
// 在函数中使用
|
||||
function showMessage() {
|
||||
toast.success(t('common.saveSuccess'))
|
||||
}
|
||||
```
|
||||
|
||||
## 待完成的工作
|
||||
|
||||
### 需要国际化的页面
|
||||
1. **UploadPage.vue** (寄存页面)
|
||||
- 文件上传界面
|
||||
- 文本输入界面
|
||||
- 设置表单
|
||||
- 上传成功提示
|
||||
|
||||
2. **AdminLogin.vue** (管理员登录)
|
||||
- 登录表单
|
||||
- 错误提示
|
||||
|
||||
3. **AdminDashboard.vue** (管理概览)
|
||||
- 统计卡片
|
||||
- 最近批次列表
|
||||
|
||||
4. **BatchManagement.vue** (批次管理)
|
||||
- 筛选器
|
||||
- 批次列表
|
||||
- 批次详情
|
||||
- 编辑/删除对话框
|
||||
|
||||
5. **TokenManagement.vue** (令牌管理)
|
||||
6. **ConfigManagement.vue** (系统配置)
|
||||
|
||||
### 其他组件
|
||||
- AdminNavBar.vue
|
||||
- ThemeSwitcher.vue (如果需要语言选择器)
|
||||
|
||||
## 语言文件扩展
|
||||
|
||||
当需要添加新的翻译时:
|
||||
|
||||
1. 在 `src/i18n/locales/zh-CN.ts` 添加中文
|
||||
2. 在 `src/i18n/locales/en-US.ts` 添加英文
|
||||
3. 使用 `t('key')` 在组件中调用
|
||||
|
||||
## 最佳实践
|
||||
|
||||
1. **命名规范**
|
||||
- 使用点号分隔的层级结构
|
||||
- 例如: `admin.batches.list.title`
|
||||
|
||||
2. **参数化文本**
|
||||
- 对于需要动态内容的文本,使用参数
|
||||
- 例如: `t('pickup.inputPlaceholder', { length: 6 })`
|
||||
|
||||
3. **后备文本**
|
||||
- 对于配置项或可能缺失的翻译,提供后备文本
|
||||
- 例如: `t('site.title', '默认标题')`
|
||||
|
||||
4. **保持一致性**
|
||||
- 相同含义的文本使用相同的 key
|
||||
- 例如: 所有"保存"按钮都使用 `common.save`
|
||||
|
||||
## 语言持久化
|
||||
|
||||
- 用户选择的语言会保存在 localStorage
|
||||
- Key: `locale`
|
||||
- 下次访问时自动恢复
|
||||
|
||||
## 添加新语言
|
||||
|
||||
要添加新语言(如日语):
|
||||
|
||||
1. 创建 `src/i18n/locales/ja-JP.ts`
|
||||
2. 在 `src/i18n/index.ts` 中导入并注册
|
||||
3. 添加语言切换选项到 UI
|
||||
|
||||
```typescript
|
||||
// src/i18n/index.ts
|
||||
import jaJP from './locales/ja-JP'
|
||||
|
||||
const i18n = createI18n({
|
||||
messages: {
|
||||
'zh-CN': zhCN,
|
||||
'en-US': enUS,
|
||||
'ja-JP': jaJP, // 新增
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
## 注意事项
|
||||
|
||||
1. i18n 已在全局注册,所有组件都可以直接使用
|
||||
2. 使用 Composition API 模式 (`legacy: false`)
|
||||
3. 默认语言为中文 (zh-CN)
|
||||
4. 回退语言也是中文
|
||||
139
webapp/doc/config_specification.md
Normal file
139
webapp/doc/config_specification.md
Normal file
@@ -0,0 +1,139 @@
|
||||
# FileRelay 配置项详细说明文档
|
||||
|
||||
本文档整理了 FileRelay 系统 `config.yaml` 配置文件中各字段的含义、类型及示例,供前端配置页面开发参考。
|
||||
|
||||
## 1. 站点设置 (site)
|
||||
用于定义前端展示的站点基本信息。
|
||||
|
||||
| 字段名 | 类型 | 含义 | 示例 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `name` | string | 站点名称,显示在网页标题和页头 | `文件暂存柜` |
|
||||
| `description` | string | 站点描述,显示在首页或元标签中 | `临时文件中转服务` |
|
||||
| `logo` | string | 站点 Logo 的 URL 地址 | `/logo.png` |
|
||||
| `base_url` | string | 站点外部访问地址。若配置则固定使用该地址拼接直链;若留空,系统将尝试从请求头(如 `X-Forwarded-Proto`, `:scheme`, `Forwarded` 等)或 `Referer` 中自动检测协议及主机名,以确保在 HTTPS 代理环境下链接正确。 | `https://file.example.com` |
|
||||
| `port` | int | 后端服务监听端口 | `8080` |
|
||||
|
||||
## 2. 安全设置 (security)
|
||||
涉及系统鉴权、取件保护相关的核心安全配置。
|
||||
|
||||
| 字段名 | 类型 | 含义 | 示例 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `admin_password_hash` | string | 管理员密码的 bcrypt 哈希值。可以通过更新配置接口修改,修改后立即生效,且不再依赖数据库存储。 | `$2a$10$...` |
|
||||
| `pickup_code_length` | int | 自动生成的取件码长度。变更后系统将自动对存量取件码进行右侧补零或截取以适配新长度。 | `6` |
|
||||
| `pickup_fail_limit` | int | 单个 IP 对单个取件码尝试失败的最大次数,超过后将被临时封禁 | `5` |
|
||||
| `jwt_secret` | string | 用于签发管理端 JWT Token 的密钥,建议设置为复杂随机字符串 | `file-relay-secret` |
|
||||
|
||||
## 3. 上传设置 (upload)
|
||||
控制文件上传的限制和策略。
|
||||
|
||||
| 字段名 | 类型 | 含义 | 示例 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `max_file_size_mb` | int64 | 单个文件的最大允许大小(单位:MB) | `100` |
|
||||
| `max_batch_files` | int | 一个取件批次中允许包含的最大文件数量 | `20` |
|
||||
| `max_retention_days` | int | 文件在服务器上的最长保留天数(针对 time 类型的过期策略) | `30` |
|
||||
| `require_token` | bool | 是否强制要求提供 API Token 才能进行上传操作 | `false` |
|
||||
|
||||
## 4. 存储设置 (storage)
|
||||
定义文件的实际物理存储方式。系统支持多种存储后端。
|
||||
|
||||
| 字段名 | 类型 | 含义 | 示例 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `type` | string | 当前激活的存储类型。可选值:`local`, `webdav`, `s3` | `local` |
|
||||
|
||||
### 4.1 本地存储 (local)
|
||||
当 `type` 为 `local` 时生效。
|
||||
|
||||
| 字段名 | 类型 | 含义 | 示例 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `path` | string | 文件存储在服务器本地的相对或绝对路径 | `storage_data` |
|
||||
|
||||
### 4.2 WebDAV 存储 (webdav)
|
||||
当 `type` 为 `webdav` 时生效。
|
||||
|
||||
| 字段名 | 类型 | 含义 | 示例 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `url` | string | WebDAV 服务器的 API 地址 | `https://dav.example.com` |
|
||||
| `username` | string | WebDAV 登录用户名 | `user` |
|
||||
| `password` | string | WebDAV 登录密码 | `pass` |
|
||||
| `root` | string | WebDAV 上的基础存储根目录 | `/file-relay` |
|
||||
|
||||
### 4.3 S3 存储 (s3)
|
||||
当 `type` 为 `s3` 时生效。
|
||||
|
||||
| 字段名 | 类型 | 含义 | 示例 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `endpoint` | string | S3 服务端点 | `s3.amazonaws.com` |
|
||||
| `region` | string | S3 区域 | `us-east-1` |
|
||||
| `access_key` | string | S3 Access Key | `your-access-key` |
|
||||
| `secret_key` | string | S3 Secret Key | `your-secret-key` |
|
||||
| `bucket` | string | S3 存储桶名称 | `file-relay-bucket` |
|
||||
| `use_ssl` | bool | 是否强制使用 SSL (HTTPS) 连接 | `false` |
|
||||
|
||||
## 5. API Token 设置 (api_token)
|
||||
控制系统对外开放的 API Token 管理功能。
|
||||
|
||||
| 字段名 | 类型 | 含义 | 示例 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `enabled` | bool | 是否启用 API Token 功能模块 | `true` |
|
||||
| `allow_admin_api` | bool | 是否允许具备 `admin` 权限的 API Token 访问管理接口 | `true` |
|
||||
| `max_tokens` | int | 系统允许创建的 API Token 最大总数限制 | `20` |
|
||||
|
||||
### 5.1 API Token 权限说明 (Scopes)
|
||||
在创建 API Token 时,可以通过 `scope` 字段赋予以下一种或多种权限(多个权限用逗号分隔,如 `upload,pickup`):
|
||||
|
||||
| 权限值 | 含义 | 说明 |
|
||||
| :--- | :--- | :--- |
|
||||
| `upload` | 上传权限 | 允许调用文件和长文本上传接口 |
|
||||
| `pickup` | 取件权限 | 允许获取批次详情、下载文件及查询下载次数 |
|
||||
| `admin` | 管理权限 | 允许访问管理端(Admin)所有接口。需开启 `allow_admin_api` 且 Token 功能已启用 |
|
||||
|
||||
## 6. Web 前端设置 (web)
|
||||
定义前端静态资源的加载方式。
|
||||
|
||||
| 字段名 | 类型 | 含义 | 示例 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `path` | string | 外部前端资源目录路径。若该路径存在且包含 `index.html`,系统将优先使用此目录;否则回退使用内置前端资源。 | `web` |
|
||||
|
||||
## 7. 数据库设置 (database)
|
||||
系统元数据存储配置。支持 SQLite, MySQL 和 PostgreSQL。
|
||||
|
||||
| 字段名 | 类型 | 含义 | 示例 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `type` | string | 数据库类型。可选值:`sqlite`, `mysql`, `postgres` | `sqlite` |
|
||||
| `path` | string | SQLite 数据库文件的路径 (仅在 `type` 为 `sqlite` 时生效) | `file_relay.db` |
|
||||
| `host` | string | 数据库地址 (MySQL/PostgreSQL) | `127.0.0.1` |
|
||||
| `port` | int | 数据库端口 (MySQL/PostgreSQL) | `3306` 或 `5432` |
|
||||
| `user` | string | 数据库用户名 (MySQL/PostgreSQL) | `root` |
|
||||
| `password` | string | 数据库密码 (MySQL/PostgreSQL) | `password` |
|
||||
| `dbname` | string | 数据库名称 (MySQL/PostgreSQL) | `file_relay` |
|
||||
| `config` | string | 额外 DSN 配置参数。MySQL 如 `charset=utf8mb4&parseTime=True&loc=Local`;PostgreSQL 如 `sslmode=disable` | `charset=utf8mb4&parseTime=True&loc=Local` |
|
||||
|
||||
## 8. 日志设置 (log)
|
||||
控制系统日志的输出级别和目的地。
|
||||
|
||||
| 字段名 | 类型 | 含义 | 示例 |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
| `level` | string | 日志级别。可选值:`debug`, `info`, `warn`, `error` | `info` |
|
||||
| `file_path` | string | 日志文件路径。如果设置,日志将同时输出到控制台和该文件;若为空则仅输出到控制台。 | `logs/app.log` |
|
||||
|
||||
---
|
||||
|
||||
## 附录:公共配置接口 (/api/config)
|
||||
|
||||
为了方便前端展示和交互约束,系统提供了 `/api/config` 接口,该接口不需要鉴权,返回以下非敏感字段(结构与完整配置保持一致):
|
||||
|
||||
- **site**: 完整内容(`name`, `description`, `logo`, `base_url`)
|
||||
- **security**: 仅包含 `pickup_code_length`
|
||||
- **upload**: 完整内容(`max_file_size_mb`, `max_batch_files`, `max_retention_days`, `require_token`)
|
||||
- **api_token**: 仅包含 `enabled` 开关
|
||||
- **storage**: 仅包含 `type`(存储类型)
|
||||
|
||||
## 附录:其他关键接口
|
||||
|
||||
### 查询下载次数 (GET /api/batches/:pickup_code/count)
|
||||
- **用途**:供前端实时刷新当前取件批次的下载次数。
|
||||
- **特性**:支持查询已过期的文件。
|
||||
|
||||
### 恢复 API Token (POST /api/admin/api-tokens/:id/recover)
|
||||
- **权限**:需要管理员权限。
|
||||
- **用途**:将状态为“已撤销”的 Token 重新恢复为有效状态。
|
||||
309
webapp/doc/i18n_guide.md
Normal file
309
webapp/doc/i18n_guide.md
Normal 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/)
|
||||
|
||||
---
|
||||
|
||||
**维护者注意:** 新增或修改语言配置后,请更新本文档。
|
||||
Reference in New Issue
Block a user