Skip to main content

Python i18n:完整本地化指南

使用 JSON 或 YAML 翻译文件设置 python-i18n、处理占位符和复数,再通过 AI 自动翻译。

1

安装 python-i18n

python-i18n 是一个轻量级 Python 国际化库,开箱即用地支持 JSON 和 YAML 翻译文件、嵌套键、占位符插值和复数。

Terminal
pip install python-i18n
python-i18n 默认支持 JSON。对于 YAML 翻译文件,请使用 pip install python-i18n[YAML] 安装可选的 YAML 依赖项,它会添加 PyYAML。
Terminal
# To use YAML translation files instead of JSON:
pip install python-i18n[YAML]
2

配置翻译

设置文件格式、添加翻译文件路径,并配置默认和回退区域设置。在调用任何翻译之前,请在应用入口点导入此配置。

i18n_config.py
import i18n

# Set the file format (json or yaml)
i18n.set("file_format", "json")

# Add the directory containing your translation files
i18n.load_path.append("translations/")

# Set the default locale
i18n.set("locale", "en")

# Set the fallback locale (used when a key is missing)
i18n.set("fallback", "en")

# Enable/disable error on missing translations
i18n.set("error_on_missing_translation", False)
load_path 必须指向包含翻译文件的目录,而不是某个具体文件。如果翻译返回原始键,请检查 load_path 是否正确,以及文件名是否与区域设置代码匹配(例如 en.json、de.json)。
3

创建翻译文件

以 JSON 或 YAML 格式为每种语言创建一个文件。使用嵌套键按功能或页面组织字符串。将源语言(通常是英语)作为唯一事实来源。

translations/en.json
// translations/en.json
{
  "greeting": "Hello!",
  "welcome": "Welcome to our application",
  "nav": {
    "home": "Home",
    "about": "About",
    "settings": "Settings"
  },
  "cart": {
    "item_count": "%{count} item(s) in your cart"
  }
}

// translations/de.json
{
  "greeting": "Hallo!",
  "welcome": "Willkommen in unserer Anwendung",
  "nav": {
    "home": "Startseite",
    "about": "Über uns",
    "settings": "Einstellungen"
  },
  "cart": {
    "item_count": "%{count} Artikel in Ihrem Warenkorb"
  }
}
按键描述的内容命名,而不是按其出现位置命名:'cart.item_count' 优于 'homepage_cart_label'。键应能在 UI 重新设计后继续使用。
4

在代码中使用翻译

使用以点分隔的键路径调用 i18n.t(),查找翻译字符串。您可在每次调用时覆盖区域设置,而无需更改全局设置。

app.py
import i18n

# Simple translation
print(i18n.t("greeting"))          # "Hello!"
print(i18n.t("nav.home"))          # "Home"
print(i18n.t("nav.about"))         # "About"

# Translation with a specific locale
print(i18n.t("greeting", locale="de"))   # "Hallo!"
print(i18n.t("nav.home", locale="ja"))   # "ホーム"

# Missing key returns a placeholder
print(i18n.t("missing.key"))       # "Missing.Key"
嵌套键使用点号表示法:i18n.t('nav.home')。如果 JSON 键包含字面点号,python-i18n 会将其解释为嵌套分隔符。请避免在键名中使用点号。
5

占位符和复数

python-i18n 支持使用 %{name} 语法进行占位符插值,并使用 'zero'、'one' 和 'many' 子键处理基本复数。将关键字参数传给 i18n.t(),即可使用这两项功能。

Placeholders
# translations/en.json
# {
#   "welcome_user": "Welcome, %{name}!",
#   "order_status": "Order #%{order_id}: %{status}",
#   "file_size": "File size: %{size} %{unit}"
# }

import i18n

# Single placeholder
print(i18n.t("welcome_user", name="Alice"))
# "Welcome, Alice!"

# Multiple placeholders
print(i18n.t("order_status", order_id=12345, status="shipped"))
# "Order #12345: shipped"

# Reusable with different values
print(i18n.t("file_size", size=2.5, unit="MB"))
# "File size: 2.5 MB"

