Skip to main content

Django i18n: vodnik po internacionalizaciji in prevajanju

Od settings.py do produkcije: nastavite prevajalski sistem ogrodja Django, pišite datoteke PO, obravnavajte množinske oblike in avtomatizirajte prevajanje z umetno inteligenco.

1

Namestite in izločite nize

Ogrodje i18n je že vgrajeno v Django -- le omogočiti ga morate. Namestite django-locale-chain za pametno uporabo nadomestnih področnih nastavitev, nato pa z makemessages iz kode Python in predlog izločite prevedljive nize v datoteke PO.

Django v ozadju uporablja GNU gettext. Ukaz makemessages v kodi poišče klice gettext in oznake predlog ter nato ustvari datoteke .po. Po prevodu jih compilemessages pretvori v binarne datoteke .mo, ki omogočajo hitro iskanje med izvajanjem.
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

Nastavite nastavitve in vmesno programsko opremo

Internacionalizacijo v settings.py omogočite tako, da nastavite USE_I18N = True, določite seznam podprtih jezikov LANGUAGES in v sklad MIDDLEWARE dodate LocaleMiddleware. LocaleMiddleware zazna uporabnikov jezik iz predpone URL-ja, seje, piškotkov ali glave 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 mora biti za SessionMiddleware (ker bere sejo) in pred CommonMiddleware. Če ga postavite v napačen vrstni red, zaznavanje jezika odpove brez opozorila, vsi uporabniki pa vidijo privzeti LANGUAGE_CODE.

Internacionalizacija URL-jev

Z i18n_patterns() URL-jem samodejno dodajte predpono s kodo aktivnega jezika. Tako vsak jezik dobi svoj imenski prostor URL-jev (/en/about/, /de/about/), kar je bolje za SEO in uporabnikom omogoča deljenje povezav za posamezne jezike.

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

Označite nize za prevajanje

Django ponuja dve glavni prevajalski funkciji: gettext() (z vzdevkom _()) za nize, ovrednotene ob zahtevi, in gettext_lazy() za nize, ovrednotene ob uvozu. V predlogah uporabite oznaki {% trans %} in {% blocktrans %}.

V pogledih (koda Python)

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}")

V predlogah

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>

V modelih in obrazcih

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
Če v poljih modelov, oznakah obrazcev ali atributih na ravni razreda namesto gettext_lazy() uporabite gettext(), se nizi prevedejo samo enkrat ob uvozu (ko se strežnik zažene), ne pa ob vsaki zahtevi. Prevod ostane v jeziku, ki je bil aktiven med uvozom -- običajno v privzetem LANGUAGE_CODE.

Oblika datotek PO

Po zagonu makemessages Django za vsak jezik ustvari datoteke .po (Portable Object). Te vsebujejo pare msgid/msgstr. Prevedite vrednosti msgstr, nato pa za ustvarjanje binarnih datotek .mo, ki jih Django bere med izvajanjem, zaženite compilemessages.

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

Obravnavajte množinske oblike in spremenljivke

Django za množinske oblike uporablja ngettext(), ki upošteva množinska pravila GNU gettext. Vsak jezik določa število množinskih oblik in formulo za izbiro ustrezne oblike. Datoteke PO to navedejo v glavi 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}
V klicih gettext nikoli ne uporabljajte Pythonovih nizov f ali .format(). Orodje za izločanje prevodov jih ne more razčleniti. Uporabite staro oblikovanje z %(): _('Hello, %(name)s!') % {'name': name}. Tako bodo prevajalci v svojih urejevalnikih PO videli tudi označbe mesta za spremenljivke.

Avtomatizirajte zagotavljanje kakovosti prevodov

Z i18n-validate odkrijte manjkajoče ključe in poškodovane označbe mest, še preden pridejo v produkcijo. Preden prispejo pravi prevodi, uporabniški vmesnik preizkusite s psevdoprevodi z orodjem i18n-pseudo.

Pogoste pasti

Zamenjava gettext() in gettext_lazy()

Za polja modelov, oznake obrazcev in vse atribute na ravni razreda, ki se ovrednotijo ob uvozu, uporabite gettext_lazy() (uvožen kot _). Za funkcije pogledov in kodo, ki se izvaja ob zahtevi, uporabite gettext(). Če ju zamenjate, prevodi ostanejo v jeziku, ki je bil aktiven ob zagonu strežnika.

Pozabljen zagon compilemessages

Django bere (prevedene) datoteke .mo, ne datotek .po. Če uredite datoteko .po in ne zaženete 'python manage.py compilemessages', se spremembe ne bodo prikazale. Dodajte compilemessages v skript za uvajanje.

LOCALE_PATHS ni nastavljen

Če je LOCALE_PATHS prazen ali kaže v napačno mapo, makemessages ustvari datoteke .po na napačnem mestu in Django jih med izvajanjem ne more najti. Vedno nastavite LOCALE_PATHS = [BASE_DIR / 'locale'] in preverite, ali mapa obstaja.

Manjkajoči i18n_patterns v URL-jih

Brez i18n_patterns() URL-ji nimajo jezikovne predpone, zato se Django pri zaznavanju jezika zanaša izključno na piškotke/glave. To škoduje optimizaciji SEO (ni URL-jev za posamezne jezike) in onemogoči preklapljanje jezika prek URL-ja. Vzorce URL-jev, namenjene uporabnikom, ovijte z i18n_patterns().

Pametne nadomestne področne nastavitve z django-locale-chain

Če regionalna različica manjka, Djangov prevajalski sistem neposredno uporabi LANGUAGE_CODE. Uporabnik z nastavitvijo pt-BR zato vidi angleščino, tudi če imate prevode za pt-PT. django-locale-chain to odpravi z namestitvijo verig nadomestnih prevodov gettext: za pt-BR najprej poskusi pt-PT, nato pt in šele zatem uporabi Vaš privzeti jezik.

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"]})

Priporočena struktura projekta

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

Preizkusite i18n Agent zdaj

Spustite prevajalsko datoteko sem

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

ali kliknite za izbiro

Ciljni jeziki

Registracija ni potrebnaTakojšnja ocena

Nadomestne področne nastavitve z django-locale-chain

Ko v regionalnih področnih nastavitvah, kot je pt-BR, manjka ključ prevoda, Django neposredno uporabi jezik predloge, namesto da bi najprej preveril nadrejene področne nastavitve 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',
    ...
]

Celoten seznam podprtih ogrodij in 75 vgrajenih verig najdete v našem vodniku po nadomestnih področnih nastavitvah. Learn more →

Pogosta vprašanja