Skip to main content

Django-i18n: Leitfaden zur Internationalisierung und Übersetzung

Von settings.py bis zur Produktion: Konfigurieren Sie Djangos Übersetzungssystem, erstellen Sie PO-Dateien, verarbeiten Sie Pluralformen und automatisieren Sie Übersetzungen mit KI.

1

Installieren und Zeichenfolgen extrahieren

Djangos i18n-Framework ist integriert – Sie müssen es nur aktivieren. Installieren Sie django-locale-chain für intelligente Locale-Fallbacks und extrahieren Sie anschließend mit makemessages übersetzbare Zeichenfolgen aus Ihrem Python-Code und Ihren Vorlagen in PO-Dateien.

Django verwendet intern GNU gettext. Der Befehl makemessages durchsucht Ihren Code nach gettext-Aufrufen und Vorlagen-Tags und erzeugt .po-Dateien. Nach der Übersetzung wandelt compilemessages sie in binäre .mo-Dateien für schnelle Abfragen zur Laufzeit um.
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

Einstellungen und Middleware konfigurieren

Aktivieren Sie die Internationalisierung in settings.py mit USE_I18N = True, definieren Sie Ihre Liste unterstützter LANGUAGES und fügen Sie LocaleMiddleware zu Ihrem MIDDLEWARE-Stack hinzu. LocaleMiddleware erkennt die Sprache anhand des URL-Präfixes, der Sitzung, Cookies oder des Accept-Language-Headers.

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 muss nach SessionMiddleware stehen, da sie die Sitzung liest, und vor CommonMiddleware. Bei falscher Reihenfolge schlägt die Spracherkennung unbemerkt fehl und alle Personen sehen den standardmäßigen LANGUAGE_CODE.

URL-Internationalisierung

Verwenden Sie i18n_patterns(), um Ihren URLs automatisch den aktiven Sprachcode voranzustellen. So erhält jede Sprache einen eigenen URL-Namensraum (/en/about/, /de/about/), was SEO verbessert und das Teilen sprachspezifischer Links ermöglicht.

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

Zeichenfolgen zur Übersetzung kennzeichnen

Django bietet zwei zentrale Übersetzungsfunktionen: gettext() mit dem Alias _() für Zeichenfolgen, die zur Anfragezeit ausgewertet werden, und gettext_lazy() für Zeichenfolgen, die zur Importzeit ausgewertet werden. Verwenden Sie in Vorlagen die Tags {% trans %} und {% blocktrans %}.

In Ansichten (Python-Code)

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

In Vorlagen

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>

In Modellen und Formularen

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
Wenn Sie gettext() statt gettext_lazy() in Modellfeldern, Formularbezeichnungen oder Attributen auf Klassenebene verwenden, werden Zeichenfolgen einmal zur Importzeit beim Serverstart statt pro Anfrage übersetzt. Die Übersetzung bleibt in der beim Import aktiven Sprache eingefroren – üblicherweise im standardmäßigen LANGUAGE_CODE.

PO-Dateiformat

Nach der Ausführung von makemessages erzeugt Django für jede Sprache .po-Dateien (Portable Object). Sie enthalten msgid/msgstr-Paare. Übersetzen Sie die msgstr-Werte und führen Sie anschließend compilemessages aus, um die binären .mo-Dateien zu erzeugen, die Django zur Laufzeit liest.

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

Pluralformen und Variablen verarbeiten

Django verwendet ngettext() für die Pluralbildung nach den Pluralregeln von GNU gettext. Jede Sprache definiert die Anzahl ihrer Pluralformen und die Formel zur Auswahl der richtigen Form. PO-Dateien deklarieren dies mit einem Plural-Forms-Header.

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}
Verwenden Sie in gettext-Aufrufen niemals Python-f-Strings oder .format(). Der Übersetzungsextraktor kann sie nicht parsen. Verwenden Sie die alte %()-Formatierung: _('Hello, %(name)s!') % {'name': name}. Dadurch sehen Übersetzungsfachkräfte die Variablenplatzhalter außerdem in ihren PO-Editoren.

Übersetzungsqualität automatisieren

Erkennen Sie mit i18n-validate fehlende Schlüssel und beschädigte Platzhalter vor der Veröffentlichung. Testen Sie Ihre Benutzeroberfläche mit i18n-pseudo und Pseudoübersetzungen, bevor echte Übersetzungen vorliegen.

Häufige Fallstricke

Verwechslung von gettext() und gettext_lazy()

Verwenden Sie gettext_lazy() mit dem Importalias _ für Modellfelder, Formularbezeichnungen und jedes zur Importzeit ausgewertete Attribut auf Klassenebene. Verwenden Sie gettext() für Ansichtsfunktionen und Code zur Anfragezeit. Eine Verwechslung friert Übersetzungen in der Sprache des Serverstarts ein.

compilemessages nicht ausgeführt

Django liest kompilierte .mo-Dateien, nicht .po-Dateien. Wenn Sie eine .po-Datei bearbeiten und 'python manage.py compilemessages' nicht ausführen, erscheinen Ihre Änderungen nicht. Fügen Sie compilemessages zu Ihrem Bereitstellungsskript hinzu.

LOCALE_PATHS nicht konfiguriert

Wenn LOCALE_PATHS leer ist oder auf das falsche Verzeichnis verweist, erstellt makemessages .po-Dateien am falschen Ort und Django findet sie zur Laufzeit nicht. Setzen Sie stets LOCALE_PATHS = [BASE_DIR / 'locale'] und prüfen Sie, ob das Verzeichnis vorhanden ist.

i18n_patterns fehlt in URLs

Ohne i18n_patterns() besitzen URLs kein Sprachpräfix und Django nutzt zur Spracherkennung ausschließlich Cookies/Header. Dies beeinträchtigt SEO, weil sprachspezifische URLs fehlen, und verhindert den Sprachwechsel über die URL. Umschließen Sie Ihre benutzerbezogenen URL-Muster mit i18n_patterns().

Intelligente Locale-Fallbacks mit django-locale-chain

Djangos Übersetzungssystem wechselt direkt zu LANGUAGE_CODE, wenn eine regionale Variante fehlt. Eine Person mit pt-BR sieht Englisch, selbst wenn pt-PT-Übersetzungen vorhanden sind. django-locale-chain behebt dies mit gettext-Fallback-Ketten: pt-BR versucht pt-PT und dann pt, bevor auf Ihre Standardsprache zurückgegriffen wird.

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

Empfohlene Projektstruktur

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

i18n Agent jetzt testen

Legen Sie Ihre Übersetzungsdatei hier ab

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

oder zum Auswählen klicken

Zielsprachen

Keine Registrierung erforderlichSofortiges Angebot

Locale-Fallback mit django-locale-chain

Fehlt ein Übersetzungsschlüssel in einer regionalen Locale wie pt-BR, wechselt Django direkt zur Vorlagensprache, statt zuerst die übergeordnete Locale pt zu prüfen.

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',
    ...
]

In unserem Leitfaden zu Locale-Fallbacks finden Sie die vollständige Liste unterstützter Frameworks und 75 integrierter Ketten. Learn more →

Häufig gestellte Fragen