Skip to main content

Django i18n: vodič za internacionalizaciju i prevođenje

Od settings.py datoteke do produkcije: podesite Django sistem za prevođenje, pišite PO datoteke, obradite množine i automatizujte prevode pomoću AI tehnologije.

1

Instalirajte i izdvojte tekstove

Django i18n radni okvir je ugrađen — treba samo da ga omogućite. Instalirajte django-locale-chain za pametne rezervne lokale, a zatim koristite makemessages da iz Python koda i šablona izdvojite prevodive tekstove u PO datoteke.

Django u pozadini koristi GNU gettext. Komanda makemessages skenira kod u potrazi za gettext pozivima i oznakama šablona, pa generiše .po datoteke. Posle prevođenja, compilemessages ih konvertuje u binarne .mo datoteke za brzu pretragu tokom izvršavanja.
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

Podesite postavke i posrednički softver

Omogućite internacionalizaciju u settings.py tako što ćete postaviti USE_I18N = True, definisati listu podržanih LANGUAGES i dodati LocaleMiddleware u MIDDLEWARE stek. LocaleMiddleware otkriva jezik korisnika iz prefiksa URL adrese, sesije, kolačića ili Accept-Language zaglavlja.

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 da bude posle SessionMiddleware (jer čita sesiju), a pre CommonMiddleware. Ako je postavljen pogrešnim redosledom, otkrivanje jezika neprimetno otkazuje i svi korisnici vide podrazumevani LANGUAGE_CODE.

Internacionalizacija URL adresa

Koristite i18n_patterns() da automatski dodate kôd aktivnog jezika kao prefiks URL adresama. Tako svaki jezik dobija sopstveni imenski prostor URL adresa (/en/about/, /de/about/), što je bolje za SEO i omogućava korisnicima da dele veze za određeni jezik.

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 tekstove za prevođenje

Django pruža dve glavne funkcije za prevođenje: gettext() (sa pseudonimom _()) za tekstove koji se vrednuju tokom zahteva i gettext_lazy() za tekstove koji se vrednuju tokom uvoza. U šablonima koristite oznake {% trans %} i {% blocktrans %}.

U prikazima (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}")

U šablonima

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>

U modelima i obrascima

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
Upotreba gettext() umesto gettext_lazy() u poljima modela, oznakama obrazaca ili atributima nivoa klase dovodi do toga da se tekstovi prevedu samo jednom tokom uvoza (kada se server pokrene), a ne za svaki zahtev. Prevod će ostati zamrznut na jeziku koji je bio aktivan tokom uvoza — obično podrazumevanom LANGUAGE_CODE jeziku.

Format PO datoteke

Nakon pokretanja makemessages komande, Django generiše .po (Portable Object) datoteke za svaki jezik. One sadrže parove msgid/msgstr. Prevedite vrednosti msgstr, a zatim pokrenite compilemessages da generišete binarne .mo datoteke koje Django čita tokom izvršavanja.

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

Obradite množine i promenljive

Django koristi ngettext() za množinu, prema pravilima množine sistema GNU gettext. Svaki jezik definiše koliko oblika množine ima i formulu za izbor ispravnog oblika. PO datoteke to navode u zaglavlju 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}
Nikada ne koristite Python f-string tekstove ili .format() unutar gettext poziva. Alatka za izdvajanje prevoda ne može da ih raščlani. Koristite stari stil %() formatiranja: _('Hello, %(name)s!') % {'name': name}. Tako prevodioci vide i čuvare mesta promenljivih u svojim PO uređivačima.

Automatizujte kvalitet prevoda

Pomoću i18n-validate alatke otkrijte nedostajuće ključeve i neispravne čuvare mesta pre isporuke. Testirajte korisnički interfejs pseudoprevodima pomoću i18n-pseudo alatke pre nego što stignu pravi prevodi.

Uobičajene zamke

Zabuna oko gettext() i gettext_lazy() funkcija

Koristite gettext_lazy() (uvezen kao _) za polja modela, oznake obrazaca i sve atribute nivoa klase koji se vrednuju tokom uvoza. Koristite gettext() za funkcije prikaza i kod koji se izvršava tokom zahteva. Ako ih pomešate, prevodi ostaju zamrznuti na jeziku pokretanja servera.

Zaboravljeno pokretanje compilemessages komande

Django čita .mo (kompajlirane) datoteke, a ne .po datoteke. Ako izmenite .po datoteku i ne pokrenete 'python manage.py compilemessages', izmene se neće pojaviti. Dodajte compilemessages u skriptu za postavljanje.

LOCALE_PATHS nije podešen

Ako je LOCALE_PATHS prazan ili pokazuje na pogrešan direktorijum, makemessages pravi .po datoteke na pogrešnom mestu i Django ne može da ih pronađe tokom izvršavanja. Uvek postavite LOCALE_PATHS = [BASE_DIR / 'locale'] i proverite da li direktorijum postoji.

i18n_patterns nedostaje u URL adresama

Bez i18n_patterns(), URL adrese nemaju jezički prefiks i Django se za otkrivanje jezika oslanja samo na kolačiće i zaglavlja. To šteti SEO optimizaciji (nema URL adresa za određene jezike) i onemogućava promenu jezika putem URL adrese. Obuhvatite obrasce URL adresa namenjene korisnicima funkcijom i18n_patterns().

Pametni rezervni lokali uz django-locale-chain

Django sistem za prevođenje odmah prelazi na LANGUAGE_CODE kada regionalna varijanta nedostaje. Korisnik lokala pt-BR vidi engleski čak i kada imate prevode za pt-PT. django-locale-chain to ispravlja postavljanjem gettext lanaca rezervnih lokala: pt-BR pokušava pt-PT, zatim pt, pre prelaska na podrazumevani 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"]})

Preporuč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

Isprobajte i18n Agent sada

Pustite datoteku za prevođenje ovde

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

ili kliknite za izbor

Ciljni jezici

Registracija nije potrebnaTrenutna procena

Rezervni lokali uz django-locale-chain

Kada ključ prevoda nedostaje u regionalnom lokalu kao što je pt-BR, Django odmah prelazi na jezik šablona umesto da prvo proveri nadređeni 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',
    ...
]

Pogledajte naš vodič za rezervne lokale za celu listu podržanih sistema i 75 ugrađenih lanaca. Learn more →

Česta pitanja