Skip to main content

Django i18n: internacionalizācijas un tulkošanas ceļvedis

No settings.py līdz produkcijas videi: konfigurējiet Django tulkošanas sistēmu, rakstiet PO failus, apstrādājiet daudzskaitli un automatizējiet tulkošanu ar MI.

1

Instalēt un izvilkt virknes

Django i18n sistēma ir iebūvēta — tā tikai jāiespējo. Instalējiet django-locale-chain viedām lokalizāciju atkāpšanās ķēdēm, pēc tam ar makemessages izvelciet tulkojamas virknes no Python koda un veidnēm PO failos.

Django pamatā izmanto GNU gettext. Komanda makemessages skenē gettext izsaukumus un veidņu tagus kodā, pēc tam ģenerē .po failus. Pēc tulkošanas compilemessages pārveido tos bināros .mo failos ātrai uzmeklēšanai izpildlaikā.
Terminal
pip install django-locale-chain
Terminal
# 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
2

Konfigurēt iestatījumus un starpprogrammatūru

Iespējojiet internacionalizāciju settings.py, iestatot USE_I18N = True, definējot atbalstīto LANGUAGES sarakstu un pievienojot LocaleMiddleware MIDDLEWARE stekam. LocaleMiddleware nosaka lietotāja valodu no URL prefiksa, sesijas, sīkfailiem vai galvenes Accept-Language.

settings.py
# 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',
]
LocaleMiddleware jāatrodas pēc SessionMiddleware (tā nolasa sesiju) un pirms CommonMiddleware. Ja tā ievietota nepareizā secībā, valodas noteikšana klusām neizdodas un visi lietotāji redz noklusējuma LANGUAGE_CODE.

URL internacionalizācija

Izmantojiet i18n_patterns(), lai URL automātiski pievienotu aktīvās valodas koda prefiksu. Tas katrai valodai piešķir savu URL nosaukumvietu (/en/about/, /de/about/), kas ir labāk SEO un ļauj kopīgot valodai specifiskas saites.

urls.py
# 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
)
3

Atzīmēt tulkojamas virknes

Django nodrošina divas galvenās tulkošanas funkcijas: gettext() (saīsinājums _()) virknēm, kas tiek novērtētas pieprasījuma laikā, un gettext_lazy() virknēm, kas tiek novērtētas importēšanas laikā. Veidnēs izmantojiet tagus {% trans %} un {% blocktrans %}.

Skatos (Python kodā)

views.py
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}")

Veidnēs

templates/myapp/index.html
{# 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>

Modeļos un formās

models.py
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
Izmantojot gettext() gettext_lazy() vietā modeļu laukos, veidlapu etiķetēs vai klases līmeņa atribūtos, virknes tiek tulkotas vienreiz importēšanas laikā (servera palaišanas brīdī), nevis katram pieprasījumam. Tulkojums tiek iesaldēts valodā, kas bija aktīva importēšanas laikā — parasti noklusējuma LANGUAGE_CODE.

PO faila formāts

Pēc makemessages palaišanas Django katrai valodai ģenerē .po (Portable Object) failus. Tajos ir msgid un msgstr pāri. Iztulkojiet msgstr vērtības, pēc tam palaidiet compilemessages, lai ģenerētu bināros .mo failus, ko Django nolasa izpildlaikā.

locale/de/LC_MESSAGES/django.po
# 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"
4

Apstrādāt daudzskaitli un mainīgos

Django daudzskaitlim izmanto ngettext(), kas seko GNU gettext daudzskaitļa kārtulām. Katra valoda definē, cik daudzskaitļa formu tai ir un pēc kādas formulas izvēlas pareizo formu. PO faili to norāda galvenē Plural-Forms.

Plural forms by language
# 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 izsaukumos nekad neizmantojiet Python f virknes vai .format(). Tulkojumu izvilcējs tās nevar parsēt. Izmantojiet vecā stila %() formatēšanu: _('Hello, %(name)s!') % {'name': name}. Tas arī nodrošina, ka tulkotāji savos PO redaktoros redz mainīgo vietturus.

Automatizēt tulkojumu kvalitāti

Ar i18n-validate pirms izlaišanas atrodiet trūkstošās atslēgas un bojātos vietturus. Kamēr īstie tulkojumi vēl nav gatavi, pārbaudiet UI ar i18n-pseudo pseidotulkojumiem.

Biežākās kļūdas

gettext() un gettext_lazy() sajaukšana

Modeļu laukiem, veidlapu etiķetēm un jebkuram klases līmeņa atribūtam, ko novērtē importēšanas laikā, izmantojiet gettext_lazy() (importētu kā _). Skatu funkcijām un pieprasījuma laikā izpildāmam kodam izmantojiet gettext(). Tos sajaucot, tulkojumi tiek iesaldēti servera palaišanas valodā.

Aizmirsts palaist compilemessages

Django nolasa kompilētus .mo failus, nevis .po failus. Ja rediģējat .po failu, bet nepalaižat 'python manage.py compilemessages', izmaiņas neparādīsies. Pievienojiet compilemessages izvietošanas skriptam.

LOCALE_PATHS nav konfigurēts

Ja LOCALE_PATHS ir tukšs vai norāda nepareizu direktoriju, makemessages izveido .po failus nepareizajā vietā un Django tos neatrod izpildlaikā. Vienmēr iestatiet LOCALE_PATHS = [BASE_DIR / 'locale'] un pārbaudiet, vai direktorija pastāv.

URL trūkst i18n_patterns

Bez i18n_patterns() URL nav valodas prefiksa, tādēļ Django valodu nosaka tikai pēc sīkfailiem vai galvenēm. Tas kaitē SEO (nav valodām specifisku URL) un neļauj pārslēgt valodu ar URL. Ietveriet lietotājiem paredzētos URL modeļus ar i18n_patterns().

Viedas lokalizāciju atkāpšanās ķēdes ar django-locale-chain

Ja trūkst reģionālā varianta, Django tulkošanas sistēma uzreiz atkāpjas uz LANGUAGE_CODE. pt-BR lietotājs redz angļu valodu, pat ja jums ir pt-PT tulkojumi. django-locale-chain to novērš, uzstādot gettext atkāpšanās ķēdes: pirms atkāpšanās uz noklusējuma valodu pt-BR izmēģina pt-PT, tad pt.

settings.py
# 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"]})

Ieteicamā projekta struktūra

Project Structure
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

Izmēģiniet i18n Agent tūlīt

Nometiet tulkošanas failu šeit

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

vai noklikšķiniet, lai izvēlētos

Mērķa valodas

Reģistrācija nav vajadzīgaTūlītēja tāme

Lokalizācijas atkāpšanās ar django-locale-chain

Ja reģionālajā lokalizācijā, piemēram, pt-BR, trūkst tulkojuma atslēgas, Django uzreiz pāriet uz veidnes valodu, nevis vispirms pārbauda vecāklokalizāciju pt.

Terminal
pip install django-locale-chain
Configuration
# settings.py
LOCALE_CHAINS = {
    'pt-BR': ['pt', 'es', 'en'],
    'zh-Hant-HK': ['zh-Hant', 'zh', 'en'],
}

MIDDLEWARE = [
    ...
    'django_locale_chain.middleware.LocaleChainMiddleware',
    ...
]

Pilnu atbalstīto sistēmu sarakstu un 75 iebūvētās ķēdes skatiet mūsu lokalizāciju atkāpšanās ceļvedī. Learn more →

Bieži uzdotie jautājumi