Add or update translations
Add or update runtime translations when you change user-facing feedback text or command triggers. Lingchu Bot uses Python gettext and Babel to manage catalogs for Simplified Chinese (zh_CN) and English (en_US).
Runtime locale
Section titled “Runtime locale”i18n helpers live in src/plugins/nonebot_plugin_lingchu_bot/i18n. Runtime code reads the lingchu_locale NoneBot configuration key. If it is unset or empty, the default is zh_CN. Locale values are normalized after reading:
en-USbecomesen_US.en_US.UTF-8becomesen_US.- Empty values fall back to
zh_CN.
gettext uses fallback=True, so untranslated text returns the original message instead of interrupting command handling.
Catalog structure
Section titled “Catalog structure”Translation files are located at:
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.momessages.pot is the extraction template, messages.po is the editable translation source, and messages.mo is the compiled runtime file.
Update flow
Section titled “Update flow”After changing translatable strings, run:
task i18ntask i18n extracts, updates, and compiles catalogs in order. The equivalent underlying commands are maintained in Taskfile.yml:
uv run pybabel extract -F src/plugins/nonebot_plugin_lingchu_bot/i18n/babel.cfg -o src/plugins/nonebot_plugin_lingchu_bot/i18n/messages.pot src/plugins/nonebot_plugin_lingchu_botuv run pybabel update -i src/plugins/nonebot_plugin_lingchu_bot/i18n/messages.pot -d src/plugins/nonebot_plugin_lingchu_bot/i18n/locales -D messagesuv run pybabel compile -d src/plugins/nonebot_plugin_lingchu_bot/i18n/locales -D messagesBefore compiling, check that .po files do not contain lingering #, fuzzy entries.
Async path
Section titled “Async path”Async handlers should use _async, gettext_async, or ngettext_async. These helpers load catalogs in worker threads, avoiding synchronous file reads on the event loop. Startup calls warm_translation_cache to prewarm the default locale.
Synchronous _ / gettext is only suitable for synchronous paths. Do not translate defaults that may vary by locale at module import time. Read and translate them while the handler is executing.