Lingchu Bot 文档现已上线 — 快来看看吧!
Lingchu Bot

运行时国际化

gettext/Babel 目录、运行时 locale 选择与 locale-exclusive 命令触发词。

运行时国际化

Lingchu Bot 使用 Python gettext 和 Babel 管理运行时反馈文本和命令触发词。本页聚焦运行时部分:目录结构、locale 选择与 locale-exclusive 触发词规则。开发态的提取/更新/编译工作流,参见国际化

目录结构

翻译文件位于 src/plugins/nonebot_plugin_lingchu_bot/i18n

src/plugins/nonebot_plugin_lingchu_bot/i18n/
├── babel.cfg
├── messages.pot
└── locales/
    ├── en_US/LC_MESSAGES/messages.po
    ├── en_US/LC_MESSAGES/messages.mo
    ├── zh_CN/LC_MESSAGES/messages.po
    └── zh_CN/LC_MESSAGES/messages.mo
文件作用
babel.cfg提取配置——[python: **.py],UTF-8 编码
messages.pot提取模板,由 pybabel extract 重新生成
messages.po按 locale 的可编辑翻译源
messages.mo编译后的二进制 catalog,运行时由 gettext 加载

gettext domain 为 messagesi18n/__init__.py 中的常量 DOMAIN),locales 目录由 Path(__file__).parent / "locales" 解析(常量 LOCALES_DIR)。当前仅发布 zh_CNen_US

运行时 locale 选择

运行时代码读取 lingchu_locale NoneBot 配置键。.env 中推荐的项目专用键为 LINGCHU_LOCALE

LINGCHU_LOCALE=zh_CN

i18n/__init__.py 中的 get_configured_locale() 是唯一入口。它从 _read_configured_locale()(一个 lru_cache 支持的读取器,调用 get_driver().config)读取缓存的值,规范化后返回。normalize_locale() 处理三种情况:

  • en-US 变为 en_US(连字符 → 下划线)。
  • en_US.UTF-8 变为 en_US(剥离编码后缀)。
  • 空或未设置的值回退到代码内默认值。

代码内默认值为 i18n/__init__.py 中的 DEFAULT_LOCALE = "en_US"。发布的 .env.example 设置 LINGCHU_LOCALE=zh_CN 作为新部署的推荐默认值,因此除非覆盖,大多数安装运行在 zh_CN

get_translation()fallback=True 打开 catalog,因此未翻译的消息会返回原始字符串,而不会抛出 MissingMessageError 中断命令处理。

Locale-exclusive 命令触发词

群命令触发词是 locale-exclusive 的。同一个 matcher 要么注册中文触发词集合,要么注册英文触发词集合,不会同时注册。选择由 handle/qq/commands/triggers.py 中的 _is_english_locale() 驱动:

def _is_english_locale(locale: str | None = None) -> bool:
    configured_locale = get_configured_locale() if locale is None else locale
    return normalize_locale(configured_locale).lower().startswith("en")

每个 CommandTrigger 携带并行的 chinese / english 主触发词与 chinese_aliases / english_aliases 别名集合。primary_for(locale)aliases_for(locale) 仅返回当前激活语言的值,因此非激活语言的别名不会进入 matcher。

例如,menu 命令根据配置的 locale 注册 菜单(别名 帮助功能功能列表指令命令列表)或 menu(别名 helpcommands)。

build_command_triggers()_DEFAULT_COMMAND_TRIGGERS 之上应用来自 command_trigger_overrides 的运行时覆盖,然后调用 _validate_no_duplicates() 确保跨两种语言没有任何触发词字符串被两个 command_key 共同拥有。重复会在导入时抛出 ValueError

_() 与异步翻译辅助

该模块同时暴露同步与异步翻译辅助:

辅助函数用途
_ / gettext同步单数翻译
ngettext同步复数翻译
_async / gettext_async异步单数翻译(在 worker 线程加载 catalog)
ngettext_async异步复数翻译
get_translation(locale)缓存的 NullTranslations 对象
get_translation_async(locale)同上,但不在事件循环上加载
warm_translation_cache(locales)启动期间预热 catalog

异步处理器应使用 _asyncgettext_asyncngettext_async,避免同步文件读取阻塞 NoneBot 事件循环。启动会调用 warm_translation_cache()(见 start/startup.py),在任何处理器运行前预热配置的 locale 与默认 locale。

不要在导入时翻译

同步 _ / gettext 仅适用于同步路径。不要在模块导入时翻译可能随 locale 变化的默认值——应在处理器执行时读取并翻译。

开发工作流

修改可翻译字符串后,运行:

task i18n

task i18n 按顺序提取、更新并编译 catalog。完整的底层 pybabel 命令与开发态工作流,参见国际化

参见

用户可见的反馈文本行为与触发词语言切换,参见命令故障排查

最后更新于

本页目录