print(i18n.t("file_size", size=800, unit="KB"))
# "File size: 800 KB"
Pluralization
# translations/en.json
# {
#   "inbox": {
#     "zero": "No messages",
#     "one": "1 message",
#     "many": "%{count} messages"
#   }
# }

import i18n

print(i18n.t("inbox", count=0))    # "No messages"
print(i18n.t("inbox", count=1))    # "1 message"
print(i18n.t("inbox", count=42))   # "42 messages"
python-i18n 的复数处理使用三个类别:zero、one 和 many。这涵盖英语和许多其他语言,但不支持完整的 CLDR 复数规则(few、two、other)。对于阿拉伯语、俄语或波兰语等具有复杂复数形式的语言,您可能需要手动处理边界情况,或使用更高级的库。
6

在运行时切换区域设置

通过 i18n.set('locale', code) 全局切换当前区域设置,或使用 locale 关键字参数在每次调用时覆盖。在 Web 框架中,请根据请求检测用户的首选语言,并在呈现前设置区域设置。

Locale switching
import i18n

# Set locale globally
i18n.set("locale", "de")
print(i18n.t("greeting"))           # "Hallo!"

# Switch to Japanese
i18n.set("locale", "ja")
print(i18n.t("greeting"))           # "こんにちは!"

# Override per-call without changing global locale
i18n.set("locale", "en")
print(i18n.t("greeting"))           # "Hello!"
print(i18n.t("greeting", locale="de"))  # "Hallo!"
app.py
from flask import Flask, request, g
import i18n

app = Flask(__name__)

i18n.set("file_format", "json")
i18n.load_path.append("translations/")

SUPPORTED_LOCALES = ["en", "de", "ja", "es", "fr"]

@app.before_request
def set_locale():
    # Check URL parameter, cookie, then Accept-Language header
    locale = request.args.get("lang")
    if not locale:
        locale = request.cookies.get("locale")
    if not locale:
        locale = request.accept_languages.best_match(SUPPORTED_LOCALES)
    g.locale = locale or "en"
    i18n.set("locale", g.locale)

@app.route("/")
def index():
    return i18n.t("welcome")
i18n.set('locale', ...) 会全局更改区域设置。在多线程 Web 服务器(带 worker 的 gunicorn、Django)中,这可能导致竞态条件:一个请求更改区域设置时,另一个请求还在呈现。请使用每次调用的区域设置覆盖或线程本地存储来避免此问题。
7

使用 python-i18n-locale-chain 实现智能区域设置回退

默认情况下,python-i18n 仅支持一个回退区域设置。当 pt-BR 用户没有 pt-BR 翻译时,该库会直接跳到英语回退,忽略完全可用的 pt-PT 翻译。python-i18n-locale-chain 通过涵盖 75 种区域设置变体的可配置回退链解决此问题。

python-i18n-locale-chain 是一个免费开源软件包。只需调用一个函数,即可启用 75 条内置回退链,涵盖中文、葡萄牙语、西班牙语、法语、德语、意大利语、荷兰语、英语、阿拉伯语、挪威语和马来语的地区变体。
Terminal
pip install python-i18n-locale-chain
i18n_config.py
from locale_chain import configure
import i18n

i18n.set("file_format", "json")
i18n.load_path.append("translations/")

# Activate smart fallback chains (75 built-in chains)
configure()

# Now pt-BR falls back to pt-PT -> pt -> en (instead of just en)
result = i18n.t("greeting", locale="pt-BR")

# es-MX falls back to es-419 -> es -> en
result = i18n.t("greeting", locale="es-MX")

# zh-Hant-HK falls back to zh-Hant-TW -> zh-Hant -> en
result = i18n.t("greeting", locale="zh-Hant-HK")
Advanced configuration
from locale_chain import configure, reset

# Override specific chains
configure(overrides={
    "pt-BR": ["pt"],         # Skip pt-PT, go straight to pt
    "ja-JP": ["ja"],         # Add a new chain
})

