Skip to main content

Django i18n: internacionalizavimo ir vertimo vadovas

Nuo settings.py iki gamybinės aplinkos: sukonfigūruokite Django vertimo sistemą, rašykite PO failus, apdorokite daugiskaitą ir automatizuokite vertimus naudodami DI.

1

Įdiegti ir išskirti eilutes

Django i18n sistema integruota – tereikia ją įjungti. Įdiekite django-locale-chain išmanioms atsarginėms lokalėms, tada su makemessages išskirkite verstinas eilutes iš Python kodo bei šablonų į PO failus.

Viduje Django naudoja GNU gettext. Komanda makemessages nuskaito gettext iškvietimus ir šablonų žymas kode, tada sugeneruoja .po failus. Išvertus compilemessages konvertuoja juos į dvejetainius .mo failus, kad vykdymo metu būtų greitai randami.
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

Sukonfigūruoti nustatymus ir tarpinę programinę įrangą

Įjunkite internacionalizavimą settings.py nustatydami USE_I18N = True, apibrėždami palaikomų LANGUAGES sąrašą ir pridėdami LocaleMiddleware prie MIDDLEWARE dėklo. LocaleMiddleware aptinka naudotojo kalbą pagal URL prefiksą, seansą, slapukus arba antraštę 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 turi būti po SessionMiddleware (ji nuskaito seansą) ir prieš CommonMiddleware. Jei įdėta netinkama tvarka, kalbos aptikimas tyliai nepavyksta ir visi naudotojai mato numatytąjį LANGUAGE_CODE.

URL internacionalizavimas

Naudokite i18n_patterns(), kad URL automatiškai gautų aktyvios kalbos kodo prefiksą. Taip kiekviena kalba turi savo URL vardų sritį (/en/about/, /de/about/), kuri geriau tinka SEO ir leidžia bendrinti konkrečios kalbos nuorodas.

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

Pažymėti verstinas eilutes

Django suteikia dvi pagrindines vertimo funkcijas: gettext() (trumpinys _()) užklausos metu įvertinamoms eilutėms ir gettext_lazy() importavimo metu įvertinamoms eilutėms. Šablonuose naudokite žymas {% trans %} ir {% blocktrans %}.

Rodiniuose (Python kode)

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

Šablonuose

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>

Modeliuose ir formose

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
Modelių laukuose, formų etiketėse ar klasės lygio atributuose naudojant gettext() vietoje gettext_lazy(), eilutės išverčiamos vieną kartą importuojant (paleidžiant serverį), o ne kiekvienai užklausai. Vertimas užfiksuojamas ta kalba, kuri buvo aktyvi importuojant – paprastai numatytąja LANGUAGE_CODE.

PO failo formatas

Paleidus makemessages Django kiekvienai kalbai sugeneruoja .po (Portable Object) failus. Juose yra msgid ir msgstr poros. Išverskite msgstr reikšmes, tada paleiskite compilemessages dvejetainiams .mo failams, kuriuos Django nuskaito vykdymo metu, sugeneruoti.

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

Apdoroti daugiskaitą ir kintamuosius

Django daugiskaitai naudoja ngettext(), kuri vadovaujasi GNU gettext daugiskaitos taisyklėmis. Kiekviena kalba apibrėžia, kiek daugiskaitos formų turi ir pagal kokią formulę parenkama tinkama forma. PO failai tai nurodo antraštėje 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 iškvietimuose niekada nenaudokite Python f eilučių ar .format(). Vertimų išskyrimo priemonė negali jų analizuoti. Naudokite senojo stiliaus %() formatavimą: _('Hello, %(name)s!') % {'name': name}. Taip vertėjai savo PO redaktoriuose matys kintamųjų vietos rezervavimo ženklus.

Automatizuoti vertimo kokybę

Naudodami i18n-validate prieš išleidimą aptikite trūkstamus raktus ir sugadintus vietos rezervavimo ženklus. Kol dar nėra tikrų vertimų, patikrinkite UI su i18n-pseudo pseudoverstimais.

Dažnos klaidos

gettext() ir gettext_lazy() painiava

Modelių laukams, formų etiketėms ir bet kuriam importavimo metu įvertinamam klasės lygio atributui naudokite gettext_lazy() (importuotą kaip _). Rodinių funkcijoms ir užklausos metu vykdomam kodui naudokite gettext(). Juos supainiojus vertimai užfiksuojami serverio paleidimo kalba.

Pamiršta paleisti compilemessages

Django nuskaito sukompiliuotus .mo, o ne .po failus. Jei pakeisite .po failą, bet nepaleisite 'python manage.py compilemessages', pakeitimai nebus rodomi. Pridėkite compilemessages prie diegimo scenarijaus.

LOCALE_PATHS nesukonfigūruotas

Jei LOCALE_PATHS tuščias arba nurodo netinkamą katalogą, makemessages sukuria .po failus netinkamoje vietoje ir Django jų neranda vykdymo metu. Visada nustatykite LOCALE_PATHS = [BASE_DIR / 'locale'] ir patikrinkite, ar katalogas egzistuoja.

URL trūksta i18n_patterns

Be i18n_patterns() URL neturi kalbos prefikso, todėl Django kalbą aptinka tik pagal slapukus ar antraštes. Tai kenkia SEO (nėra konkrečioms kalboms skirtų URL) ir neleidžia keisti kalbos per URL. Apgaubkite naudotojams skirtus URL šablonus su i18n_patterns().

Išmanios atsarginės lokalės su django-locale-chain

Kai nėra regioninio varianto, Django vertimo sistema iškart grįžta prie LANGUAGE_CODE. pt-BR naudotojas mato anglų kalbą, net jei turite pt-PT vertimų. django-locale-chain tai ištaiso įdiegdama gettext atsargines grandines: prieš grįžtant prie numatytosios kalbos pt-BR išbando pt-PT, tada 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"]})

Rekomenduojama projekto 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

Išbandykite i18n Agent dabar

Nuvilkite vertimo failą čia

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

arba spustelėkite norėdami pasirinkti

Tikslinės kalbos

Registruotis nereikiaMomentinis įvertis

Atsarginė lokalė su django-locale-chain

Kai regioninėje lokalėje, pavyzdžiui, pt-BR, trūksta vertimo rakto, Django iškart pereina prie šablono kalbos, užuot pirmiausia patikrinęs pirminę lokalę 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',
    ...
]

Visą palaikomų sistemų sąrašą ir 75 integruotas grandines rasite mūsų atsarginių lokalių vadove. Learn more →

Dažnai užduodami klausimai