feat: 改进下单错误处理和市场价格接口

- 修复市场价格接口:移除side参数,使用outcomeIndex判断方向
- 添加规范:禁止使用YES/NO字符串判断side,必须使用outcomeIndex
- 改进所有下单错误处理:所有错误都打印详细日志并存入数据库
  - AccountService.sellPosition: 添加完整错误日志
  - CopyOrderTrackingService.createOrderWithRetry: 所有失败都记录详细日志
  - recordFailedTrade: 改进错误信息存储,包含堆栈信息
  - PolymarketClobService.createSignedOrder: 添加完整错误日志
- 前端:更新市场价格接口调用,使用outcomeIndex替代side参数
- 清理:删除过时的i18n文档
This commit is contained in:
WrBug
2025-12-05 00:23:44 +08:00
parent 1a9407c544
commit 41596887c9
18 changed files with 215 additions and 1841 deletions
-266
View File
@@ -1,266 +0,0 @@
# Controller 多语言更新指南
## 已完成的 Controller ✅
1. **AccountController** - 完全更新
2. **AuthController** - 完全更新
3. **LeaderController** - 完全更新
4. **UserController** - 完全更新
## 待更新的 Controller
以下 Controller 需要按照相同模式更新:
1. **CopyTradingController** - 已添加 MessageSource,需要更新所有 ApiResponse.error() 调用
2. **CopyTradingTemplateController** - 需要添加 MessageSource 并更新调用
3. **MarketController** - 需要添加 MessageSource 并更新调用
4. **CopyTradingStatisticsController** - 需要添加 MessageSource 并更新调用
5. **ProxyConfigController** - 需要添加 MessageSource 并更新调用
6. **HealthController** - 需要检查是否需要更新
## 更新步骤
### 步骤 1:添加导入和依赖注入
```kotlin
// 1. 添加导入
import com.wrbug.polymarketbot.util.error
import org.springframework.context.MessageSource
// 2. 在构造函数中注入 MessageSource
class YourController(
private val yourService: YourService,
private val messageSource: MessageSource // 添加这一行
) {
// ...
}
```
### 步骤 2:更新所有 ApiResponse.error() 调用
**模式 1:只有 ErrorCode**
```kotlin
// 旧代码
ApiResponse.error(ErrorCode.PARAM_ERROR)
// 新代码
ApiResponse.error(ErrorCode.PARAM_ERROR, messageSource = messageSource)
```
**模式 2ErrorCode + 自定义消息**
```kotlin
// 旧代码
ApiResponse.error(ErrorCode.PARAM_ERROR, e.message)
ApiResponse.error(ErrorCode.PARAM_ERROR, "自定义消息")
// 新代码
ApiResponse.error(ErrorCode.PARAM_ERROR, e.message, messageSource)
ApiResponse.error(ErrorCode.PARAM_ERROR, "自定义消息", messageSource)
```
**模式 3:使用 code + msg(已废弃的方法)**
```kotlin
// 旧代码
ApiResponse.error(ErrorCode.PARAM_ERROR.code, "消息")
ApiResponse.paramError("消息")
ApiResponse.serverError("消息")
// 新代码
ApiResponse.error(ErrorCode.PARAM_ERROR, "消息", messageSource)
ApiResponse.error(ErrorCode.SERVER_ERROR, "消息", messageSource)
```
### 步骤 3:批量查找和替换
使用 IDE 的查找替换功能:
1. **查找模式**`ApiResponse.error(ErrorCode.`
2. **替换模式**:在方法调用末尾添加 `, messageSource = messageSource)`
**注意**:需要逐个检查,因为有些调用已经有其他参数。
### 示例:CopyTradingController 更新
```kotlin
// 更新前
if (request.accountId <= 0) {
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ACCOUNT_ID_INVALID))
}
// 更新后
if (request.accountId <= 0) {
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ACCOUNT_ID_INVALID, messageSource = messageSource))
}
// 更新前
ApiResponse.error(ErrorCode.PARAM_ERROR, e.message)
// 更新后
ApiResponse.error(ErrorCode.PARAM_ERROR, e.message, messageSource)
```
## 验证
更新完成后,检查:
1. ✅ 所有 Controller 都注入了 MessageSource
2. ✅ 所有 ApiResponse.error() 调用都传入了 messageSource 参数
3. ✅ 编译无错误
4. ✅ 测试 API 响应消息是否正确显示对应语言
## 快速更新脚本(参考)
可以使用以下模式批量更新:
```bash
# 在 IDE 中使用正则表达式查找替换
# 查找:ApiResponse\.error\(ErrorCode\.(\w+)\)\)
# 替换:ApiResponse.error(ErrorCode.$1, messageSource = messageSource)
# 查找:ApiResponse\.error\(ErrorCode\.(\w+),\s*([^,)]+)\)\)
# 替换:ApiResponse.error(ErrorCode.$1, $2, messageSource)
```
## 注意事项
1. **自定义消息**:如果错误消息是硬编码的中文,建议:
- 优先使用 ErrorCode 的 messageKey(已在语言包中翻译)
- 如果必须使用自定义消息,确保消息本身也需要国际化(通过 MessageUtils.getMessage()
2. **向后兼容**:如果前端没有发送语言 Header,后端会使用默认语言(英文)
3. **测试**:更新后测试不同语言下的错误消息显示
## 已完成的 Controller ✅
1. **AccountController** - 完全更新
2. **AuthController** - 完全更新
3. **LeaderController** - 完全更新
4. **UserController** - 完全更新
## 待更新的 Controller
以下 Controller 需要按照相同模式更新:
1. **CopyTradingController** - 已添加 MessageSource,需要更新所有 ApiResponse.error() 调用
2. **CopyTradingTemplateController** - 需要添加 MessageSource 并更新调用
3. **MarketController** - 需要添加 MessageSource 并更新调用
4. **CopyTradingStatisticsController** - 需要添加 MessageSource 并更新调用
5. **ProxyConfigController** - 需要添加 MessageSource 并更新调用
6. **HealthController** - 需要检查是否需要更新
## 更新步骤
### 步骤 1:添加导入和依赖注入
```kotlin
// 1. 添加导入
import com.wrbug.polymarketbot.util.error
import org.springframework.context.MessageSource
// 2. 在构造函数中注入 MessageSource
class YourController(
private val yourService: YourService,
private val messageSource: MessageSource // 添加这一行
) {
// ...
}
```
### 步骤 2:更新所有 ApiResponse.error() 调用
**模式 1:只有 ErrorCode**
```kotlin
// 旧代码
ApiResponse.error(ErrorCode.PARAM_ERROR)
// 新代码
ApiResponse.error(ErrorCode.PARAM_ERROR, messageSource = messageSource)
```
**模式 2ErrorCode + 自定义消息**
```kotlin
// 旧代码
ApiResponse.error(ErrorCode.PARAM_ERROR, e.message)
ApiResponse.error(ErrorCode.PARAM_ERROR, "自定义消息")
// 新代码
ApiResponse.error(ErrorCode.PARAM_ERROR, e.message, messageSource)
ApiResponse.error(ErrorCode.PARAM_ERROR, "自定义消息", messageSource)
```
**模式 3:使用 code + msg(已废弃的方法)**
```kotlin
// 旧代码
ApiResponse.error(ErrorCode.PARAM_ERROR.code, "消息")
ApiResponse.paramError("消息")
ApiResponse.serverError("消息")
// 新代码
ApiResponse.error(ErrorCode.PARAM_ERROR, "消息", messageSource)
ApiResponse.error(ErrorCode.SERVER_ERROR, "消息", messageSource)
```
### 步骤 3:批量查找和替换
使用 IDE 的查找替换功能:
1. **查找模式**`ApiResponse.error(ErrorCode.`
2. **替换模式**:在方法调用末尾添加 `, messageSource = messageSource)`
**注意**:需要逐个检查,因为有些调用已经有其他参数。
### 示例:CopyTradingController 更新
```kotlin
// 更新前
if (request.accountId <= 0) {
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ACCOUNT_ID_INVALID))
}
// 更新后
if (request.accountId <= 0) {
return ResponseEntity.ok(ApiResponse.error(ErrorCode.PARAM_ACCOUNT_ID_INVALID, messageSource = messageSource))
}
// 更新前
ApiResponse.error(ErrorCode.PARAM_ERROR, e.message)
// 更新后
ApiResponse.error(ErrorCode.PARAM_ERROR, e.message, messageSource)
```
## 验证
更新完成后,检查:
1. ✅ 所有 Controller 都注入了 MessageSource
2. ✅ 所有 ApiResponse.error() 调用都传入了 messageSource 参数
3. ✅ 编译无错误
4. ✅ 测试 API 响应消息是否正确显示对应语言
## 快速更新脚本(参考)
可以使用以下模式批量更新:
```bash
# 在 IDE 中使用正则表达式查找替换
# 查找:ApiResponse\.error\(ErrorCode\.(\w+)\)\)
# 替换:ApiResponse.error(ErrorCode.$1, messageSource = messageSource)
# 查找:ApiResponse\.error\(ErrorCode\.(\w+),\s*([^,)]+)\)\)
# 替换:ApiResponse.error(ErrorCode.$1, $2, messageSource)
```
## 注意事项
1. **自定义消息**:如果错误消息是硬编码的中文,建议:
- 优先使用 ErrorCode 的 messageKey(已在语言包中翻译)
- 如果必须使用自定义消息,确保消息本身也需要国际化(通过 MessageUtils.getMessage()
2. **向后兼容**:如果前端没有发送语言 Header,后端会使用默认语言(英文)
3. **测试**:更新后测试不同语言下的错误消息显示
View File
-246
View File
@@ -1,246 +0,0 @@
# 多语言支持实现状态
## ✅ 已完成的工作
### 后端部分(100% 完成)
#### 1. 核心框架 ✅
- ✅ 创建语言资源文件(messages_zh_CN.properties, messages_zh_TW.properties, messages_en.properties
- ✅ 配置 MessageSource BeanMessageSourceConfig.kt
- ✅ 创建 LocaleInterceptor 拦截器
- ✅ 修改 ErrorCode 枚举,添加 messageKey 字段(100+ 条错误消息)
- ✅ 修改 ApiResponse.error() 方法,支持多语言
- ✅ 创建 MessageUtils 工具类
- ✅ 更新 WebMvcConfig,注册 LocaleInterceptor
#### 2. Controller 更新 ✅(全部完成)
- ✅ AccountController - 完全更新
- ✅ AuthController - 完全更新
- ✅ LeaderController - 完全更新
- ✅ UserController - 完全更新
- ✅ CopyTradingController - 完全更新
- ✅ CopyTradingTemplateController - 完全更新
- ✅ MarketController - 完全更新
- ✅ CopyTradingStatisticsController - 完全更新(包含 CopyOrderTrackingController
- ✅ ProxyConfigController - 完全更新
- ✅ HealthController - 无需更新(无错误响应)
#### 3. 编译状态 ✅
- ✅ 后端编译通过,无错误
- ✅ 所有 ApiResponse.error() 调用都已传入 messageSource 参数
### 前端部分(部分完成)
#### 1. 核心框架 ✅
- ✅ 安装 i18next 和 react-i18next 依赖
- ✅ 配置 i18n(语言检测、资源加载)
- ✅ 创建语言包文件结构(zh-CN, zh-TW, en
- ✅ 在 api.ts 中添加语言 HeaderX-Language
- ✅ 在 main.tsx 中初始化 i18n
#### 2. 页面更新 ✅(2个页面已完成)
- ✅ AccountDetail.tsx - 完全使用 i18n
- ✅ App.tsx - 订单推送通知已使用 i18nAnt Design locale 已配置
- ✅ Login.tsx - 完全使用 i18n
#### 3. 语言包扩展 ✅
- ✅ 添加了登录相关翻译(login.*)
- ✅ 添加了订单相关翻译(order.*)
- ✅ 添加了账户相关翻译(account.*)
- ✅ 添加了通用翻译(common.*)
#### 4. 编译状态 ✅
- ✅ 前端编译通过,无错误
- ⚠️ 有 5 个 TypeScript linter 警告(文件存在,可能是缓存问题)
## ⏳ 待完成的工作
### 前端部分(21个页面待更新)
需要更新以下页面组件,使用 `useTranslation` Hook 替换硬编码文本:
1. AccountList.tsx
2. AccountImport.tsx
3. AccountEdit.tsx
4. LeaderList.tsx
5. LeaderAdd.tsx
6. LeaderEdit.tsx
7. TemplateList.tsx
8. TemplateAdd.tsx
9. TemplateEdit.tsx
10. CopyTradingList.tsx
11. CopyTradingAdd.tsx
12. CopyTradingStatistics.tsx
13. CopyTradingBuyOrders.tsx
14. CopyTradingSellOrders.tsx
15. CopyTradingMatchedOrders.tsx
16. PositionList.tsx
17. OrderList.tsx
18. Statistics.tsx
19. UserList.tsx
20. ResetPassword.tsx
21. SystemSettings.tsx
22. ConfigPage.tsx
### 语言包扩展
根据页面内容,可能需要添加更多翻译键:
- Leader 相关翻译
- Template 相关翻译
- CopyTrading 相关翻译
- Position 相关翻译
- Statistics 相关翻译
- 等等
## 测试建议
### 后端测试
1. ✅ 编译通过
2. ⏳ 测试不同语言 Header 下的错误消息显示
3. ⏳ 测试默认语言(无 Header 时)
### 前端测试
1. ✅ 编译通过
2. ⏳ 测试系统语言自动检测
3. ⏳ 测试语言切换(如果添加了切换功能)
4. ⏳ 测试不同语言下的页面显示
5. ⏳ 测试 API 请求是否正确传递语言 Header
## 使用说明
### 后端
所有 Controller 已更新,错误消息会自动根据 HTTP Header `X-Language``Accept-Language` 返回对应语言。
### 前端
已更新的页面会自动根据系统语言显示对应文本。其他页面需要逐步更新。
## 下一步
1. 逐步更新剩余的前端页面组件
2. 根据页面内容扩展语言包
3. 全面测试多语言功能
4. (可选)添加语言切换组件
## ✅ 已完成的工作
### 后端部分(100% 完成)
#### 1. 核心框架 ✅
- ✅ 创建语言资源文件(messages_zh_CN.properties, messages_zh_TW.properties, messages_en.properties
- ✅ 配置 MessageSource BeanMessageSourceConfig.kt
- ✅ 创建 LocaleInterceptor 拦截器
- ✅ 修改 ErrorCode 枚举,添加 messageKey 字段(100+ 条错误消息)
- ✅ 修改 ApiResponse.error() 方法,支持多语言
- ✅ 创建 MessageUtils 工具类
- ✅ 更新 WebMvcConfig,注册 LocaleInterceptor
#### 2. Controller 更新 ✅(全部完成)
- ✅ AccountController - 完全更新
- ✅ AuthController - 完全更新
- ✅ LeaderController - 完全更新
- ✅ UserController - 完全更新
- ✅ CopyTradingController - 完全更新
- ✅ CopyTradingTemplateController - 完全更新
- ✅ MarketController - 完全更新
- ✅ CopyTradingStatisticsController - 完全更新(包含 CopyOrderTrackingController
- ✅ ProxyConfigController - 完全更新
- ✅ HealthController - 无需更新(无错误响应)
#### 3. 编译状态 ✅
- ✅ 后端编译通过,无错误
- ✅ 所有 ApiResponse.error() 调用都已传入 messageSource 参数
### 前端部分(部分完成)
#### 1. 核心框架 ✅
- ✅ 安装 i18next 和 react-i18next 依赖
- ✅ 配置 i18n(语言检测、资源加载)
- ✅ 创建语言包文件结构(zh-CN, zh-TW, en
- ✅ 在 api.ts 中添加语言 HeaderX-Language
- ✅ 在 main.tsx 中初始化 i18n
#### 2. 页面更新 ✅(2个页面已完成)
- ✅ AccountDetail.tsx - 完全使用 i18n
- ✅ App.tsx - 订单推送通知已使用 i18nAnt Design locale 已配置
- ✅ Login.tsx - 完全使用 i18n
#### 3. 语言包扩展 ✅
- ✅ 添加了登录相关翻译(login.*)
- ✅ 添加了订单相关翻译(order.*)
- ✅ 添加了账户相关翻译(account.*)
- ✅ 添加了通用翻译(common.*)
#### 4. 编译状态 ✅
- ✅ 前端编译通过,无错误
- ⚠️ 有 5 个 TypeScript linter 警告(文件存在,可能是缓存问题)
## ⏳ 待完成的工作
### 前端部分(21个页面待更新)
需要更新以下页面组件,使用 `useTranslation` Hook 替换硬编码文本:
1. AccountList.tsx
2. AccountImport.tsx
3. AccountEdit.tsx
4. LeaderList.tsx
5. LeaderAdd.tsx
6. LeaderEdit.tsx
7. TemplateList.tsx
8. TemplateAdd.tsx
9. TemplateEdit.tsx
10. CopyTradingList.tsx
11. CopyTradingAdd.tsx
12. CopyTradingStatistics.tsx
13. CopyTradingBuyOrders.tsx
14. CopyTradingSellOrders.tsx
15. CopyTradingMatchedOrders.tsx
16. PositionList.tsx
17. OrderList.tsx
18. Statistics.tsx
19. UserList.tsx
20. ResetPassword.tsx
21. SystemSettings.tsx
22. ConfigPage.tsx
### 语言包扩展
根据页面内容,可能需要添加更多翻译键:
- Leader 相关翻译
- Template 相关翻译
- CopyTrading 相关翻译
- Position 相关翻译
- Statistics 相关翻译
- 等等
## 测试建议
### 后端测试
1. ✅ 编译通过
2. ⏳ 测试不同语言 Header 下的错误消息显示
3. ⏳ 测试默认语言(无 Header 时)
### 前端测试
1. ✅ 编译通过
2. ⏳ 测试系统语言自动检测
3. ⏳ 测试语言切换(如果添加了切换功能)
4. ⏳ 测试不同语言下的页面显示
5. ⏳ 测试 API 请求是否正确传递语言 Header
## 使用说明
### 后端
所有 Controller 已更新,错误消息会自动根据 HTTP Header `X-Language``Accept-Language` 返回对应语言。
### 前端
已更新的页面会自动根据系统语言显示对应文本。其他页面需要逐步更新。
## 下一步
1. 逐步更新剩余的前端页面组件
2. 根据页面内容扩展语言包
3. 全面测试多语言功能
4. (可选)添加语言切换组件
-444
View File
@@ -1,444 +0,0 @@
# 多语言支持实现总结
## 已完成的工作
### 后端部分 ✅
1. **语言资源文件** (`backend/src/main/resources/i18n/`)
- `messages_zh_CN.properties` - 简体中文
- `messages_zh_TW.properties` - 繁体中文
- `messages_en.properties` - 英文
- 已翻译所有 ErrorCode 错误消息(100+ 条)
2. **配置类**
- `MessageSourceConfig.kt` - 配置 MessageSource 和 LocaleResolver
- `LocaleInterceptor.kt` - 从 HTTP Header 读取语言设置
3. **核心修改**
- `ErrorCode.kt` - 添加 `messageKey` 字段,每个错误码都有对应的消息键
- `ApiResponse.kt` - 支持多语言错误消息
- `ApiResponseExt.kt` - 提供便捷的扩展函数
- `MessageUtils.kt` - 消息工具类
- `WebMvcConfig.kt` - 注册 LocaleInterceptor
4. **示例更新**
- `AccountController.kt` - 已更新部分方法作为示例
### 前端部分 ✅
1. **依赖安装**
- `i18next``react-i18next` 已安装
2. **i18n 配置** (`frontend/src/i18n/config.ts`)
- 自动检测系统语言
- 支持语言切换
- 语言持久化到 localStorage
3. **语言包** (`frontend/src/locales/`)
- `zh-CN/common.json` - 简体中文
- `zh-TW/common.json` - 繁体中文
- `en/common.json` - 英文
- 已包含账户管理相关的基础翻译
4. **API 集成**
- `api.ts` - 自动在请求头添加 `X-Language` Header
5. **示例页面**
- `AccountDetail.tsx` - 已完全使用 i18n
## 待完成的工作
### 后端部分
需要更新所有 Controller,使用 `MessageUtils` 或扩展函数来获取国际化消息:
```kotlin
// 方式1:使用扩展函数(推荐)
@RestController
class ExampleController(
private val messageSource: MessageSource
) {
@PostMapping("/example")
fun example(): ResponseEntity<ApiResponse<Unit>> {
// 使用扩展函数,自动国际化
return ResponseEntity.ok(
ApiResponse.error(ErrorCode.PARAM_ERROR, messageSource = messageSource)
)
}
}
// 方式2:使用 MessageUtils
@RestController
class ExampleController(
private val messageUtils: MessageUtils
) {
@PostMapping("/example")
fun example(): ResponseEntity<ApiResponse<Unit>> {
val msg = messageUtils.getMessage(ErrorCode.PARAM_ERROR)
return ResponseEntity.ok(
ApiResponse.error(ErrorCode.PARAM_ERROR.code, msg)
)
}
}
```
需要更新的 Controller
- `AuthController.kt`
- `LeaderController.kt`
- `CopyTradingController.kt`
- `CopyTradingTemplateController.kt`
- `CopyTradingStatisticsController.kt`
- `MarketController.kt`
- `UserController.kt`
- `ProxyConfigController.kt`
- `AccountController.kt` (部分方法已更新,需要完成剩余部分)
### 前端部分
需要更新所有页面组件,使用 `useTranslation` Hook
```typescript
import { useTranslation } from 'react-i18next'
const MyComponent: React.FC = () => {
const { t } = useTranslation()
return (
<div>
<Button>{t('common.save')}</Button>
<div>{t('account.accountName')}</div>
</div>
)
}
```
需要更新的页面:
- `AccountList.tsx`
- `AccountImport.tsx`
- `AccountEdit.tsx`
- `LeaderList.tsx`
- `LeaderAdd.tsx`
- `LeaderEdit.tsx`
- `TemplateList.tsx`
- `TemplateAdd.tsx`
- `TemplateEdit.tsx`
- `CopyTradingList.tsx`
- `CopyTradingAdd.tsx`
- `Login.tsx`
- `UserList.tsx`
- 以及其他所有页面
## 使用说明
### 后端使用
1. **在 Controller 中注入 MessageSource**
```kotlin
@RestController
class MyController(
private val messageSource: MessageSource
) {
// ...
}
```
2. **使用扩展函数创建错误响应**
```kotlin
ApiResponse.error(ErrorCode.PARAM_ERROR, messageSource = messageSource)
```
3. **自定义消息(如果需要)**
```kotlin
ApiResponse.error(ErrorCode.PARAM_ERROR, "自定义消息", messageSource)
```
### 前端使用
1. **在组件中使用 useTranslation**
```typescript
import { useTranslation } from 'react-i18next'
const { t } = useTranslation()
```
2. **翻译文本**
```typescript
t('common.save') // 返回当前语言的"保存"
t('account.accountName') // 返回当前语言的"账户名称"
```
3. **切换语言**(可选):
```typescript
import { changeLanguage } from '../i18n/config'
changeLanguage('zh-CN') // 切换到简体中文
changeLanguage('zh-TW') // 切换到繁体中文
changeLanguage('en') // 切换到英文
```
## 语言检测规则
### 前端
1. 优先使用 localStorage 中保存的语言设置
2. 如果没有,检测系统语言:
- `zh-CN`, `zh` → 简体中文
- `zh-TW`, `zh-HK`, `zh-MO` → 繁体中文
- 其他 → 英文(默认)
### 后端
1. 从 HTTP Header 读取:
- `X-Language` (优先)
- `Accept-Language` (备选)
2. 语言映射规则同前端
3. 默认语言:英文
## 测试建议
1. **测试语言检测**
- 修改浏览器语言设置,刷新页面,检查是否自动切换
- 测试不同语言下的 API 响应消息
2. **测试语言切换**
- 在前端添加语言切换组件(可选)
- 测试切换后 API 请求是否正确传递语言 Header
3. **测试错误消息**
- 触发各种错误,检查错误消息是否正确显示对应语言
## 注意事项
1. **向后兼容**:如果前端没有发送语言 Header,后端默认使用英文
2. **消息键命名**:所有消息键使用 `error.` 前缀,便于管理
3. **翻译质量**:建议由专业翻译人员审核翻译内容
4. **性能**:语言包已配置缓存,不会影响性能
## 下一步
1. 完成所有 Controller 的更新
2. 完成所有前端页面的翻译
3. 添加语言切换组件(可选)
4. 全面测试多语言功能
5. 更新 API 文档,说明语言 Header 的使用
## 已完成的工作
### 后端部分 ✅
1. **语言资源文件** (`backend/src/main/resources/i18n/`)
- `messages_zh_CN.properties` - 简体中文
- `messages_zh_TW.properties` - 繁体中文
- `messages_en.properties` - 英文
- 已翻译所有 ErrorCode 错误消息(100+ 条)
2. **配置类**
- `MessageSourceConfig.kt` - 配置 MessageSource 和 LocaleResolver
- `LocaleInterceptor.kt` - 从 HTTP Header 读取语言设置
3. **核心修改**
- `ErrorCode.kt` - 添加 `messageKey` 字段,每个错误码都有对应的消息键
- `ApiResponse.kt` - 支持多语言错误消息
- `ApiResponseExt.kt` - 提供便捷的扩展函数
- `MessageUtils.kt` - 消息工具类
- `WebMvcConfig.kt` - 注册 LocaleInterceptor
4. **示例更新**
- `AccountController.kt` - 已更新部分方法作为示例
### 前端部分 ✅
1. **依赖安装**
- `i18next``react-i18next` 已安装
2. **i18n 配置** (`frontend/src/i18n/config.ts`)
- 自动检测系统语言
- 支持语言切换
- 语言持久化到 localStorage
3. **语言包** (`frontend/src/locales/`)
- `zh-CN/common.json` - 简体中文
- `zh-TW/common.json` - 繁体中文
- `en/common.json` - 英文
- 已包含账户管理相关的基础翻译
4. **API 集成**
- `api.ts` - 自动在请求头添加 `X-Language` Header
5. **示例页面**
- `AccountDetail.tsx` - 已完全使用 i18n
## 待完成的工作
### 后端部分
需要更新所有 Controller,使用 `MessageUtils` 或扩展函数来获取国际化消息:
```kotlin
// 方式1:使用扩展函数(推荐)
@RestController
class ExampleController(
private val messageSource: MessageSource
) {
@PostMapping("/example")
fun example(): ResponseEntity<ApiResponse<Unit>> {
// 使用扩展函数,自动国际化
return ResponseEntity.ok(
ApiResponse.error(ErrorCode.PARAM_ERROR, messageSource = messageSource)
)
}
}
// 方式2:使用 MessageUtils
@RestController
class ExampleController(
private val messageUtils: MessageUtils
) {
@PostMapping("/example")
fun example(): ResponseEntity<ApiResponse<Unit>> {
val msg = messageUtils.getMessage(ErrorCode.PARAM_ERROR)
return ResponseEntity.ok(
ApiResponse.error(ErrorCode.PARAM_ERROR.code, msg)
)
}
}
```
需要更新的 Controller
- `AuthController.kt`
- `LeaderController.kt`
- `CopyTradingController.kt`
- `CopyTradingTemplateController.kt`
- `CopyTradingStatisticsController.kt`
- `MarketController.kt`
- `UserController.kt`
- `ProxyConfigController.kt`
- `AccountController.kt` (部分方法已更新,需要完成剩余部分)
### 前端部分
需要更新所有页面组件,使用 `useTranslation` Hook
```typescript
import { useTranslation } from 'react-i18next'
const MyComponent: React.FC = () => {
const { t } = useTranslation()
return (
<div>
<Button>{t('common.save')}</Button>
<div>{t('account.accountName')}</div>
</div>
)
}
```
需要更新的页面:
- `AccountList.tsx`
- `AccountImport.tsx`
- `AccountEdit.tsx`
- `LeaderList.tsx`
- `LeaderAdd.tsx`
- `LeaderEdit.tsx`
- `TemplateList.tsx`
- `TemplateAdd.tsx`
- `TemplateEdit.tsx`
- `CopyTradingList.tsx`
- `CopyTradingAdd.tsx`
- `Login.tsx`
- `UserList.tsx`
- 以及其他所有页面
## 使用说明
### 后端使用
1. **在 Controller 中注入 MessageSource**
```kotlin
@RestController
class MyController(
private val messageSource: MessageSource
) {
// ...
}
```
2. **使用扩展函数创建错误响应**
```kotlin
ApiResponse.error(ErrorCode.PARAM_ERROR, messageSource = messageSource)
```
3. **自定义消息(如果需要)**
```kotlin
ApiResponse.error(ErrorCode.PARAM_ERROR, "自定义消息", messageSource)
```
### 前端使用
1. **在组件中使用 useTranslation**
```typescript
import { useTranslation } from 'react-i18next'
const { t } = useTranslation()
```
2. **翻译文本**
```typescript
t('common.save') // 返回当前语言的"保存"
t('account.accountName') // 返回当前语言的"账户名称"
```
3. **切换语言**(可选):
```typescript
import { changeLanguage } from '../i18n/config'
changeLanguage('zh-CN') // 切换到简体中文
changeLanguage('zh-TW') // 切换到繁体中文
changeLanguage('en') // 切换到英文
```
## 语言检测规则
### 前端
1. 优先使用 localStorage 中保存的语言设置
2. 如果没有,检测系统语言:
- `zh-CN`, `zh` → 简体中文
- `zh-TW`, `zh-HK`, `zh-MO` → 繁体中文
- 其他 → 英文(默认)
### 后端
1. 从 HTTP Header 读取:
- `X-Language` (优先)
- `Accept-Language` (备选)
2. 语言映射规则同前端
3. 默认语言:英文
## 测试建议
1. **测试语言检测**
- 修改浏览器语言设置,刷新页面,检查是否自动切换
- 测试不同语言下的 API 响应消息
2. **测试语言切换**
- 在前端添加语言切换组件(可选)
- 测试切换后 API 请求是否正确传递语言 Header
3. **测试错误消息**
- 触发各种错误,检查错误消息是否正确显示对应语言
## 注意事项
1. **向后兼容**:如果前端没有发送语言 Header,后端默认使用英文
2. **消息键命名**:所有消息键使用 `error.` 前缀,便于管理
3. **翻译质量**:建议由专业翻译人员审核翻译内容
4. **性能**:语言包已配置缓存,不会影响性能
## 下一步
1. 完成所有 Controller 的更新
2. 完成所有前端页面的翻译
3. 添加语言切换组件(可选)
4. 全面测试多语言功能
5. 更新 API 文档,说明语言 Header 的使用
-89
View File
@@ -1,89 +0,0 @@
# 前端语言切换功能实现总结
## ✅ 已完成的工作
### 1. 语言切换组件 ✅
- **文件**: `frontend/src/components/LanguageSwitcher.tsx`
- **功能**:
- 显示当前语言(简体中文、繁體中文、English)
- 支持手动切换语言
- 切换后自动刷新页面以应用 Ant Design 的 locale
- 支持移动端和桌面端响应式设计
### 2. Layout 组件集成 ✅
- **文件**: `frontend/src/components/Layout.tsx`
- **更新内容**:
- 在移动端 Header 中添加了语言切换器
- 在桌面端 Sider 中添加了语言切换器
- 菜单项已使用 i18n 翻译(menu.*
- 退出登录确认对话框已使用 i18n
### 3. i18n 配置优化 ✅
- **文件**: `frontend/src/i18n/config.ts`
- **功能**:
- 自动检测系统语言
- 优先使用 localStorage 中保存的用户选择
- 提供 `changeLanguage()` 函数用于手动切换
- 提供 `getCurrentLanguage()` 函数获取当前语言
### 4. 语言包扩展 ✅
- **新增翻译键**: `menu.*`
- `menu.accounts`: 账户管理
- `menu.copyTrading`: 跟单交易
- `menu.leaders`: Leader 管理
- `menu.templates`: 跟单模板
- `menu.copyTradingConfig`: 跟单配置
- `menu.positions`: 仓位管理
- `menu.statistics`: 统计信息
- `menu.users`: 用户管理
- `menu.systemSettings`: 系统管理
- `menu.logout`: 退出登录
- `menu.logoutConfirm`: 确认退出
- `menu.logoutConfirmDesc`: 确定要退出登录吗?
- `menu.navigation`: 导航菜单
### 5. API 请求同步 ✅
- **文件**: `frontend/src/services/api.ts`
- **功能**: 自动在请求头中添加 `X-Language`,与后端语言保持一致
## 使用方式
### 用户操作
1. 在页面右上角(桌面端)或 Header(移动端)找到语言切换器
2. 点击下拉菜单选择语言:
- 简体中文
- 繁體中文
- English
3. 选择后页面会自动刷新,应用新语言
### 技术实现
- 语言选择保存在 `localStorage``i18n_language` 键中
- 切换语言后自动刷新页面,确保:
- Ant Design 的 locale 正确应用
- 所有组件重新渲染,使用新语言
- API 请求自动携带新语言 Header
## 编译状态
- ✅ 前端编译通过,无错误
- ✅ 所有组件正常工作
## 位置说明
### 桌面端
- 语言切换器位于左侧导航栏顶部(PolyHermes 标题旁边)
### 移动端
- 语言切换器位于顶部 Header 右侧(GitHub 和 Twitter 图标之前)
## 后续优化建议
1. **无需刷新页面切换**(可选):
- 当前实现需要刷新页面以确保 Ant Design locale 正确应用
- 未来可以考虑动态更新 ConfigProvider 的 locale,避免刷新
2. **语言图标优化**(可选):
- 可以使用国旗图标或语言缩写(如 CN、TW、EN)代替文字
3. **语言切换动画**(可选):
- 添加平滑的切换动画,提升用户体验
-572
View File
@@ -1,572 +0,0 @@
# 多语言支持遗漏工作清单
## 后端遗漏工作
### ❌ 需要更新的 Controller
#### 1. CopyTradingController
- ✅ 已添加 MessageSource 依赖注入
-**所有 ApiResponse.error() 调用都缺少 messageSource 参数**
- 第 31 行:`ApiResponse.error(ErrorCode.PARAM_ACCOUNT_ID_INVALID)` → 需要添加 `, messageSource = messageSource`
- 第 34 行:`ApiResponse.error(ErrorCode.PARAM_TEMPLATE_ID_INVALID)` → 需要添加
- 第 37 行:`ApiResponse.error(ErrorCode.PARAM_LEADER_ID_INVALID)` → 需要添加
- 第 48-49 行:`ApiResponse.error(ErrorCode.PARAM_ERROR, e.message)` → 需要添加 `, messageSource`
- 第 55 行:`ApiResponse.error(ErrorCode.SERVER_COPY_TRADING_CREATE_FAILED, e.message)` → 需要添加
- 第 72, 77 行:查询列表的错误响应 → 需要添加
- 第 88, 99-101, 107 行:更新状态的错误响应 → 需要添加
- 第 118, 129-130, 136 行:删除的错误响应 → 需要添加
- 第 147, 158-159, 165 行:查询模板的错误响应 → 需要添加
#### 2. CopyTradingTemplateController
-**未添加 MessageSource 依赖注入**
-**所有 ApiResponse.error() 调用都需要更新**
- 需要添加:`private val messageSource: MessageSource`
- 需要添加导入:`import com.wrbug.polymarketbot.util.error`
- 所有 `ApiResponse.error()` 调用都需要添加 `messageSource` 参数
#### 3. MarketController
-**未添加 MessageSource 依赖注入**
-**所有 ApiResponse.error() 调用都需要更新**
- 第 34 行:`ApiResponse.error(ErrorCode.PARAM_MARKET_ID_EMPTY)`
- 第 44, 49 行:`ApiResponse.error(ErrorCode.SERVER_MARKET_PRICE_FETCH_FAILED, e.message)`
- 第 62 行:`ApiResponse.error(ErrorCode.PARAM_TOKEN_ID_EMPTY)`
- 第 72, 77 行:`ApiResponse.error(ErrorCode.SERVER_MARKET_LATEST_PRICE_FETCH_FAILED, e.message)`
#### 4. CopyTradingStatisticsController
-**未添加 MessageSource 依赖注入**
-**所有 ApiResponse.error() 调用都需要更新**
- 第 31 行:`ApiResponse.error(ErrorCode.PARAM_COPY_TRADING_ID_INVALID)`
- 第 42-43, 49 行:统计查询的错误响应
- 需要检查整个文件的所有错误响应
#### 5. ProxyConfigController
-**未添加 MessageSource 依赖注入**
-**所有 ApiResponse.error() 调用都需要更新**
- 第 35 行:`ApiResponse.error(ErrorCode.SERVER_ERROR, "获取代理配置失败:${e.message}")`
- 第 49 行:`ApiResponse.error(ErrorCode.SERVER_ERROR, "获取代理配置列表失败:${e.message}")`
- 需要检查整个文件的所有错误响应
#### 6. HealthController
-**不需要更新**(没有错误响应,只有健康检查)
### 更新模式
对于每个 Controller,需要:
1. **添加导入**
```kotlin
import com.wrbug.polymarketbot.util.error
import org.springframework.context.MessageSource
```
2. **添加依赖注入**
```kotlin
class YourController(
private val yourService: YourService,
private val messageSource: MessageSource // 添加这一行
)
```
3. **更新所有 ApiResponse.error() 调用**
```kotlin
// 模式1:只有 ErrorCode
ApiResponse.error(ErrorCode.PARAM_ERROR)
ApiResponse.error(ErrorCode.PARAM_ERROR, messageSource = messageSource)
// 模式2ErrorCode + 消息
ApiResponse.error(ErrorCode.PARAM_ERROR, e.message)
ApiResponse.error(ErrorCode.PARAM_ERROR, e.message, messageSource)
```
## 前端遗漏工作
### ❌ 需要更新的页面组件(23个页面,只有1个已更新)
#### ✅ 已完成的页面
1. **AccountDetail.tsx** - 已完全使用 i18n
#### ❌ 待更新的页面(22个)
1. **Login.tsx**
- 硬编码文本:`'登录成功'`, `'登录失败'`, `'用户名'`, `'密码'`
- 需要添加:`import { useTranslation } from 'react-i18next'`
- 需要添加:`const { t } = useTranslation()`
- 需要替换所有硬编码文本
2. **AccountList.tsx**
- 需要检查并替换所有硬编码文本
3. **AccountImport.tsx**
- 硬编码文本:`'钱包地址与私钥不匹配'`, `'钱包地址格式不正确'`, `'钱包地址'`
- 需要更新
4. **AccountEdit.tsx**
- 需要检查并替换所有硬编码文本
5. **LeaderList.tsx**
- 需要检查并替换所有硬编码文本
6. **LeaderAdd.tsx**
- 需要检查并替换所有硬编码文本
7. **LeaderEdit.tsx**
- 需要检查并替换所有硬编码文本
8. **TemplateList.tsx**
- 需要检查并替换所有硬编码文本
9. **TemplateAdd.tsx**
- 需要检查并替换所有硬编码文本
10. **TemplateEdit.tsx**
- 需要检查并替换所有硬编码文本
11. **CopyTradingList.tsx**
- 硬编码文本:`'删除跟单成功'`, `'删除跟单失败'`, `'钱包'`, `'模板'`, `'Leader'`, `'取消'`, `'订单'`
- 需要更新
12. **CopyTradingAdd.tsx**
- 需要检查并替换所有硬编码文本
13. **CopyTradingStatistics.tsx**
- 需要检查并替换所有硬编码文本
14. **CopyTradingBuyOrders.tsx**
- 需要检查并替换所有硬编码文本
15. **CopyTradingSellOrders.tsx**
- 需要检查并替换所有硬编码文本
16. **CopyTradingMatchedOrders.tsx**
- 需要检查并替换所有硬编码文本
17. **PositionList.tsx**
- 硬编码文本:`'账户'`, `'市场'`, `'搜索账户、市场、方向...'`, `'确认卖出'`, `'取消'`, `'订单类型'`, `'确认赎回'`
- 需要更新
18. **OrderList.tsx**
- 需要检查并替换所有硬编码文本
19. **Statistics.tsx**
- 需要检查并替换所有硬编码文本
20. **UserList.tsx**
- 需要检查并替换所有硬编码文本
21. **ResetPassword.tsx**
- 需要检查并替换所有硬编码文本
22. **SystemSettings.tsx**
- 需要检查并替换所有硬编码文本
23. **ConfigPage.tsx**
- 需要检查并替换所有硬编码文本
### App.tsx 中的硬编码文本
**App.tsx** 中有硬编码的中文文本:
- 第 61 行:`'订单创建'`
- 第 63 行:`'订单更新'`
- 第 65 行:`'订单取消'`
- 第 67 行:`'订单事件'`
- 第 79 行:`'买入'`, `'卖出'`
- 第 92 行:`'市场:'`, `'状态:'`, `'已成交:'`, `'剩余:'`
需要:
1. 添加 `import { useTranslation } from 'react-i18next'`
2. 在组件中使用 `const { t } = useTranslation()`
3. 替换所有硬编码文本
### 前端更新模式
对于每个页面组件:
1. **添加导入**
```typescript
import { useTranslation } from 'react-i18next'
```
2. **在组件中使用**
```typescript
const YourComponent: React.FC = () => {
const { t } = useTranslation()
// ...
}
```
3. **替换硬编码文本**
```typescript
// 旧代码
<Button></Button>
message.success('操作成功')
// 新代码
<Button>{t('common.save')}</Button>
message.success(t('message.operationSuccess'))
```
4. **扩展语言包**
-`frontend/src/locales/*/common.json` 中添加缺失的翻译键
- 确保三个语言包(zh-CN, zh-TW, en)都有对应的翻译
## 语言包扩展
### 需要添加的翻译键
根据检查,需要在语言包中添加以下键:
```json
{
"order": {
"create": "订单创建",
"update": "订单更新",
"cancel": "订单取消",
"event": "订单事件",
"buy": "买入",
"sell": "卖出",
"market": "市场",
"status": "状态",
"filled": "已成交",
"remaining": "剩余"
},
"wallet": {
"address": "钱包地址",
"addressMismatch": "钱包地址与私钥不匹配",
"addressInvalid": "钱包地址格式不正确"
},
"copyTrading": {
"deleteSuccess": "删除跟单成功",
"deleteFailed": "删除跟单失败",
"wallet": "钱包",
"template": "模板",
"leader": "Leader"
},
"position": {
"account": "账户",
"market": "市场",
"searchPlaceholder": "搜索账户、市场、方向...",
"confirmSell": "确认卖出",
"confirmRedeem": "确认赎回",
"orderType": "订单类型"
}
}
```
## 优先级建议
### 高优先级(核心功能)
1. ✅ 后端:完成所有 Controller 的 MessageSource 更新
2. ✅ 前端:更新 Login.tsx(登录页面)
3. ✅ 前端:更新 App.tsx(全局通知)
### 中优先级(常用功能)
4. 前端:更新 AccountList.tsx, AccountImport.tsx
5. 前端:更新 LeaderList.tsx, LeaderAdd.tsx
6. 前端:更新 CopyTradingList.tsx
### 低优先级(其他页面)
7. 前端:逐步更新其他页面组件
## 验证清单
完成后检查:
### 后端
- [ ] 所有 Controller 都注入了 MessageSource
- [ ] 所有 ApiResponse.error() 调用都传入了 messageSource
- [ ] 编译无错误
- [ ] 测试不同语言下的错误消息
### 前端
- [ ] 所有页面都使用了 useTranslation
- [ ] 所有硬编码文本都已替换
- [ ] 语言包包含所有需要的翻译键
- [ ] 测试不同语言下的页面显示
- [ ] 测试语言切换功能
## 后端遗漏工作
### ❌ 需要更新的 Controller
#### 1. CopyTradingController
- ✅ 已添加 MessageSource 依赖注入
-**所有 ApiResponse.error() 调用都缺少 messageSource 参数**
- 第 31 行:`ApiResponse.error(ErrorCode.PARAM_ACCOUNT_ID_INVALID)` → 需要添加 `, messageSource = messageSource`
- 第 34 行:`ApiResponse.error(ErrorCode.PARAM_TEMPLATE_ID_INVALID)` → 需要添加
- 第 37 行:`ApiResponse.error(ErrorCode.PARAM_LEADER_ID_INVALID)` → 需要添加
- 第 48-49 行:`ApiResponse.error(ErrorCode.PARAM_ERROR, e.message)` → 需要添加 `, messageSource`
- 第 55 行:`ApiResponse.error(ErrorCode.SERVER_COPY_TRADING_CREATE_FAILED, e.message)` → 需要添加
- 第 72, 77 行:查询列表的错误响应 → 需要添加
- 第 88, 99-101, 107 行:更新状态的错误响应 → 需要添加
- 第 118, 129-130, 136 行:删除的错误响应 → 需要添加
- 第 147, 158-159, 165 行:查询模板的错误响应 → 需要添加
#### 2. CopyTradingTemplateController
-**未添加 MessageSource 依赖注入**
-**所有 ApiResponse.error() 调用都需要更新**
- 需要添加:`private val messageSource: MessageSource`
- 需要添加导入:`import com.wrbug.polymarketbot.util.error`
- 所有 `ApiResponse.error()` 调用都需要添加 `messageSource` 参数
#### 3. MarketController
-**未添加 MessageSource 依赖注入**
-**所有 ApiResponse.error() 调用都需要更新**
- 第 34 行:`ApiResponse.error(ErrorCode.PARAM_MARKET_ID_EMPTY)`
- 第 44, 49 行:`ApiResponse.error(ErrorCode.SERVER_MARKET_PRICE_FETCH_FAILED, e.message)`
- 第 62 行:`ApiResponse.error(ErrorCode.PARAM_TOKEN_ID_EMPTY)`
- 第 72, 77 行:`ApiResponse.error(ErrorCode.SERVER_MARKET_LATEST_PRICE_FETCH_FAILED, e.message)`
#### 4. CopyTradingStatisticsController
-**未添加 MessageSource 依赖注入**
-**所有 ApiResponse.error() 调用都需要更新**
- 第 31 行:`ApiResponse.error(ErrorCode.PARAM_COPY_TRADING_ID_INVALID)`
- 第 42-43, 49 行:统计查询的错误响应
- 需要检查整个文件的所有错误响应
#### 5. ProxyConfigController
-**未添加 MessageSource 依赖注入**
-**所有 ApiResponse.error() 调用都需要更新**
- 第 35 行:`ApiResponse.error(ErrorCode.SERVER_ERROR, "获取代理配置失败:${e.message}")`
- 第 49 行:`ApiResponse.error(ErrorCode.SERVER_ERROR, "获取代理配置列表失败:${e.message}")`
- 需要检查整个文件的所有错误响应
#### 6. HealthController
-**不需要更新**(没有错误响应,只有健康检查)
### 更新模式
对于每个 Controller,需要:
1. **添加导入**
```kotlin
import com.wrbug.polymarketbot.util.error
import org.springframework.context.MessageSource
```
2. **添加依赖注入**
```kotlin
class YourController(
private val yourService: YourService,
private val messageSource: MessageSource // 添加这一行
)
```
3. **更新所有 ApiResponse.error() 调用**
```kotlin
// 模式1:只有 ErrorCode
ApiResponse.error(ErrorCode.PARAM_ERROR)
ApiResponse.error(ErrorCode.PARAM_ERROR, messageSource = messageSource)
// 模式2ErrorCode + 消息
ApiResponse.error(ErrorCode.PARAM_ERROR, e.message)
ApiResponse.error(ErrorCode.PARAM_ERROR, e.message, messageSource)
```
## 前端遗漏工作
### ❌ 需要更新的页面组件(23个页面,只有1个已更新)
#### ✅ 已完成的页面
1. **AccountDetail.tsx** - 已完全使用 i18n
#### ❌ 待更新的页面(22个)
1. **Login.tsx**
- 硬编码文本:`'登录成功'`, `'登录失败'`, `'用户名'`, `'密码'`
- 需要添加:`import { useTranslation } from 'react-i18next'`
- 需要添加:`const { t } = useTranslation()`
- 需要替换所有硬编码文本
2. **AccountList.tsx**
- 需要检查并替换所有硬编码文本
3. **AccountImport.tsx**
- 硬编码文本:`'钱包地址与私钥不匹配'`, `'钱包地址格式不正确'`, `'钱包地址'`
- 需要更新
4. **AccountEdit.tsx**
- 需要检查并替换所有硬编码文本
5. **LeaderList.tsx**
- 需要检查并替换所有硬编码文本
6. **LeaderAdd.tsx**
- 需要检查并替换所有硬编码文本
7. **LeaderEdit.tsx**
- 需要检查并替换所有硬编码文本
8. **TemplateList.tsx**
- 需要检查并替换所有硬编码文本
9. **TemplateAdd.tsx**
- 需要检查并替换所有硬编码文本
10. **TemplateEdit.tsx**
- 需要检查并替换所有硬编码文本
11. **CopyTradingList.tsx**
- 硬编码文本:`'删除跟单成功'`, `'删除跟单失败'`, `'钱包'`, `'模板'`, `'Leader'`, `'取消'`, `'订单'`
- 需要更新
12. **CopyTradingAdd.tsx**
- 需要检查并替换所有硬编码文本
13. **CopyTradingStatistics.tsx**
- 需要检查并替换所有硬编码文本
14. **CopyTradingBuyOrders.tsx**
- 需要检查并替换所有硬编码文本
15. **CopyTradingSellOrders.tsx**
- 需要检查并替换所有硬编码文本
16. **CopyTradingMatchedOrders.tsx**
- 需要检查并替换所有硬编码文本
17. **PositionList.tsx**
- 硬编码文本:`'账户'`, `'市场'`, `'搜索账户、市场、方向...'`, `'确认卖出'`, `'取消'`, `'订单类型'`, `'确认赎回'`
- 需要更新
18. **OrderList.tsx**
- 需要检查并替换所有硬编码文本
19. **Statistics.tsx**
- 需要检查并替换所有硬编码文本
20. **UserList.tsx**
- 需要检查并替换所有硬编码文本
21. **ResetPassword.tsx**
- 需要检查并替换所有硬编码文本
22. **SystemSettings.tsx**
- 需要检查并替换所有硬编码文本
23. **ConfigPage.tsx**
- 需要检查并替换所有硬编码文本
### App.tsx 中的硬编码文本
**App.tsx** 中有硬编码的中文文本:
- 第 61 行:`'订单创建'`
- 第 63 行:`'订单更新'`
- 第 65 行:`'订单取消'`
- 第 67 行:`'订单事件'`
- 第 79 行:`'买入'`, `'卖出'`
- 第 92 行:`'市场:'`, `'状态:'`, `'已成交:'`, `'剩余:'`
需要:
1. 添加 `import { useTranslation } from 'react-i18next'`
2. 在组件中使用 `const { t } = useTranslation()`
3. 替换所有硬编码文本
### 前端更新模式
对于每个页面组件:
1. **添加导入**
```typescript
import { useTranslation } from 'react-i18next'
```
2. **在组件中使用**
```typescript
const YourComponent: React.FC = () => {
const { t } = useTranslation()
// ...
}
```
3. **替换硬编码文本**
```typescript
// 旧代码
<Button></Button>
message.success('操作成功')
// 新代码
<Button>{t('common.save')}</Button>
message.success(t('message.operationSuccess'))
```
4. **扩展语言包**
-`frontend/src/locales/*/common.json` 中添加缺失的翻译键
- 确保三个语言包(zh-CN, zh-TW, en)都有对应的翻译
## 语言包扩展
### 需要添加的翻译键
根据检查,需要在语言包中添加以下键:
```json
{
"order": {
"create": "订单创建",
"update": "订单更新",
"cancel": "订单取消",
"event": "订单事件",
"buy": "买入",
"sell": "卖出",
"market": "市场",
"status": "状态",
"filled": "已成交",
"remaining": "剩余"
},
"wallet": {
"address": "钱包地址",
"addressMismatch": "钱包地址与私钥不匹配",
"addressInvalid": "钱包地址格式不正确"
},
"copyTrading": {
"deleteSuccess": "删除跟单成功",
"deleteFailed": "删除跟单失败",
"wallet": "钱包",
"template": "模板",
"leader": "Leader"
},
"position": {
"account": "账户",
"market": "市场",
"searchPlaceholder": "搜索账户、市场、方向...",
"confirmSell": "确认卖出",
"confirmRedeem": "确认赎回",
"orderType": "订单类型"
}
}
```
## 优先级建议
### 高优先级(核心功能)
1. ✅ 后端:完成所有 Controller 的 MessageSource 更新
2. ✅ 前端:更新 Login.tsx(登录页面)
3. ✅ 前端:更新 App.tsx(全局通知)
### 中优先级(常用功能)
4. 前端:更新 AccountList.tsx, AccountImport.tsx
5. 前端:更新 LeaderList.tsx, LeaderAdd.tsx
6. 前端:更新 CopyTradingList.tsx
### 低优先级(其他页面)
7. 前端:逐步更新其他页面组件
## 验证清单
完成后检查:
### 后端
- [ ] 所有 Controller 都注入了 MessageSource
- [ ] 所有 ApiResponse.error() 调用都传入了 messageSource
- [ ] 编译无错误
- [ ] 测试不同语言下的错误消息
### 前端
- [ ] 所有页面都使用了 useTranslation
- [ ] 所有硬编码文本都已替换
- [ ] 语言包包含所有需要的翻译键
- [ ] 测试不同语言下的页面显示
- [ ] 测试语言切换功能