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

7.4 KiB
Raw Permalink Blame History

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 的翻译

注意事项

  1. 线程安全:每个线程可通过 setCurrentLang() 独立设置语言。
  2. 性能优化:所有翻译数据在初始化时一次性加载进内存,避免重复 IO。
  3. 超时清理:长时间未活动的线程语言记录将被清除,防止内存泄漏。
  4. 编码要求:所有 msg.txt 文件必须为 UTF-8 编码(或其他指定编码)。
  5. 错误处理:未找到翻译时返回原文,适合开发阶段“降级显示”。

扩展建议

  • 添加 .json.yaml 格式支持。
  • 增加运行时动态添加翻译项的功能。
  • 提供缺失翻译日志记录接口(如 missed_pt 预留字段)。
  • 支持复数形式、占位符替换(如 %s, {name})。

版本信息

  • 创建时间:未知
  • 最后修改:未知
  • 作者:未知
  • 许可协议:请参考项目整体 LICENSE