7.4 KiB
7.4 KiB
MiniI18N 国际化模块技术文档
# 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
从逗号分隔的语言列表中返回第一个语言标签。
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)
设置语言别名映射。
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)
为当前线程设置语言环境。
i18n.setCurrentLang('zh')
getCurrentLang() -> str
获取当前线程所设语言。
若未设置,则抛出异常(要求先调用
setCurrentLang)。
魔术方法:__call__(self, msg, lang=None)
使对象可直接调用,实现快捷翻译。
_ = i18n # 绑定翻译函数
_("Hello") # 等价于 i18n.getLangText("Hello")
支持 bytes 输入自动解码。
工厂函数
getI18N(coding='utf8') -> MiniI18N
创建并返回单例化的 MiniI18N 实例,使用当前程序路径作为根路径。
from mymodule import getI18N
i18n = getI18N('utf8')
_ = i18n
print(_("Welcome"))
使用示例
1. 准备语言文件
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. 加载并使用
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. 使用语言映射
i18n.setLangMapping('zh-CN', 'zh')
i18n.setCurrentLang('zh-CN') # 实际使用 zh 的翻译
注意事项
- 线程安全:每个线程可通过
setCurrentLang()独立设置语言。 - 性能优化:所有翻译数据在初始化时一次性加载进内存,避免重复 IO。
- 超时清理:长时间未活动的线程语言记录将被清除,防止内存泄漏。
- 编码要求:所有
msg.txt文件必须为 UTF-8 编码(或其他指定编码)。 - 错误处理:未找到翻译时返回原文,适合开发阶段“降级显示”。
扩展建议
- 添加
.json或.yaml格式支持。 - 增加运行时动态添加翻译项的功能。
- 提供缺失翻译日志记录接口(如
missed_pt预留字段)。 - 支持复数形式、占位符替换(如
%s,{name})。
版本信息
- 创建时间:未知
- 最后修改:未知
- 作者:未知
- 许可协议:请参考项目整体 LICENSE