# `MiniI18N` 国际化工具技术文档 ```markdown # MiniI18N - 轻量级多语言支持模块 `MiniI18N` 是一个基于 Python 的轻量级国际化(i18n)工具,用于在应用程序中实现多语言文本的加载与动态切换。它通过读取指定目录下的语言文件(如 `msg.txt`),将键值对形式的消息映射到目标语言,并提供线程安全的语言上下文管理。 --- ## 模块依赖 ```python import os, re, sys import codecs from appPublic.folderUtils import _mkdir, ProgramPath from appPublic.Singleton import SingletonDecorator from appPublic.jsonConfig import getConfig import threading import time import locale ``` > 说明:该模块依赖于 `appPublic` 包中的若干实用工具类和函数,包括单例装饰器、配置读取、路径处理等。 --- ## 全局变量与常量 ### 正则表达式 - `comment_re`: 匹配以 `#` 开头的注释行。 ```python comment_re = re.compile(r'\s*#.*') ``` - `msg_re`: 匹配形如 `key : value` 的消息条目(允许前后空格)。 ```python msg_re = re.compile(r'\s*([^:]*)\s*:\s*([^\s].*)') ``` ### 编码转换表 用于对特殊字符进行编码/解码,避免配置文件解析冲突: ```python convert_pairs = { ':': '\\x3A', '\n': '\\x0A', '\r': '\\x0D', } ``` | 原始字符 | 编码表示 | |--------|---------| | `:` | `\x3A` | | `\n` | `\x0A` | | `\r` | `\x0D` | --- ## 核心函数 ### `dictModify(d, md)` 合并字典 `md` 到字典 `d`,仅当值不为 `None` 时更新。 **参数:** - `d` (dict): 目标字典 - `md` (dict): 更新数据字典 **返回:** - 修改后的 `d` --- ### `charEncode(s)` 对字符串中的特殊字符进行编码替换,防止解析错误。 **参数:** - `s` (str): 待编码字符串 **逻辑:** 1. 将 `\` 替换为 `\\\\` 2. 对 `convert_pairs` 中定义的字符进行编码替换 **示例:** ```python charEncode("hello:world\n") # 输出: "hello\\x3Aworld\\x0A" ``` --- ### `charDecode(s)` 反向解码由 `charEncode` 编码的字符串。 **参数:** - `s` (str): 已编码字符串 **逻辑:** 1. 按照 `convert_pairs` 的逆序还原特殊字符 2. 将 `\\\\` 还原为 `\` **示例:** ```python charDecode("hello\\x3Aworld\\x0A") # 输出: "hello:world\n" ``` --- ### `getTextDictFromLines(lines)` 从文本行列表中解析出语言键值对字典。 **参数:** - `lines` (list of str): 文件内容的每一行 **处理规则:** - 忽略空行和以 `#` 开头的注释行 - 使用正则匹配 `key : value` 结构 - 对 key 和 value 分别调用 `charDecode` 解码 **返回:** - dict: `{原始消息: 翻译文本}` --- ### `getFirstLang(lang)` 从浏览器或系统传入的逗号分隔语言优先级列表中提取首选语言。 **参数:** - `lang` (str): 如 `"zh-CN,zh;q=0.9,en-US;q=0.8"` **返回:** - str: 第一个语言代码(如 `"zh-CN"`) --- ## 核心类:`MiniI18N` 使用 `@SingletonDecorator` 实现单例模式,确保全局唯一实例。 ### 类定义 ```python @SingletonDecorator class MiniI18N: ``` --- ### 构造函数 `__init__(path, lang=None, coding='utf8')` 初始化 i18n 引擎。 **参数:** - `path` (str): 应用根路径,语言资源位于 `{path}/i18n/` - `lang` (str, optional): 默认语言(可选) - `coding` (str): 文件编码,默认 `'utf8'` **初始化行为:** - 获取系统默认语言 `locale.getdefaultlocale()[0]` - 初始化内部字典: - `langTextDict`: 存储各语言的翻译字典 - `messages`: 所有出现过的原始消息集合 - `clientLangs`: 线程级别的语言上下文(含时间戳) - 加载语言映射配置(来自 `getConfig().langMapping`) - 调用 `setupMiniI18N()` 加载所有语言文件 --- ### 方法列表 #### `setLangMapping(lang, path)` 设置语言别名映射,例如将 `"zh"` 映射到 `"zh_CN"`。 **用途:** 支持语言标签标准化。 ```python i18n.setLangMapping('zh', 'zh_CN') ``` #### `getLangMapping(lang)` 获取实际使用的语言目录名。若无映射,则返回原语言名。 #### `setTimeout(timeout=600)` 设置客户端语言上下文的有效期(单位:秒)。超时后自动清理过期记录。 #### `delClientLangs()` 清理 `clientLangs` 中超过 `timeout` 时间未访问的线程语言设置。 > 自动在 `getCurrentLang` 和 `setCurrentLang` 中触发。 #### `getLangDict(lang)` 获取指定语言的完整翻译字典。 会先通过 `getLangMapping` 解析真实语言名称。 #### `getLangText(msg, lang=None)` 根据当前或指定语言查找翻译文本。 - 若未找到对应翻译,返回原始 `msg` - 支持 bytes 输入自动解码 #### `setupMiniI18N()` 扫描 `{self.path}/i18n/` 目录下所有子目录(视为语言目录),读取其中的 `msg.txt` 文件并构建翻译字典。 **结构要求:** ``` / └── en_US/ └── msg.txt └── zh_CN/ └── msg.txt ``` 每条记录格式: ``` hello world : Hello, World! greeting : Welcome to our app. # 这是注释 error_open : Failed to open file: %s ``` #### `setCurrentLang(lang)` 为当前线程设置语言环境,并记录时间戳。 **注意:** 基于线程 ID 存储,支持多线程独立语言上下文。 #### `getCurrentLang()` 获取当前线程的语言设置。若未设置,则抛出异常(需确保已调用 `setCurrentLang`)。 --- ## 辅助函数 ### `getI18N(path=None, coding='utf8')` 获取 `MiniI18N` 单例实例的便捷入口。 **参数:** - `path`: 项目根路径(默认为 `ProgramPath()`) - `coding`: 文件编码 **返回:** - `MiniI18N` 实例 **示例:** ```python i18n = getI18N() print(i18n("hello world")) # 根据当前线程语言输出翻译 ``` --- ## 使用示例 ### 1. 准备语言文件 创建 `./i18n/en_US/msg.txt`: ``` hello : Hello, World! greeting : Welcome! ``` 创建 `./i18n/zh_CN/msg.txt`: ``` hello : 你好,世界! greeting : 欢迎! ``` ### 2. 在代码中使用 ```python from your_module import getI18N i18n = getI18N() # 设置当前线程语言 i18n.setCurrentLang('zh_CN') # 获取翻译 print(i18n('hello')) # 输出: 你好,世界! print(i18n('greeting')) # 输出: 欢迎! # 切换语言 i18n.setCurrentLang('en_US') print(i18n('hello')) # 输出: Hello, World! ``` --- ## 高级特性 ### 语言映射配置(via JSON Config) 在 `config.json` 中添加: ```json { "langMapping": { "zh": "zh_CN", "en": "en_US" } } ``` 这样即使请求 `zh`,也会自动加载 `zh_CN` 的翻译文件。 ### 线程安全设计 - 每个线程可通过 `setCurrentLang/lang` 独立设置语言 - 使用 `threading.currentThread()` 作为键存储上下文 - 定期清理过期线程状态(防止内存泄漏) --- ## 注意事项 1. **文件编码必须一致**,默认为 UTF-8。 2. 键名中不能包含未转义的 `:`、`\n`、`\r` 等特殊字符(应使用编码形式)。 3. 推荐使用英文原始消息作为 key,便于维护。 4. `msg.txt` 文件建议按功能模块分类组织。 --- ## TODO / 扩展建议 - 支持 `.po` 或 `.yaml` 格式导入 - 提供运行时动态添加翻译接口 - 添加缺失翻译日志记录机制(`missed_pt` 可扩展) - Web 场景下结合 Cookie 或 Header 自动识别语言 --- ``` > ✅ **版本信息** > 作者:AutoDoc Generator > 生成时间:2025-04-05 > 模块版本:v1.0(基于所提供代码分析)