Skip to main content

i18n Python: полное руководство по локализации

Настройте python-i18n с файлами перевода JSON или YAML, обработайте заполнители и формы множественного числа, а затем автоматизируйте перевод с помощью ИИ.

1

Установить python-i18n

python-i18n — лёгкая библиотека интернационализации для Python. Она сразу поддерживает файлы перевода JSON и YAML, вложенные ключи, интерполяцию заполнителей и формы множественного числа.

Terminal
pip install python-i18n
python-i18n по умолчанию поддерживает JSON. Для файлов перевода YAML установите необязательную зависимость командой pip install python-i18n[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'. Ключи должны сохраняться при изменении дизайна интерфейса.
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. В веб-фреймворках определяйте предпочитаемый язык пользователя из запроса и задавайте локаль до отрисовки.

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', ...) изменяет локаль глобально. На многопоточных веб-серверах, например 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 переведите файлы локалей с помощью ИИ. Попросите ИИ-помощника перевести исходный файл в своей IDE или используйте CLI i18n Agent в конвейере CI/CD.

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, пока настоящие переводы ещё не готовы.

Распространённые ошибки

Переводы возвращают исходные ключи

Причины: load_path не задан или указывает не на тот каталог, file_format не соответствует расширениям файлов либо имена файлов не соответствуют кодам локалей. Убедитесь, что i18n.load_path содержит правильный каталог, а файлы названы верно, например en.json и de.json.

Файлы YAML не загружаются

Для поддержки YAML python-i18n требуется PyYAML, но по умолчанию он не устанавливается. Выполните pip install python-i18n[YAML]. Без зависимости файлы YAML без уведомления игнорируются, а переводы возвращают заполнители отсутствующих ключей.

Поиск вложенных ключей завершается сбоем

python-i18n использует для вложенных ключей запись через точку: i18n.t('nav.home'). Если JSON содержит плоские ключи с точками в имени, например единый ключ 'nav.home', библиотека воспринимает его как вложенный путь и не находит. Используйте настоящие вложенные объекты JSON.

Изменения локали переходят между запросами

i18n.set('locale', ...) — глобальная операция. На многопоточных серверах один запрос может изменить локаль во время отрисовки другого. Передавайте именованный аргумент locale= в отдельные вызовы i18n.t() или задавайте локаль в локальном хранилище потока через промежуточное ПО.

Рекомендуемая структура файлов

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 →

Часто задаваемые вопросы