# Full custom map (no defaults)
configure(
    fallbacks={"pt-BR": ["pt-PT"]},
    merge_defaults=False
)

# Use German as final fallback instead of English
configure(default_locale="de")

# Restore original i18n.t() behaviour
reset()
最值得测试的回退链:pt-BR -> pt-PT -> pt -> en(葡萄牙语)、es-MX -> es-419 -> es -> en(西班牙语)、zh-Hant-HK -> zh-Hant-TW -> zh-Hant -> en(繁体中文)。这些链涵盖最常见的地区回退场景。
8

自动翻译

完成 i18n 设置后,使用 AI 翻译本地化文件。在 IDE 中让 AI 助手翻译源文件,或在 CI/CD 管线中使用 i18n Agent CLI。

Terminal
# In your IDE, ask your AI assistant:
> Translate translations/en.json to German, Japanese, and Spanish

translations/de.json created (1.2s)
translations/ja.json created (1.5s)
translations/es.json created (1.1s)

# Or use the CLI in CI/CD:
npx i18n-agent translate translations/en.json --lang de,ja,es
采用渐进式翻译。向源文件添加新键时,只翻译差异内容,不要重新生成所有文件。这样可保留经人工审核的翻译。

自动保证翻译质量

使用 i18n-validate 在发布前发现缺失键和损坏的占位符。真实译文完成前,可使用 i18n-pseudo 生成伪译文来测试 UI。

常见问题

翻译返回原始键

可能原因:未设置 load_path 或它指向错误目录、file_format 与文件扩展名不匹配,或文件名与区域设置代码不匹配。请验证 i18n.load_path 包含正确目录,并确认文件命名正确(例如 en.json、de.json)。

YAML 文件未加载

python-i18n 需要 PyYAML 才能支持 YAML,但默认不会安装。请使用 pip install python-i18n[YAML] 安装。缺少它时,YAML 文件会被静默忽略,翻译会返回缺失键占位符。

嵌套键查找失败

python-i18n 使用点号表示法表示嵌套键:i18n.t('nav.home')。如果 JSON 使用名称中带点号的扁平键(例如将 'nav.home' 作为单个键),该库会将其解释为嵌套查找并失败。请改用真正的嵌套 JSON 对象。

区域设置更改泄漏到其他请求

i18n.set('locale', ...) 是全局操作。在多线程服务器中,一个请求可在另一个请求呈现时更改区域设置。请对每个 i18n.t() 调用使用 locale= 关键字参数,或通过中间件在线程本地存储中设置区域设置。

推荐的文件结构

Project Structure
my-python-app/
├── translations/
│   ├── en.json           # Source language (JSON)
│   ├── de.json           # German
│   ├── ja.json           # Japanese
│   ├── es.json           # Spanish
│   └── pt-BR.json        # Brazilian Portuguese
├── app.py                # Application entry point
├── i18n_config.py        # i18n setup and configuration
├── requirements.txt      # pip dependencies
└── pyproject.toml        # Project metadata

# Or with YAML files:
my-python-app/
├── translations/
│   ├── en.yml
│   ├── de.yml
│   └── ja.yml
├── app.py
└── ...

立即试用 i18n Agent

将翻译文件拖放到此处

JSON, YAML, PO, XML, CSV, Markdown, Properties

或点击选择文件

目标语言

无需注册即时估价

使用 python-i18n-locale-chain 实现区域设置回退

当 es-419 等地区区域设置缺少翻译键时,python-i18n 会直接跳到默认区域设置,而不会先检查父级区域设置 es。

Terminal
pip install python-i18n-locale-chain
Configuration
from i18n_locale_chain import configure_chain

configure_chain('{')
    'es': ['en', 'ru'],
    'pt-BR': ['pt', 'en'],
    'zh-Hant-HK': ['zh-Hant', 'zh', 'en'],
'}')

# Usage: t('greeting', locale='es') — falls back through chain

查看语言回退指南,了解受支持框架的完整列表和 75 条内置回退链。 Learn more →

常见问题