Комментарии (1)
🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)
Ответ сгенерирован нейросетью и может содержать ошибки
Мультиязычность в Django
Django имеет встроенную систему интернационализации (i18n) для поддержки множества языков. Это мощный инструмент, но требует правильной настройки и понимания концепций.
Настройка Django для мультиязычности
# settings.py
LANGUAGE_CODE = "en-us"
LANGUAGES = [
("en", "English"),
("ru", "Russian"),
("de", "German"),
("fr", "French"),
]
LOCALE_PATHS = [
BASE_DIR / "locale", # Путь где хранятся переводы
]
INSTALLED_APPS = [
"django.contrib.auth",
"django.contrib.contenttypes",
# ...
]
MIDDLEWARE = [
"django.middleware.locale.LocaleMiddleware", # ВАЖНО: после SessionMiddleware
# ...
]
TEMPLATES = [
{
"BACKEND": "django.template.backends.django.DjangoTemplates",
"DIRS": [],
"APP_DIRS": True,
"OPTIONS": {
"context_processors": [
"django.template.context_processors.i18n",
],
},
},
]
USE_I18N = True
USE_L10N = True
Метод 1: Перевод строк в Python коде
from django.utils.translation import gettext, gettext_lazy
from django.utils.translation import ngettext, gettext as _
# Простой перевод
message = _("Hello, World!") # Будет переведено
# Ленивый перевод (для использования на уровне модели/view)
error_message = gettext_lazy("Something went wrong")
# Множественные формы
from django.utils.translation import ngettext
def display_count(count):
message = ngettext(
"You have %(count)d item",
"You have %(count)d items",
count
) % {"count": count}
return message
print(display_count(1)) # You have 1 item
print(display_count(5)) # You have 5 items
Метод 2: Перевод в шаблонах
{% load i18n %}
<!-- Простой перевод -->
<h1>{% trans "Welcome" %}</h1>
<!-- Перевод с переменными -->
<p>{% blocktrans %}Hello, {{ name }}!{% endblocktrans %}</p>
<!-- Множественные формы -->
{% blocktrans count counter=items|length %}
You have {{ counter }} item
{% plural %}
You have {{ counter }} items
{% endblocktrans %}
<!-- Переключение языка -->
{% for lang in LANGUAGES %}
<a href="/{{ lang.0 }}/">{{ lang.1 }}</a>
{% endfor %}
Метод 3: Переводы в моделях
from django.db import models
from django.utils.translation import gettext_lazy as _
class Product(models.Model):
# gettext_lazy — для того, чтобы перевод происходил при отображении
name = models.CharField(
max_length=100,
help_text=_("Product name")
)
description = models.TextField(
help_text=_("Product description")
)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
verbose_name = _("Product")
verbose_name_plural = _("Products")
def __str__(self):
return self.name
Метод 4: Перевод сообщений об ошибках
from django import forms
from django.utils.translation import gettext_lazy as _
class ContactForm(forms.Form):
name = forms.CharField(
label=_("Name"),
error_messages={
"required": _("Name is required"),
"max_length": _("Name is too long"),
}
)
email = forms.EmailField(
label=_("Email address"),
error_messages={
"required": _("Email is required"),
"invalid": _("Invalid email address"),
}
)
message = forms.CharField(
label=_("Message"),
widget=forms.Textarea,
error_messages={
"required": _("Message is required"),
}
)
def contact_form_view(request):
if request.method == "POST":
form = ContactForm(request.POST)
if form.is_valid():
# Обработка
messages.success(request, _("Message sent successfully"))
else:
messages.error(request, _("Please fix the errors below"))
else:
form = ContactForm()
return render(request, "contact.html", {"form": form})
Создание файлов переводов
# Шаг 1: Создать базовый .po файл
python manage.py makemessages -l ru
# Создаст: locale/ru/LC_MESSAGES/django.po
# Шаг 2: Отредактировать django.po
# msgid — оригинальный текст
# msgstr — переведённый текст
# Шаг 3: Скомпилировать переводы
python manage.py compilemessages
# Создаст: locale/ru/LC_MESSAGES/django.mo
# Для нескольких языков
python manage.py makemessages -l ru -l de -l fr
Пример файла перевода (locale/ru/LC_MESSAGES/django.po):
msgid ""
msgstr ""
"Content-Type: text/plain; charset=UTF-8\n"
"Language: ru\n"
msgid "Hello, World!"
msgstr "Привет, мир!"
msgid "You have %(count)d item"
msgid_plural "You have %(count)d items"
msgstr[0] "У вас %(count)d товар"
msgstr[1] "У вас %(count)d товара"
msgstr[2] "У вас %(count)d товаров"
Переключение языка
from django.views.i18n import set_language
from django.shortcuts import redirect
from django.utils.translation import activate
# Способ 1: Через встроенное представление Django
urlpatterns = [
path("i18n/", include("django.conf.urls.i18n")),
]
# Способ 2: Кастомное представление
def change_language(request, language):
activate(language) # Активировать язык
response = redirect(request.META.get("HTTP_REFERER", "/"))
response.set_cookie("django_language", language) # Сохранить в cookie
return response
# Способ 3: Определить по URL
# urls.py
urlpatterns = [
path("en/", include("myapp.urls")),
path("ru/", include("myapp.urls")),
]
# middleware.py
class LanguageMiddleware:
def __init__(self, get_response):
self.get_response = get_response
def __call__(self, request):
lang = request.path.split("/")[1] # en или ru
if lang in ["en", "ru"]:
activate(lang)
response = self.get_response(request)
return response
API для мультиязычности
from rest_framework import viewsets, serializers
from django.utils.translation import activate, get_language
class ProductSerializer(serializers.ModelSerializer):
class Meta:
model = Product
fields = ["id", "name", "description"]
class ProductViewSet(viewsets.ModelViewSet):
queryset = Product.objects.all()
serializer_class = ProductSerializer
def get_serializer_context(self):
context = super().get_serializer_context()
# Активировать язык из параметра запроса
lang = self.request.query_params.get("lang", "en")
activate(lang)
context["language"] = lang
return context
# Использование
# GET /api/products/?lang=ru
# GET /api/products/?lang=en
Хранение переводов в БД (для динамических данных)
from django.db import models
from parler.models import TranslatableModel, TranslatedFields
class Article(TranslatableModel):
# Используется пакет django-parler
translations = TranslatedFields(
title=models.CharField(max_length=200),
content=models.TextField(),
)
created_at = models.DateTimeField(auto_now_add=True)
def __str__(self):
return self.title
# Использование
article = Article.objects.language("ru").get(id=1)
print(article.title) # На русском
article.translate("en")
print(article.title) # На английском
Юнит-тесты для переводов
from django.test import TestCase, override_settings
from django.utils.translation import activate, gettext as _
class TranslationTestCase(TestCase):
@override_settings(LANGUAGE_CODE="en")
def test_english_translation(self):
activate("en")
# Важно: убедись, что .mo файл скомпилирован
self.assertEqual(_("Hello"), "Hello")
@override_settings(LANGUAGE_CODE="ru")
def test_russian_translation(self):
activate("ru")
self.assertEqual(_("Hello"), "Привет")
def test_language_switching(self):
activate("en")
en_text = _("Welcome")
activate("ru")
ru_text = _("Welcome")
self.assertNotEqual(en_text, ru_text)
Best Practices
- Используй gettext_lazy для моделей и форм — переводится при отображении
- Используй gettext для коммуникаций — письма, логи
- Всегда компилируй переводы —
makemessagesиcompilemessages - Структурируй переводы — не смешивай языки в одном файле
- Тестируй переводы — проверяй все языки
- Используй django-parler для контента в БД — для пользовательского контента
- Форматируй даты по локали — используй date filter в шаблонах
- Документируй ключи переводов — что означает каждый ключ
Мультиязычность требует внимания к деталям, но Django предоставляет все инструменты для реализации.