Skip to content

Commit 34eb41c

Browse files
committed
feat: i18 support
1 parent 8591d4e commit 34eb41c

File tree

11 files changed

+1602
-3
lines changed

11 files changed

+1602
-3
lines changed

backend/common/i18n/README.md

Lines changed: 254 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,254 @@
1+
# 国际化 (i18n) 模块
2+
3+
FastAPI 项目的完整国际化解决方案,支持多语言响应消息、验证错误消息和业务逻辑消息的自动翻译。
4+
5+
## 🌍 功能特性
6+
7+
- **自动语言检测**: 支持从 URL 参数、请求头、Accept-Language 等多种方式检测用户语言偏好
8+
- **响应码国际化**: 自动翻译所有响应状态码消息
9+
- **验证消息国际化**: 支持 100+ 条 Pydantic 验证错误消息的翻译
10+
- **业务消息国际化**: 支持业务逻辑中的错误和成功消息翻译
11+
- **灵活的翻译管理**: 基于 JSON 文件的翻译资源管理
12+
- **上下文感知**: 支持参数格式化的动态翻译
13+
14+
## 📁 文件结构
15+
16+
```
17+
backend/common/i18n/
18+
├── __init__.py # 模块导出
19+
├── manager.py # 国际化管理器
20+
├── middleware.py # 国际化中间件
21+
├── locales/ # 翻译文件目录
22+
│ ├── zh-CN.json # 中文翻译
23+
│ └── en-US.json # 英文翻译
24+
├── usage_example.py # 使用示例
25+
└── README.md # 文档说明
26+
```
27+
28+
## 🚀 快速开始
29+
30+
### 1. 启用国际化中间件
31+
32+
`main.py` 中添加国际化中间件:
33+
34+
```python
35+
from fastapi import FastAPI
36+
from backend.common.i18n import I18nMiddleware
37+
38+
app = FastAPI()
39+
40+
# 添加国际化中间件
41+
app.add_middleware(I18nMiddleware, default_language='zh-CN')
42+
```
43+
44+
### 2. 基本使用
45+
46+
```python
47+
from backend.common.i18n.manager import t
48+
from backend.common.response.response_code import CustomResponseCode
49+
50+
# 使用响应码(自动国际化)
51+
res = CustomResponseCode.HTTP_200
52+
print(res.msg) # 根据当前语言显示 "请求成功" 或 "Request successful"
53+
54+
# 手动翻译
55+
message = t('error.user_not_found')
56+
formatted_msg = t('error.invalid_request_params', message="用户名")
57+
```
58+
59+
### 3. 语言切换方式
60+
61+
客户端可以通过以下方式指定语言:
62+
63+
1. **URL 参数**: `GET /api/users?lang=en-US`
64+
2. **请求头**: `X-Language: en-US`
65+
3. **Accept-Language**: `Accept-Language: en-US,en;q=0.9`
66+
67+
优先级: URL 参数 > X-Language 头 > Accept-Language 头 > 默认语言
68+
69+
## 📖 API 文档
70+
71+
### I18nManager
72+
73+
国际化管理器,负责加载和管理翻译资源。
74+
75+
```python
76+
from backend.common.i18n.manager import get_i18n_manager, t
77+
78+
# 获取管理器实例
79+
i18n = get_i18n_manager()
80+
81+
# 翻译方法
82+
def t(key: str, language: str = None, **kwargs) -> str:
83+
"""
84+
翻译函数
85+
86+
Args:
87+
key: 翻译键,支持点号分隔的嵌套键
88+
language: 目标语言,None 则使用当前语言
89+
**kwargs: 格式化参数
90+
91+
Returns:
92+
翻译后的文本
93+
"""
94+
```
95+
96+
### I18nMiddleware
97+
98+
国际化中间件,自动检测和设置请求语言。
99+
100+
```python
101+
class I18nMiddleware(BaseHTTPMiddleware):
102+
def __init__(self, app, default_language: str = 'zh-CN'):
103+
"""
104+
Args:
105+
app: FastAPI 应用实例
106+
default_language: 默认语言
107+
"""
108+
```
109+
110+
## 🔧 翻译文件格式
111+
112+
翻译文件使用 JSON 格式,支持嵌套结构:
113+
114+
```json
115+
{
116+
"response": {
117+
"success": "请求成功",
118+
"error": "请求错误"
119+
},
120+
"error": {
121+
"user_not_found": "用户不存在",
122+
"invalid_request_params": "请求参数非法: {message}"
123+
},
124+
"validation": {
125+
"missing": "字段为必填项",
126+
"string_too_short": "字符串应至少有 {min_length} 个字符"
127+
}
128+
}
129+
```
130+
131+
## 💡 使用示例
132+
133+
### 在 API 端点中使用
134+
135+
```python
136+
from fastapi import APIRouter
137+
from backend.common.i18n.manager import t
138+
from backend.common.response.response_code import CustomResponseCode
139+
140+
router = APIRouter()
141+
142+
@router.get("/users")
143+
async def get_users():
144+
# 响应码会自动国际化
145+
res = CustomResponseCode.HTTP_200
146+
return {
147+
"code": res.code,
148+
"msg": res.msg, # 自动翻译
149+
"data": []
150+
}
151+
152+
@router.post("/users")
153+
async def create_user(user_data: dict):
154+
if not user_data.get('username'):
155+
# 手动翻译错误消息
156+
raise HTTPException(
157+
status_code=400,
158+
detail=t('error.user_not_found')
159+
)
160+
161+
return {
162+
"msg": t('success.create_success', name="用户")
163+
}
164+
```
165+
166+
### 在服务层中使用
167+
168+
```python
169+
from backend.common.exception.errors import CustomError
170+
from backend.common.response.response_code import CustomErrorCode
171+
from backend.common.i18n.manager import t
172+
173+
class UserService:
174+
def get_user(self, user_id: int):
175+
user = self.user_repository.get(user_id)
176+
if not user:
177+
# 使用预定义的错误码
178+
raise CustomError(error=CustomErrorCode.USER_NOT_FOUND)
179+
180+
return user
181+
182+
def validate_password(self, password: str):
183+
if len(password) < 8:
184+
# 使用动态翻译
185+
raise ValueError(t('error.password_too_short', min_length=8))
186+
```
187+
188+
### 在 Pydantic 模型中使用
189+
190+
```python
191+
from pydantic import BaseModel, Field, validator
192+
from backend.common.i18n.manager import t
193+
194+
class UserCreateSchema(BaseModel):
195+
username: str = Field(..., description="用户名")
196+
password: str = Field(..., description="密码")
197+
198+
@validator('username')
199+
def validate_username(cls, v):
200+
if not v or len(v) < 3:
201+
raise ValueError(t('validation.string_too_short', min_length=3))
202+
return v
203+
```
204+
205+
## 🔄 扩展新语言
206+
207+
1.`locales/` 目录下创建新的语言文件,如 `ja-JP.json`
208+
2. 复制现有翻译文件结构,翻译所有文本
209+
3.`I18nManager` 中添加新语言到 `supported_languages` 列表
210+
4. 在中间件的 `_normalize_language` 方法中添加语言映射
211+
212+
## 📝 翻译键命名规范
213+
214+
- **响应码**: `response.{type}` (如: `response.success`)
215+
- **错误消息**: `error.{error_type}` (如: `error.user_not_found`)
216+
- **成功消息**: `success.{action}` (如: `success.login_success`)
217+
- **验证消息**: `validation.{validation_type}` (如: `validation.missing`)
218+
- **任务消息**: `task.{task_type}` (如: `task.execute_failed`)
219+
220+
## ⚠️ 注意事项
221+
222+
1. **性能考虑**: 翻译文件在启动时加载到内存,避免频繁的文件 I/O
223+
2. **缓存机制**: 使用 `@lru_cache` 缓存管理器实例
224+
3. **参数格式化**: 支持 Python 字符串格式化语法,如 `{name}`, `{count:d}`
225+
4. **回退机制**: 如果翻译不存在,会回退到默认语言或返回翻译键
226+
5. **上下文变量**: 使用 `contextvars` 确保请求级别的语言隔离
227+
228+
## 🔍 故障排除
229+
230+
### 翻译不生效
231+
- 检查翻译文件是否存在且格式正确
232+
- 确认中间件已正确添加
233+
- 验证翻译键是否正确
234+
235+
### 语言检测不准确
236+
- 检查请求头格式
237+
- 确认支持的语言列表包含目标语言
238+
- 验证语言代码规范化映射
239+
240+
### 格式化参数错误
241+
- 确保参数名与翻译文件中的占位符匹配
242+
- 检查参数类型是否正确
243+
- 验证格式化语法
244+
245+
## 🤝 贡献指南
246+
247+
1. 添加新的翻译键时,请同时更新所有语言文件
248+
2. 保持翻译文件结构的一致性
249+
3. 为新功能编写相应的使用示例
250+
4. 更新文档说明
251+
252+
---
253+
254+
通过这个国际化模块,你的 FastAPI 项目可以轻松支持多语言,为全球用户提供本地化的体验。

backend/common/i18n/__init__.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
"""
4+
国际化(i18n)模块
5+
6+
支持多语言的翻译系统
7+
"""
8+
9+
from .manager import I18nManager, get_i18n_manager
10+
from .middleware import I18nMiddleware
11+
12+
__all__ = ['I18nManager', 'get_i18n_manager', 'I18nMiddleware']

0 commit comments

Comments
 (0)