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

7.3 KiB
Raw Blame History

MiniI18N 国际化工具技术文档

# 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: 匹配以 # 开头的注释行。

    comment_re = re.compile(r'\s*#.*')
    
  • msg_re: 匹配形如 key : value 的消息条目(允许前后空格)。

    msg_re = re.compile(r'\s*([^:]*)\s*:\s*([^\s].*)')
    

编码转换表

用于对特殊字符进行编码/解码,避免配置文件解析冲突:

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 中定义的字符进行编码替换

示例:

charEncode("hello:world\n") 
# 输出: "hello\\x3Aworld\\x0A"

charDecode(s)

反向解码由 charEncode 编码的字符串。

参数:

  • s (str): 已编码字符串

逻辑:

  1. 按照 convert_pairs 的逆序还原特殊字符
  2. \\\\ 还原为 \

示例:

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 实现单例模式,确保全局唯一实例。

类定义

@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"

用途: 支持语言标签标准化。

i18n.setLangMapping('zh', 'zh_CN')

getLangMapping(lang)

获取实际使用的语言目录名。若无映射,则返回原语言名。

setTimeout(timeout=600)

设置客户端语言上下文的有效期(单位:秒)。超时后自动清理过期记录。

delClientLangs()

清理 clientLangs 中超过 timeout 时间未访问的线程语言设置。

自动在 getCurrentLangsetCurrentLang 中触发。

getLangDict(lang)

获取指定语言的完整翻译字典。

会先通过 getLangMapping 解析真实语言名称。

getLangText(msg, lang=None)

根据当前或指定语言查找翻译文本。

  • 若未找到对应翻译,返回原始 msg
  • 支持 bytes 输入自动解码

setupMiniI18N()

扫描 {self.path}/i18n/ 目录下所有子目录(视为语言目录),读取其中的 msg.txt 文件并构建翻译字典。

结构要求:

<i18n_root>/
└── 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 实例

示例:

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. 在代码中使用

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 中添加:

{
  "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(基于所提供代码分析)