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 →

常見問題