apppublic/aidocs/MiniI18N.md
2025-10-05 11:23:33 +08:00

307 lines
7.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# `MiniI18N` 国际化模块技术文档
```markdown
# MiniI18N 模块技术文档
## 概述
`MiniI18N` 是一个轻量级的 Python 国际化i18n工具用于实现多语言文本的动态加载与翻译。它支持基于线程的用户语言隔离、自动语言检测、键值对格式的消息文件解析并通过单例模式确保全局唯一实例。
该模块适用于需要在不同语言环境下运行的小型应用或 Web 后端服务。
---
## 依赖
- Python 标准库:
- `os`, `re`, `sys`, `codecs`, `threading`, `time`, `locale`
- 第三方模块(来自 `appPublic` 包):
- `appPublic.folderUtils._mkdir`
- `appPublic.Singleton.SingletonDecorator`
- `appPublic.folderUtils.ProgramPath`
> ⚠️ 注意:需确保 `appPublic` 包已安装并可导入。
---
## 核心功能
- 支持 UTF-8 编码的多语言 `.txt` 文件读取。
- 基于正则表达式解析 `key: value` 形式的消息条目。
- 忽略以 `#` 开头的注释行。
- 线程安全的语言上下文管理(每个线程可设置独立语言)。
- 单例模式保证全局配置一致性。
- 自动清理过期客户端语言状态(默认超时 600 秒)。
- 支持语言别名映射(如 `zh-CN``zh`)。
---
## 数据格式说明
### 消息文件结构(`msg.txt`
位于 `{path}/i18n/{lang}/msg.txt`,每行为:
```
key : value
# 这是注释
hello_world : 你好,世界
welcome : 欢迎使用我们的产品
```
#### 规则:
- 使用 `:` 分隔键和值。
- 可包含空格,但会被去除前后空白。
- 支持特殊字符转义(见下文)。
- `#` 开头的行为注释,将被忽略。
---
## 特殊字符编码机制
由于键值中可能包含冒号 `:` 或换行符等,模块内置了一套简单的转义机制。
### 转义表 (`convert_pairs`)
| 原始字符 | 转义后字符串 |
|--------|-------------|
| `:` | `\x3A` |
| `\n` | `\x0A` |
| `\r` | `\x0D` |
| `\` | `\\\\` |
> 示例:`user:name` → 键变为 `user\x3Aname`
### 相关函数
#### `charEncode(s: str) -> str`
对字符串中的特殊字符进行编码。
#### `charDecode(s: str) -> str`
对编码后的字符串进行解码,还原原始内容。
---
## 主要函数与类
### 辅助函数
#### `dictModify(d: dict, md: dict) -> dict`
合并字典 `md` 到 `d` 中,仅当值不为 `None` 时更新。
```python
dictModify({'a': 1}, {'a': None, 'b': 2}) # 返回 {'a': 1, 'b': 2}
```
#### `getTextDictFromLines(lines: list[str]) -> dict`
从文本行列表中提取键值对字典,跳过注释,解析 `key: value` 并自动解码。
#### `getFirstLang(lang: str) -> str`
从逗号分隔的语言列表中返回第一个语言标签。
```python
getFirstLang("zh-CN,zh,en") # 返回 "zh-CN"
```
---
### 类:`MiniI18N`
使用 `@SingletonDecorator` 装饰,确保全局只有一个实例。
#### 构造方法:`__init__(path, lang=None, coding='utf8')`
| 参数 | 类型 | 描述 |
|---------|--------|------|
| `path` | str | 应用根路径,用于查找 `/i18n` 目录 |
| `lang` | str or None | 默认语言(可选),未指定则使用系统默认语言 |
| `coding`| str | 文件编码,默认 `'utf8'` |
> 初始化时会自动扫描 `path/i18n/` 下所有子目录作为语言包。
#### 属性
| 属性 | 类型 | 描述 |
|--------------------|----------|------|
| `path` | str | 根路径 |
| `curLang` | str | 系统默认语言(来自 `locale.getdefaultlocale()` |
| `coding` | str | 文本编码方式 |
| `langTextDict` | dict | 存储各语言的翻译字典 `{lang: {key: text}}` |
| `clientLangs` | dict | 线程级语言状态 `{thread_id: {'timestamp': t, 'lang': lang}}` |
| `languageMapping` | dict | 语言别名映射,如 `{'zh-CN': 'zh'}` |
| `timeout` | int | 客户端语言状态过期时间(秒),默认 600 |
---
### 公共方法
#### `setLangMapping(lang: str, path: str)`
设置语言别名映射。
```python
i18n.setLangMapping('zh-CN', 'zh')
```
#### `getLangMapping(lang: str) -> str`
获取实际使用的语言名称(考虑映射规则)。
#### `setTimeout(timeout: int = 600)`
设置客户端语言缓存的超时时间。
#### `delClientLangs()`
清理超过 `timeout` 时间未访问的线程语言状态。
> 通常由内部调用,无需手动触发。
#### `getLangDict(lang: str) -> dict`
获取指定语言的翻译字典(经过映射处理)。
#### `getLangText(msg: str, lang: str = None) -> str`
根据当前或指定语言返回翻译文本。若无翻译,则返回原消息。
#### `setupMiniI18N()`
扫描 `i18n` 目录下的所有语言文件夹,加载 `msg.txt` 内容至内存。
> 调用示例:
>
> ```
> project_root/
> └── i18n/
> ├── en/
> │ └── msg.txt
> ├── zh/
> │ └── msg.txt
> └── ja/
> └── msg.txt
> ```
#### `setCurrentLang(lang: str)`
为当前线程设置语言环境。
```python
i18n.setCurrentLang('zh')
```
#### `getCurrentLang() -> str`
获取当前线程所设语言。
> 若未设置,则抛出异常(要求先调用 `setCurrentLang`)。
---
### 魔术方法:`__call__(self, msg, lang=None)`
使对象可直接调用,实现快捷翻译。
```python
_ = i18n # 绑定翻译函数
_("Hello") # 等价于 i18n.getLangText("Hello")
```
> 支持 bytes 输入自动解码。
---
## 工厂函数
### `getI18N(coding='utf8') -> MiniI18N`
创建并返回单例化的 `MiniI18N` 实例,使用当前程序路径作为根路径。
```python
from mymodule import getI18N
i18n = getI18N('utf8')
_ = i18n
print(_("Welcome"))
```
---
## 使用示例
### 1. 准备语言文件
```bash
your_project/
└── i18n/
├── en/
│ └── msg.txt
└── zh/
└── msg.txt
```
`zh/msg.txt` 内容:
```
# 中文翻译
greeting : 欢迎
goodbye : 再见
error.network : 网络错误,请重试
```
`en/msg.txt` 内容:
```
greeting : Welcome
goodbye : Goodbye
error.network : Network error, please retry
```
### 2. 加载并使用
```python
from mini_i18n import getI18N
# 获取 i18n 实例
i18n = getI18N()
# 设置当前线程语言
i18n.setCurrentLang('zh')
# 翻译
print(i18n('greeting')) # 输出:欢迎
print(i18n('goodbye')) # 输出:再见
# 切换语言
i18n.setCurrentLang('en')
print(i18n('greeting')) # 输出Welcome
```
### 3. 使用语言映射
```python
i18n.setLangMapping('zh-CN', 'zh')
i18n.setCurrentLang('zh-CN') # 实际使用 zh 的翻译
```
---
## 注意事项
1. **线程安全**:每个线程可通过 `setCurrentLang()` 独立设置语言。
2. **性能优化**:所有翻译数据在初始化时一次性加载进内存,避免重复 IO。
3. **超时清理**:长时间未活动的线程语言记录将被清除,防止内存泄漏。
4. **编码要求**:所有 `msg.txt` 文件必须为 UTF-8 编码(或其他指定编码)。
5. **错误处理**:未找到翻译时返回原文,适合开发阶段“降级显示”。
---
## 扩展建议
- 添加 `.json``.yaml` 格式支持。
- 增加运行时动态添加翻译项的功能。
- 提供缺失翻译日志记录接口(如 `missed_pt` 预留字段)。
- 支持复数形式、占位符替换(如 `%s`, `{name}`)。
---
## 版本信息
- 创建时间:未知
- 最后修改:未知
- 作者:未知
- 许可协议:请参考项目整体 LICENSE
---
```