
Django i18n: посібник з інтернаціоналізації та перекладу
Від settings.py до розгортання у виробничому середовищі: налаштуйте систему перекладу Django, створюйте файли PO, опрацьовуйте форми множини й автоматизуйте переклад за допомогою ШІ.
Установити компоненти та видобути рядки
Фреймворк i18n вбудований у Django — його потрібно лише ввімкнути. Установіть django-locale-chain для розумних резервних локалей, а потім використовуйте makemessages, щоб видобути придатні до перекладу рядки з коду Python і шаблонів у файли PO.
pip install django-locale-chain# Extract all translatable strings from Python and template files
python manage.py makemessages -l de -l ja -l es -l fr
# After translating .po files, compile to .mo (binary)
python manage.py compilemessages
# Project structure after running makemessages:
# locale/
# ├── de/
# │ └── LC_MESSAGES/
# │ ├── django.po <-- translate this
# │ └── django.mo <-- compiled (auto-generated)
# ├── ja/
# │ └── LC_MESSAGES/
# │ ├── django.po
# │ └── django.mo
# └── es/
# └── LC_MESSAGES/
# ├── django.po
# └── django.moНалаштувати параметри та проміжне програмне забезпечення
Увімкніть інтернаціоналізацію в settings.py: задайте USE_I18N = True, визначте список підтримуваних LANGUAGES і додайте LocaleMiddleware до послідовності MIDDLEWARE. LocaleMiddleware визначає мову користувача за префіксом URL-адреси, сеансом, файлами cookie або заголовком Accept-Language.
# settings.py
from django.utils.translation import gettext_lazy as _
# Default language
LANGUAGE_CODE = 'en'
# Enable i18n
USE_I18N = True
USE_L10N = True
# Languages your site supports
LANGUAGES = [
('en', _('English')),
('de', _('German')),
('ja', _('Japanese')),
('es', _('Spanish')),
('fr', _('French')),
('pt-br', _('Brazilian Portuguese')),
]
# Where Django looks for .po files
LOCALE_PATHS = [
BASE_DIR / 'locale',
]
MIDDLEWARE = [
'django.middleware.security.SecurityMiddleware',
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware', # <-- enables i18n
'locale_chain.middleware.LocaleChainMiddleware', # <-- smart fallbacks
'django.middleware.common.CommonMiddleware',
'django.middleware.csrf.CsrfViewMiddleware',
'django.contrib.auth.middleware.AuthenticationMiddleware',
'django.contrib.messages.middleware.MessageMiddleware',
'django.middleware.clickjacking.XFrameOptionsMiddleware',
]Інтернаціоналізація URL-адрес
Використовуйте i18n_patterns(), щоб автоматично додавати до URL-адрес префікс із кодом активної мови. Так кожна мова отримує власний простір URL-адрес (/en/about/, /de/about/), що покращує SEO й дає користувачам змогу ділитися посиланнями для певної мови.
# urls.py
from django.conf.urls.i18n import i18n_patterns
from django.urls import path, include
urlpatterns = [
# Non-localized URLs (API, admin, etc.)
path('api/', include('api.urls')),
]
urlpatterns += i18n_patterns(
# These get prefixed with the language code: /en/about/, /de/about/
path('', include('myapp.urls')),
path('admin/', admin.site.urls),
prefix_default_language=False, # Skip prefix for default language
)Позначити рядки для перекладу
Django надає дві основні функції перекладу: gettext() (псевдонім _()) для рядків, що обчислюються під час запиту, і gettext_lazy() для рядків, що обчислюються під час імпорту. У шаблонах використовуйте теги {% trans %} і {% blocktrans %}.
У представленнях (код Python)
from django.utils.translation import gettext as _
from django.utils.translation import ngettext
from django.http import HttpResponse
def greeting_view(request):
# Simple translation
welcome = _("Welcome to our site")
# Translation with variables (Python string formatting)
user_greeting = _("Hello, %(name)s!") % {"name": request.user.username}
# Plurals
count = request.user.order_set.count()
order_text = ngettext(
"You have %(count)d order.",
"You have %(count)d orders.",
count,
) % {"count": count}
return HttpResponse(f"{welcome}<br>{user_greeting}<br>{order_text}")У шаблонах
{# Load the i18n template tags #}
{% load i18n %}
{# Simple translation #}
<h1>{% trans "Welcome to our site" %}</h1>
{# Translation with variables #}
{% blocktrans with name=user.username %}
Hello, {{ name }}!
{% endblocktrans %}
{# Plurals in templates #}
{% blocktrans count count=order_count %}
You have {{ count }} order.
{% plural %}
You have {{ count }} orders.
{% endblocktrans %}
{# Mark strings as translatable but don't output them (for attributes, etc.) #}
{% trans "Submit" as submit_label %}
<button type="submit">{{ submit_label }}</button>У моделях і формах
from django.db import models
from django.utils.translation import gettext_lazy as _
class Product(models.Model):
name = models.CharField(_("product name"), max_length=200)
description = models.TextField(_("description"), blank=True)
class Meta:
verbose_name = _("product")
verbose_name_plural = _("products")
def __str__(self):
return self.name
# IMPORTANT: Use gettext_lazy (_) for anything evaluated at import time:
# - Model field labels, verbose_name, help_text
# - Form field labels
# - Class-level attributes
# Use gettext for anything evaluated at request time:
# - View functions, template tagsФормат файлів PO
Після запуску makemessages Django створює для кожної мови файли .po (Portable Object). Вони містять пари msgid/msgstr. Перекладіть значення msgstr, а потім запустіть compilemessages, щоб створити двійкові файли .mo, які Django читає під час виконання.
# locale/de/LC_MESSAGES/django.po
msgid "Welcome to our site"
msgstr "Willkommen auf unserer Seite"
msgid "Hello, %(name)s!"
msgstr "Hallo, %(name)s!"
#, python-format
msgid "You have %(count)d order."
msgid_plural "You have %(count)d orders."
msgstr[0] "Sie haben %(count)d Bestellung."
msgstr[1] "Sie haben %(count)d Bestellungen."
msgid "product name"
msgstr "Produktname"
msgid "description"
msgstr "Beschreibung"
msgid "product"
msgstr "Produkt"
msgid "products"
msgstr "Produkte"
msgid "Submit"
msgstr "Absenden"Опрацювати форми множини та змінні
Django використовує ngettext() для форм множини відповідно до правил GNU gettext. Кожна мова визначає кількість форм множини та формулу для вибору правильної форми. У файлах PO це оголошується в заголовку Plural-Forms.
# English: 2 forms (singular, plural)
msgid "%(count)d item"
msgid_plural "%(count)d items"
msgstr[0] "%(count)d item"
msgstr[1] "%(count)d items"
# German: 2 forms (singular, plural)
msgstr[0] "%(count)d Artikel"
msgstr[1] "%(count)d Artikel"
# Russian: 3 forms (one, few, many)
msgstr[0] "%(count)d товар" # 1 item
msgstr[1] "%(count)d товара" # 2-4 items
msgstr[2] "%(count)d товаров" # 5+ items
# Arabic: 6 forms (zero, one, two, few, many, other)
msgstr[0] "لا عناصر" # 0
msgstr[1] "عنصر واحد" # 1
msgstr[2] "عنصران" # 2
msgstr[3] "%(count)d عناصر" # 3-10
msgstr[4] "%(count)d عنصرًا" # 11-99
msgstr[5] "%(count)d عنصر" # 100+
# Japanese: 1 form (no plural distinction)
msgstr[0] "%(count)d個のアイテム"
# In Python code, always use ngettext:
from django.utils.translation import ngettext
msg = ngettext(
"%(count)d item",
"%(count)d items",
count,
) % {"count": count}Автоматизувати контроль якості перекладу
Поширені помилки
Плутанина між gettext() і gettext_lazy()
Не запущено compilemessages
LOCALE_PATHS не налаштовано
В URL-адресах відсутній i18n_patterns
Розумні резервні локалі з django-locale-chain
Система перекладу Django одразу переходить до LANGUAGE_CODE, якщо регіональний варіант відсутній. Користувач із локаллю pt-BR бачить англійський текст, навіть якщо доступні переклади pt-PT. django-locale-chain усуває цю проблему, установлюючи резервні ланцюжки gettext: для pt-BR система спочатку шукає переклад pt-PT, потім pt і лише після цього переходить до Вашої стандартної мови.
# settings.py -- Smart fallback with django-locale-chain
# pip install django-locale-chain
MIDDLEWARE = [
# ...
'django.middleware.locale.LocaleMiddleware',
'locale_chain.middleware.LocaleChainMiddleware', # after LocaleMiddleware
# ...
]
# That's it! 75 built-in fallback chains are now active:
# pt-BR user → tries pt-PT → tries pt → falls back to LANGUAGE_CODE
# es-MX user → tries es-419 → tries es → falls back to LANGUAGE_CODE
# fr-CA user → tries fr → falls back to LANGUAGE_CODE
# Optional: customize specific chains
LOCALE_FALLBACK_CHAINS = {
"pt-BR": ["pt-PT", "pt"],
"es-MX": ["es-419", "es"],
"fr-CA": ["fr"],
}
# Or configure programmatically in AppConfig.ready():
from locale_chain import configure
class MyAppConfig(AppConfig):
name = "myapp"
def ready(self):
configure(overrides={"zh-Hant-HK": ["zh-Hant-TW", "zh-Hant"]})Рекомендована структура проєкту
myproject/
├── myproject/
│ ├── settings.py # i18n config, MIDDLEWARE, LANGUAGES
│ ├── urls.py # i18n_patterns for URL prefixing
│ └── wsgi.py
├── myapp/
│ ├── models.py # gettext_lazy for field labels
│ ├── views.py # gettext for request-time strings
│ └── templates/
│ └── myapp/
│ └── index.html # {% load i18n %}, {% trans %}, {% blocktrans %}
├── locale/ # Created by makemessages
│ ├── de/
│ │ └── LC_MESSAGES/
│ │ ├── django.po # German translations
│ │ └── django.mo # Compiled binary
│ ├── ja/
│ │ └── LC_MESSAGES/
│ │ ├── django.po
│ │ └── django.mo
│ └── es/
│ └── LC_MESSAGES/
│ ├── django.po
│ └── django.mo
├── manage.py
└── requirements.txtТакож перекласти:
Спробуйте i18n Agent зараз
Перетягніть сюди файл для перекладу
JSON, YAML, PO, XML, CSV, Markdown, Properties
або натисніть, щоб вибрати
Цільові мови
Резервні локалі з django-locale-chain
Коли в регіональній локалі на кшталт pt-BR відсутній ключ перекладу, Django одразу переходить до мови шаблону, не перевіряючи спершу батьківську локаль pt.
pip install django-locale-chain# settings.py
LOCALE_CHAINS = {
'pt-BR': ['pt', 'es', 'en'],
'zh-Hant-HK': ['zh-Hant', 'zh', 'en'],
}
MIDDLEWARE = [
...
'django_locale_chain.middleware.LocaleChainMiddleware',
...
]Перегляньте наш посібник із резервних локалей, щоб ознайомитися з повним переліком підтримуваних фреймворків і 75 вбудованими ланцюжками. Learn more →