Sie haben eine Django-App, die auf Englisch funktioniert. Jetzt soll sie auch in anderen Sprachen funktionieren. Dieser Leitfaden behandelt den gesamten Prozess, vom Markieren von Strings in Ihrem Code bis zur Bereitstellung einer vollständig lokalisierten Website, mit praktischen Beispielen bei jedem Schritt.
Djangos Internationalisierungs-Framework (üblicherweise i18n genannt) gehört zu den besseren seiner Art. Es unterstützt Rechts-nach-links-Sprachen, Pluraliseirungsregeln, Datumsformate und all die anderen Dinge, die Lokaliseirung wirklich schwierig machen. Der Haken ist, dass die Einrichtung mehrere bewegliche Teile umfasst, und die meisten Tutorials behandeln nur ein oder zwei davon.
Was Lokalisierung eigentich bedeutet
Lokalisierung ist mehr als nur das Übersetzen von Strings. Eine korrekt lokalisierte Django-App verarbeitet:
- Textübersetzung (Templates, Views, Models, JavaScript)
- URL-Routing pro Sprache (
/en/about/,/de/about/) - Datums-, Zeit- und Zahlenformatierung (14/03/2026 vs 03/14/2026)
- Pluralisierungsregeln (Englisch hat 2 Formen, Arabisch hat 6, Japanisch hat 1)
- Rechts-nach-links-Layout für Arabisch, Hebräisch, Farsi
- Zeitzonen-Unterstützung
Die meisten Django-Projekte benötigen nur die ersten drei Punkte. Aber es lohnt sich zu wissen, was das Framework leisten kann, bevor Sie beginnen, damit Sie sich nicht in eine Sackgasse manövrieren.
Schritt 1: Einstellungen konfiguartion
Beginnen Sie mit den Internationalisierungs-Einstellungen in settings.py:
from django.utils.translation import gettext_lazy as _
LANGUAGE_CODE = "en"
USE_I18N = True
USE_L10N = True
USE_TZ = True
LANGUAGES = [
("en", _("English")),
("de", _("German")),
("fr", _("French")),
("ja", _("Japanese")),
("es", _("Spanish")),
]
LOCALE_PATHS = [
BASE_DIR / "locale",
]
LANGUAGES definiert, welche Sprachen Ihre Website unterstützt. Fügen Sie nur Sprachen hinzu, die Sie tatsächlich übersetzen möchten. 30 Sprachen hier hinzuzufügen, ohne sie zu übersetzen, erzeugt nur leere .po-Dateien und macht Ihre URL-Struktur unübersichtlich.
LOCALE_PATHS teilt Django mit, wo nach Übersetzungsdateien gesucht werden soll. Standardmäßig ist das ein locale/-Verzeichnis in jeder App, aber ein einzelnes locale/-Verzeichnis auf Projektebene ist einfacher zu verwalten.
Schritt 2: Middleware und URL-Konfiguration hinzufügen
Fügen Sie die Locale-Middleware zu Ihrer MIDDLEWARE-Einstellung hinzu. Die Reihenfolge ist hier wichtig:
MIDDLEWARE = [
"django.middleware.security.SecurityMiddleware",
"django.contrib.sessions.middleware.SessionMiddleware",
"django.middleware.locale.LocaleMiddleware", # after SessionMiddleware
"django.middleware.common.CommonMiddleware",
# ...
]
LocaleMiddleware muss nach SessionMiddleware kommen (sie benötigt die Session, um Spracheinstellungen zu speichern) und vor CommonMiddleware. Eine falsche Reihenfolge ist einer der häufigsten Gründe, warum Django-Übersetzungen stillschweigend fehlschlagen.
Dann umschließen Sie Ihre URL-Muster mit i18n_patterns:
from django.conf.urls.i18n import i18n_patterns
urlpatterns = [
path("admin/", admin.site.urls),
]
urlpatterns += i18n_patterns(
path("", include("myapp.urls")),
)
Dies versieht alle Ihre URLs mit dem Sprachcode als Präfix: /en/about/, /de/about/, /fr/about/. Der Admin-Bereich bleibt ohne Präfix, da er in den meisten Projekten keine Lokalisierung benötigt.
Schritt 3: Strings für die Übersetzung markieren
Hier findet der Großteil der Arbeit statt. Jeder benutzersichtbare String in Ihrem Code muss in eine Übersetzungsfunktion eingeschlossen werden.
In Python-Code
from django.utils.translation import gettext as _
def my_view(request):
message = _("Your order has been placed.")
return render(request, "order.html", {"message": message})
Verwenden Sie gettext (als _ aliasiert) in Views und Funktionen. Für Strings auf Modulebene wie Model-Feldbezeichnungen verwenden Sie gettext_lazy:
from django.utils.translation import gettext_lazy as _
class Product(models.Model):
name = models.CharField(_("product name"), max_length=200)
description = models.TextField(_("description"))
class Meta:
verbose_name = _("product")
verbose_name_plural = _("products")
Der Unterschied ist wichtig: gettext_lazy verzögert die Übersetzungssuche, bis der String tatsächlich gerendert wird, was für alles notwendg ist, das zur Importzeit ausgewertet wird (Model-Definitionen, Formularfelder, URL-Namen). Die Verwendung von normalem gettext auf Modulebene übersetzt einmal beim Start und liefert dann allen die falsche Sprache.
In Templates
{% load i18n %}
<h1>{% trans "Welcome to our store" %}</h1>
<p>
{% blocktrans count items=cart.item_count %}
You have {{ items }} item in your cart.
{% plural %}
You have {{ items }} items in your cart.
{% endblocktrans %}
</p>
{% trans %} verarbeitet einfache Strings. {% blocktrans %} verarbeitet Strings mit Variablen oder Pluralisierung. Vergessen Sie nicht {% load i18n %} am Anfang jedes Templates, das diese Tags verwendet.
In JavaScript
Django kann einen JavaScript-Katalog Ihrer Übersetzungen generieren:
from django.views.i18n import JavaScriptCatalog
urlpatterns += i18n_patterns(
path("jsi18n/", JavaScriptCatalog.as_view(), name="javascript-catalog"),
)
Dann in Ihrem JavaScript:
document.getElementById("status").textContent = gettext("Loading...");
Binden Sie das Katalog-Skript ein, bevor JavaScript gettext verwendet:
<script src="{% url 'javascript-catalog' %}"></script>
Schritt 4: .po-Dateien generieren und übersetzen
Sobald Ihre Strings markiert sind, generieren Sie die Übersetzungsdateien:
python manage.py makemessages -l de -l fr -l ja -l es
Dies erstellt .po-Dateien in Ihrem locale/-Verzeichnis:
locale/
de/LC_MESSAGES/django.po
fr/LC_MESSAGES/django.po
ja/LC_MESSAGES/django.po
es/LC_MESSAGES/django.po
Jede .po-Datei enthält Einträge wie diesen:
#: myapp/views.py:12
msgid "Your order has been placed."
msgstr ""
In msgstr kommt die Übersetzung. Sie können diese manuell ausfüllen, Übersetzer beauftragen oder den Prozess mit KI-Übersetzungstools automatisieren.
Nach dem Übersetzen kompilieren Sie die .po-Dateien in binäre .mo-Dateien, die Django effizient lesen kann:
python manage.py compilemessages
Führen Sie compilemessages jedes Mal aus, wenn Sie Übersetzungen aktualisieren. Diesen Schritt zu vergessen ist ein weiterer häufiger Grund, warum Übersetzugen nicht angezeigt werden. Django liest die .mo-Dateien, nicht die .po-Dateien.
Schritt 5: Datums-, Zahlen- und Zeitformatierung verarbeiten
Djangos L10N-Einstellung steuert, wie Daten und Zahlen formatiert werden. Mit USE_L10N = True verwendet Django automatsich locale-spezifische Formatierung:
{% load l10n %}
<p>Order date: {{ order.created_at }}</p>
<p>Total: {{ order.total }}</p>
Ein Datum, das auf Englisch als "July 10, 2026" angezeigt wird, erscheint auf Deutsch automatisch als "10. Juli 2026" und auf Japanisch als "2026年7月10日". Zahlen folgen ähnlichen Regeln: 1,234.56 auf Englisch wird zu 1.234,56 auf Deutsch.
Wenn Sie das Format für bestimmte Werte überschreiben müssen, verwenden Sie die Filter localize und unlocalize:
{% load l10n %}
<!-- Always use locale formatting -->
<p>{{ value|localize }}</p>
<!-- Always use the default (English) format -->
<p>{{ value|unlocalize }}</p>
Schritt 6: Sprachumschalter hinzufügen
Benutzer benötigen eine Möglichkeit, die Sprache zu wechseln. Hier ist ein einfacher Sprachumschalter, der mit Djangos set_language-View funktioniert:
{% load i18n %}
<form action="{% url 'set_language' %}" method="post">
{% csrf_token %}
<input type="hidden" name="next" value="{{ request.path }}">
<select name="language" onchange="this.form.submit()">
{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}
{% for lang_code, lang_name in LANGUAGES %}
<option value="{{ lang_code }}"
{% if lang_code == LANGUAGE_CODE %}selected{% endif %}>
{{ lang_name }}
</option>
{% endfor %}
</select>
</form>
Stellen Sie sicher, dass die set_language-URL in Ihrer URL-Konfiguration enthalten ist:
urlpatterns = [
path("i18n/", include("django.conf.urls.i18n")),
# ...
]
Diese sollte außerhalb von i18n_patterns liegen, da der Sprachumschalter selbst kein Sprachpärfix benötigt.
Häufige Fehler und wie Sie sie vermeiden
Verwendung von gettext statt gettext_lazy in Models
Dies ist der häufigste Lokalisierungsfehler in Django-Projekten. Model-Felder, Formular-Labels und alles andere, was auf Modulebene definiert wird, benötigt gettext_lazy, nicht gettext. Das Symptom: Alle Benutzer sehen Übersetzungen in der Sprache, mit der der Serverprozess gestartet wurde.
compilemessages nicht ausgeführt
Sie haben die .po-Datei bearbeitet, den Server neu gestartet, aber die Übersetzungen erscheinen trotzdem nicht. Die .mo-Datei ist das, was Django liest, und sie wird nicht automatisch aktualisiert. Fügen Sie compilemessages zu Ihrer Deployment-Pipeline hinzu.
Falsche Middleware-Reihenfolge
LocaleMiddleware nach CommonMiddleware bedeutet, dass Django die Sprache nicht aus dem URL-Präfix erkennen kann. Die Anfrage fällt jedes Mal auf die Standardsprache zurück. Platzieren Sie sie zwischen SessionMiddleware und CommonMiddleware.
Fest kodierte Strings in Templates
Es ist leicht, Strings zu übersehen, die übersetzt werden sollten. Durchsuchen Sie Ihre Templates nach bloßem Text außerhalb von {% trans %}- oder {% blocktrans %}-Tags. Typische Übeltäter: Button-Beschriftungen, Formularfeld-Platzhalter, Fehlermeldungen und Footer-Text.
Pluraliseirung nicht berücksichtigt
Englisch hat zwei Pluralformen (1 item, 2 items). Russisch hat drei. Arabisch hat sechs. Wenn Sie "item(s)" fest kodieren, anstatt ngettext oder {% blocktrans count %} zu verwenden, werden Ihre Übersetzungen in anderen Sprachen holprig klingen oder grammatikalisch falsch sein.
Den Übersetzungs-Workflow automatisieren
Das manuelle Übersetzen von .po-Dateien funktioniert für kleine Projekte, skaliert aber nicht. Ein typisches Django-Projekt mit 200 übersetzbaren Strings in 5 Sprachen bedeutet 1.000 Übersetzungen, die verwaltet werden müssen. Jedes Mal, wenn Sie einen String hinzufügen oder ändern, müssen alle Sprachen aktualisiert werden.
Der Workflow sieht normalerweise so aus:
- Neue Strings mit
_()oder{% trans %}markieren makemessagesausführen, um sie zu extrahieren- Die neuen Einträge in jeder
.po-Datei übersetzen compilemessagesausführen- Alles committen
Bei den Schritten 3 und 4 wird es langsam. Menschliche Übersetzer verursachen Verzögerungen und Kosten. Manuelles Kopieren und Einfügen in Übersetzungsdienste ist mühsam und fehleranfällig, besonders wenn Sie Djangos Platzhalter-Formate wie %(name)s oder {count} beibehalten müssen.
KI-Übersetzungstools können Schritt 3 automatisieren, während Schritt 4 in Ihrer CI/CD-Pipeline verbleibt. Der Kompromiss ist, dass KI-Übersetzungen möglicherweise eine Überprüfung hinsichtlich Nuancen und Terminologie benötigen, aber für die meisten UI-Strings ist die Qualität gut genug, um sie direkt bereitgestelt werden zu können.
Ihre Lokalisierung testen
Bevor Sie deployen, überprüfen Sie, ob Ihre Lokalisierung tatsächlich funktioniert:
# Generate messages for all configured languages
python manage.py makemessages -a
# Check for missing translations
python manage.py compilemessages
# Start the dev server and switch languages
python manage.py runserver
Punkte zum Prüfen:
- Wechseln Sie zwischen allen unterstützten Sprachen mit dem Sprachumschalter
- Überprüfen Sie, dass URLs das korrekte Sprachpräfix enthalten
- Prüfen Sie, ob Daten und Zahlen pro Locale korrekt formatiert werden
- Suchen Sie nach unübersetzten Strings (sie erscheinen auf Englisch)
- Testen Sie Rechts-nach-links-Sprachen, falls Sie diese unterstützen
- Überprüfen Sie, ob die Pluralisierung korrekt funktioniert (testen Sie mit 0, 1, 2 und 5+ Elementen)
Erwägen Sie, einen CI-Check hinzuzufügen, der fehlschlägt, wenn eine .po-Datei unübersetzte oder unscharfe Einträge enthält. Dies verhindert versehentliche Deployments mit fehlnden Übersetzungen.
Projektstruktur
Ein gut organisiertes Lokalisierungs-Setup sieht so aus:
myproject/
locale/
de/LC_MESSAGES/django.po
fr/LC_MESSAGES/django.po
ja/LC_MESSAGES/django.po
es/LC_MESSAGES/django.po
myapp/
templates/
views.py
models.py
settings.py
urls.py
TRANSLATING.md
Die TRANSLATING.md-Datei ist optional, aber nützlich. Sie dokumentiert Ihre Terminologie-Präferenzen, Tonrichtlinien und alle übersetzungsspezifischen Regeln für Ihr Projekt. Wenn Sie KI-Übersetzungstools verwenden, die Kontextdateien unterstüzen, können diese die Datei lesen und Ihre Präferenzen anwenden.
Nächste Schritte
Wenn Sie bei Null anfangen:
- Fügen Sie die Einstellungen und Middleware aus den Schritten 1 und 2 hinzu
- Wählen Sie Ihr wichtigstes Template und markieren Sie dessen Strings (Schritt 3)
- Generieren Sie
.po-Dateien zunächst für eine Sprache (Schritt 4) - Übersetzen Sie diese eine Sprache und überprüfen Sie, ob alles durchgängig funktioniert
- Erweitern Sie dann auf weitere Templates und Sprachen
Wenn Sie bereits eine teilweise lokalisierte App haben:
- Führen Sie
makemessages -aaus, um alle.po-Dateien neu zu generieren - Prüfen Sie auf unscharfe oder unübersetzte Strings
- Füllen Sie fehlende Übersetzungen aus
- Richten Sie einen CI-Check ein, damit neue unübersetzte Strings erkannt werden, bevor sie in Produktion gelangen
Klein anfangen und erweitern ist besser, als alles auf einmal zu lokalisieren. Bringen Sie eine Sprache vollständig zum Laufen und fügen Sie dann weitere hinzu.