Tutorials//13 Min. Lesezeit

Django i18n mit KI-Übersetzung: Vollständige Einrichtungsanleitung

Eray Gündoğmuş
Teilen

Django i18n mit KI-Übersetzung: Vollständige Einrichtungsanleitung

Django wird mit einem ausgereiften Internationalisierungs-Framework (i18n) geliefert, das auf GNU gettext aufbaut. Wenn Sie dieses Fundament mit KI-gestützter Übersetzung kombinieren, erhalten Sie einen Workflow, der von einem Solo-Projekt bis zu einer mehrsprachigen Produktionsanwendung skaliert, ohne dass Sie in manueller Übersetzungsarbeit untergehen.

Dieser Leitfaden führt Sie durch den gesamten Prozess: Django für i18n konfigurieren, Zeichenketten markieren, .po-Dateien verwalten, Übersetzungen mit KI automatisieren und alles in eine CI/CD-Pipeline einbinden.

Wichtigste Erkenntnisse

  • Djangos i18n-System verwendet GNU gettext — Zeichenketten werden in Python und Templates markiert, in .po-Dateien extrahiert und zu binären .mo-Dateien für die Laufzeitnutzung kompiliert.
  • KI-Übersetzung kann die .po-Datei-Übersetzung automatisieren — Maschinenübersetzungs-APIs verarbeiten nicht übersetzte Einträge in großen Mengen und reduzieren tagelange manuelle Arbeit auf Minuten.
  • Ein Qualitätsprüfungsschritt ist unerlässlich — KI-generierte Übersetzungen sollten vor der Produktionsbereitstellung von Muttersprachlern überprüft werden, insbesondere für benutzerseitige Inhalte.
  • CI/CD-Integration schließt den Kreislauf — automatisierte Pipelines können neue Zeichenketten extrahieren, übersetzen, Nachrichtendateien kompilieren und ohne manuelle Eingriffe bereitstellen.
  • Better i18n bietet einen verwalteten Workflow — anstatt benutzerdefinierte Skripte zu erstellen, können Sie .po-Dateien synchronisieren, Übersetzungen verwalten und den gesamten Lebenszyklus von einer einzigen Plattform aus automatisieren.

Was ist Django i18n?

Django i18n ist Djangos integriertes Internationalisierungs-Framework, mit dem Sie Ihre Webanwendung in mehrere Sprachen übersetzen können. Es umhüllt GNU gettext, um Zeichenkettenextraktion, Übersetzungsdateiverwaltung und Sprachenwechsel zur Laufzeit bereitzustellen — alles in Djangos Templates, Formulare und URL-Routing integriert.

Django trennt Internationalisierung (i18n) von Lokalisierung (l10n). Internationalisierung ist der Prozess, Ihren Code auf die Unterstützung mehrerer Sprachen vorzubereiten. Lokalisierung ist der Prozess, Inhalte tatsächlich zu übersetzen und Formate für ein bestimmtes Gebietsschema anzupassen. Django verwaltet beides über sein django.utils.translation-Modul und die gettext-Toolchain.

Das Framework unterstützt die Übersetzung von:

  • Python-Zeichenketten in Views, Modellen und Formularen
  • Template-Inhalten mit integrierten Template-Tags
  • URL-Mustern für gebietsschema-präfixiertes Routing
  • Datums-, Zeit-, Zahlen- und Währungsformatierung über django.utils.formats

Die offizielle Referenz finden Sie in der Django-Internationalisierungsdokumentation.

Django für Internationalisierung einrichten

Bevor Sie Zeichenketten für die Übersetzung markieren, müssen Sie Djangos Einstellungen konfigurieren und die erforderliche Middleware installieren.

Einstellungen konfigurieren

Öffnen Sie Ihre settings.py und legen Sie Folgendes fest:

# settings.py

from django.utils.translation import gettext_lazy as _

# Standardsprache für die Anwendung
LANGUAGE_CODE = "en"

# Das Internationalisierungs-Framework aktivieren
USE_I18N = True

# Lokalisierte Formatierung von Daten, Zahlen usw. aktivieren
USE_L10N = True

# Zeitzonenbewusste Datetimes aktivieren
USE_TZ = True

# Sprachen, die Ihre Anwendung unterstützt
LANGUAGES = [
    ("en", _("English")),
    ("es", _("Spanish")),
    ("fr", _("French")),
    ("de", _("German")),
    ("ja", _("Japanese")),
]

# Wo Django nach Übersetzungsdateien sucht
LOCALE_PATHS = [
    BASE_DIR / "locale",
]

Sie benötigen außerdem LocaleMiddleware in Ihrem Middleware-Stack. Es muss nach SessionMiddleware und vor CommonMiddleware kommen:

MIDDLEWARE = [
    "django.middleware.security.SecurityMiddleware",
    "django.contrib.sessions.middleware.SessionMiddleware",
    "django.middleware.locale.LocaleMiddleware",  # Muss hier stehen
    "django.middleware.common.CommonMiddleware",
    "django.middleware.csrf.CsrfViewMiddleware",
    "django.contrib.auth.middleware.AuthenticationMiddleware",
    "django.contrib.messages.middleware.MessageMiddleware",
    "django.middleware.clickjacking.XFrameOptionsMiddleware",
]

Erstellen Sie die locale-Verzeichnisstruktur:

mkdir -p locale/{es,fr,de,ja}/LC_MESSAGES

Zeichenketten für die Übersetzung markieren

Django bietet zwei Hauptfunktionen zum Markieren übersetzbarer Zeichenketten:

  • gettext() (als _() aliasiert) — übersetzt die Zeichenkette sofort zur Laufzeit
  • gettext_lazy() (als _() aliasiert) — verzögert die Übersetzung bis die Zeichenkette gerendert wird, was für Code auf Modulebene wie Modellfelder und Formularbeschriftungen erforderlich ist

In Views (gettext verwenden):

from django.utils.translation import gettext as _

def dashboard_view(request):
    welcome_message = _("Welcome to your dashboard")
    context = {
        "title": _("Dashboard"),
        "welcome": welcome_message,
    }
    return render(request, "dashboard.html", context)

In Modellen (gettext_lazy verwenden):

from django.db import models
from django.utils.translation import gettext_lazy as _

class Article(models.Model):
    title = models.CharField(
        max_length=200,
        verbose_name=_("Title"),
    )
    body = models.TextField(
        verbose_name=_("Body"),
        help_text=_("The main content of the article."),
    )
    created_at = models.DateTimeField(
        auto_now_add=True,
        verbose_name=_("Created at"),
    )

    class Meta:
        verbose_name = _("Article")
        verbose_name_plural = _("Articles")

    def __str__(self):
        return self.title

Der Unterschied ist wichtig: gettext_lazy gibt einen lazy String-Proxy zurück, der zur korrekten Sprache aufgelöst wird, wenn die Zeichenkette tatsächlich angezeigt wird. Modelldefinitionen werden einmalig beim Import ausgewertet; die Verwendung von gettext dort würde die beim Import aktive Sprache dauerhaft einfrieren.

Template-Übersetzungs-Tags

Django-Templates verwenden {% load i18n %}, um auf Übersetzungs-Tags zuzugreifen:

Einfache Zeichenkettenübersetzung mit {% trans %}:

{% load i18n %}

<h1>{% trans "Welcome to our site" %}</h1>
<p>{% trans "This content will be translated." %}</p>

Block-Übersetzung mit {% blocktrans %} für Zeichenketten mit Variablen:

{% load i18n %}

{% blocktrans with username=user.username %}
    Hello, {{ username }}! You have new notifications.
{% endblocktrans %}

Pluralisierung:

{% load i18n %}

{% blocktrans count counter=item_count %}
    You have {{ counter }} item in your cart.
{% plural %}
    You have {{ counter }} items in your cart.
{% endblocktrans %}

Sprachkontext setzen:

{% load i18n %}

{% get_current_language as LANGUAGE_CODE %}
<html lang="{{ LANGUAGE_CODE }}">

URL-Internationalisierung

Djangos i18n_patterns-Funktion versieht Ihre URL-Muster mit dem aktiven Sprachcode als Präfix:

# urls.py
from django.conf.urls.i18n import i18n_patterns
from django.urls import path, include

urlpatterns = [
    # Nicht lokalisierte URLs (Admin, API usw.)
    path("api/", include("api.urls")),
]

urlpatterns += i18n_patterns(
    path("", include("pages.urls")),
    path("blog/", include("blog.urls")),
    path("accounts/", include("accounts.urls")),
    prefix_default_language=True,
)

Mit dieser Konfiguration werden Ihre URLs zu:

  • /en/blog/ — Englischer Blog
  • /es/blog/ — Spanischer Blog
  • /fr/blog/ — Französischer Blog

Sie sollten auch Djangos eingebaute Sprachenwechsel-View einschließen:

from django.conf.urls.i18n import i18n_patterns
from django.urls import path, include

urlpatterns = [
    path("i18n/", include("django.conf.urls.i18n")),
]

urlpatterns += i18n_patterns(
    # ... Ihre Muster
)

Dies aktiviert den {% url 'set_language' %}-Template-Tag, mit dem Benutzer die Sprache über ein Formular-POST wechseln können.

Arbeiten mit .po- und .mo-Dateien

Djangos Übersetzungssystem basiert auf dem Dateiformat von GNU gettext. Das Verständnis dieser Pipeline ist unerlässlich, bevor Sie sie automatisieren.

Wie gettext in Django funktioniert

Der Workflow folgt drei Schritten:

  1. Extrahierenmakemessages scannt Ihre Python-Dateien und Templates nach übersetzbaren Zeichenketten und schreibt sie in .po-Dateien (Portable Object).
  2. Übersetzen — Übersetzer (oder KI) füllen das msgstr-Feld für jeden msgid-Eintrag in den .po-Dateien aus.
  3. Kompilierencompilemessages konvertiert .po-Dateien in binäre .mo-Dateien (Machine Object), die Django zur Laufzeit für schnelle Lookups liest.

Nachrichten extrahieren

Führen Sie den Extraktionsbefehl aus Ihrem Projektstamm aus:

# Nachrichten für alle konfigurierten Sprachen extrahieren
python manage.py makemessages --all --no-obsolete

# Für eine bestimmte Sprache extrahieren
python manage.py makemessages -l es

# JavaScript-Zeichenketten einschließen (für Djangos JS i18n-Katalog)
python manage.py makemessages -d djangojs --all

Das --no-obsolete-Flag entfernt Einträge für Zeichenketten, die nicht mehr in Ihrem Code vorhanden sind, und hält Ihre .po-Dateien sauber.

Die .po-Dateistruktur

Nach der Extraktion erhält jedes Gebietsschema eine .po-Datei:

locale/
├── es/
│   └── LC_MESSAGES/
│       └── django.po
├── fr/
│   └── LC_MESSAGES/
│       └── django.po
└── de/
    └── LC_MESSAGES/
        └── django.po

Ein .po-Dateieintrag sieht so aus:

#: templates/dashboard.html:5
msgid "Welcome to your dashboard"
msgstr ""

#: myapp/models.py:12
msgid "Article"
msgstr ""

#. Translators: This is a button label
#: templates/base.html:42
msgid "Submit"
msgstr ""

Jeder Eintrag hat:

  • #:-Kommentare — Quelldatei- und Zeilenreferenzen
  • msgid — die Originalzeichenkette (in Ihrer Quellsprache)
  • msgstr — die übersetzte Zeichenkette (leer bis übersetzt)
  • #.-Kommentare — Hinweise für Übersetzer (über Translators:-Kommentare in Ihrem Code hinzugefügt)

Nachrichten kompilieren

Sobald Übersetzungen abgeschlossen sind, kompilieren Sie sie:

python manage.py compilemessages

Dadurch werden .mo-Dateien neben den .po-Dateien erstellt. Django lädt diese Binärdateien beim Start für schnelle Übersetzungs-Lookups. Sie müssen Ihren Django-Server (oder Worker-Prozesse) nach dem Kompilieren neuer Übersetzungen neu starten.

KI-gestützte Übersetzung zu Django hinzufügen

Die manuelle Übersetzung von .po-Dateien ist genau, aber langsam. KI-gestützte Übersetzung kann Hunderte von Einträgen in Sekunden verarbeiten und gibt Ihnen einen funktionierenden ersten Entwurf, den menschliche Prüfer dann verfeinern können.

.po-Dateien mit Python analysieren und übersetzen

Die polib-Bibliothek bietet eine saubere API zum programmatischen Lesen und Schreiben von .po-Dateien:

pip install polib openai

Hier ist ein Skript, das nicht übersetzte Einträge in einer .po-Datei mithilfe einer KI-Übersetzungs-API übersetzt:

# scripts/translate_po.py

import sys
import polib
from openai import OpenAI

client = OpenAI()  # Verwendet die OPENAI_API_KEY-Umgebungsvariable

TARGET_LANGUAGES = {
    "es": "Spanish",
    "fr": "French",
    "de": "German",
    "ja": "Japanese",
}


def translate_text(text: str, target_language: str) -> str:
    """Übersetzt eine einzelne Zeichenkette mit einem KI-Modell."""
    response = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[
            {
                "role": "system",
                "content": (
                    f"You are a professional translator. Translate the following "
                    f"text to {target_language}. Preserve any Python format strings "
                    f"like %(name)s or {{variable}} exactly as they are. "
                    f"Return only the translated text, nothing else."
                ),
            },
            {"role": "user", "content": text},
        ],
        temperature=0.3,
    )
    return response.choices[0].message.content.strip()


def translate_po_file(po_path: str, lang_code: str) -> int:
    """Übersetzt alle nicht übersetzten Einträge in einer .po-Datei."""
    language_name = TARGET_LANGUAGES.get(lang_code)
    if not language_name:
        print(f"Nicht unterstützter Sprachcode: {lang_code}")
        return 0

    po = polib.pofile(po_path)
    untranslated = po.untranslated_entries()

    if not untranslated:
        print(f"Keine nicht übersetzten Einträge in {po_path}")
        return 0

    print(f"{len(untranslated)} Einträge werden ins {language_name} übersetzt...")

    translated_count = 0
    for entry in untranslated:
        try:
            entry.msgstr = translate_text(entry.msgid, language_name)
            entry.flags.append("fuzzy")  # Als prüfungsbedürftig markieren
            translated_count += 1
        except Exception as e:
            print(f"  Fehler beim Übersetzen von '{entry.msgid[:50]}...': {e}")

    po.save()
    print(f"{translated_count} Einträge in {po_path} übersetzt")
    return translated_count


if __name__ == "__main__":
    if len(sys.argv) != 3:
        print("Verwendung: python translate_po.py <pfad/django.po> <sprachcode>")
        sys.exit(1)

    translate_po_file(sys.argv[1], sys.argv[2])

Ausführen:

python scripts/translate_po.py locale/es/LC_MESSAGES/django.po es
python scripts/translate_po.py locale/fr/LC_MESSAGES/django.po fr

Batch-Übersetzung über alle Gebietsschemata

Für größere Projekte verarbeitet ein Batch-Skript alle Gebietsschemata auf einmal:

# scripts/translate_all.py

from pathlib import Path
from translate_po import translate_po_file, TARGET_LANGUAGES

LOCALE_DIR = Path("locale")


def translate_all_locales():
    """Übersetzt nicht übersetzte Einträge für alle konfigurierten Gebietsschemata."""
    total = 0
    for lang_code in TARGET_LANGUAGES:
        po_path = LOCALE_DIR / lang_code / "LC_MESSAGES" / "django.po"
        if po_path.exists():
            count = translate_po_file(str(po_path), lang_code)
            total += count
        else:
            print(f"Keine .po-Datei unter {po_path} gefunden")

    print(f"\nGesamtübersetzungen: {total}")


if __name__ == "__main__":
    translate_all_locales()

Qualitätsprüfungs-Workflow

KI-übersetzte Einträge werden mit dem fuzzy-Flag markiert, was Django (und menschlichen Prüfern) mitteilt, dass die Übersetzung verifiziert werden muss. Dies ist beabsichtigt und wichtig:

  1. KI übersetzt — alle nicht übersetzten msgstr-Werte werden ausgefüllt und als fuzzy markiert
  2. Prüfer verifizieren — Muttersprachler prüfen Fuzzy-Einträge und entfernen das Flag nach der Genehmigung
  3. Kompilieren — standardmäßig werden nur Nicht-Fuzzy-Einträge in die kompilierten .mo-Dateien aufgenommen

Um Fuzzy-Einträge zu überprüfen:

# Fuzzy-Einträge pro Gebietsschema zählen
for lang in es fr de ja; do
    count=$(grep -c "^#, fuzzy" locale/$lang/LC_MESSAGES/django.po 2>/dev/null || echo 0)
    echo "$lang: $count fuzzy Einträge"
done

Sie können auch .po-Dateieditoren wie Poedit oder webbasierte Plattformen für den Prüfungsschritt verwenden.

CI/CD-Pipeline für Django-Lokalisierung

Die Automatisierung des Extrahieren-Übersetzen-Kompilieren-Zyklus in Ihrer CI/CD-Pipeline stellt sicher, dass Übersetzungen mit Ihrem Code synchron bleiben.

GitHub Actions-Workflow

Hier ist ein GitHub Actions-Workflow, der bei jedem Push zu main ausgeführt wird:

# .github/workflows/i18n.yml

name: i18n Translation Pipeline

on:
  push:
    branches: [main]
    paths:
      - "**.py"
      - "**.html"
      - "locale/**"

jobs:
  translate:
    runs-on: ubuntu-latest
    permissions:
      contents: write

    steps:
      - uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: "3.12"

      - name: Install dependencies
        run: |
          pip install -r requirements.txt
          pip install polib openai

      - name: Install gettext
        run: sudo apt-get install -y gettext

      - name: Extract messages
        run: python manage.py makemessages --all --no-obsolete

      - name: AI-translate new strings
        env:
          OPENAI_API_KEY: ${{ secrets.OPENAI_API_KEY }}
        run: python scripts/translate_all.py

      - name: Compile messages
        run: python manage.py compilemessages

      - name: Commit translation updates
        run: |
          git config user.name "i18n-bot"
          git config user.email "i18n-bot@users.noreply.github.com"
          git add locale/
          git diff --staged --quiet || git commit -m "chore(i18n): update translations"
          git push

Pipeline-Aufschlüsselung

Die Pipeline folgt vier Stufen:

  1. Extrahierenmakemessages scannt alle Python-Dateien und Templates nach neuen oder geänderten übersetzbaren Zeichenketten
  2. Übersetzen — das KI-Übersetzungsskript füllt alle nicht übersetzten Einträge aus und markiert sie als fuzzy
  3. Kompilierencompilemessages generiert die binären .mo-Dateien
  4. Commit — Änderungen werden zurück in das Repository übertragen, damit sie bei der nächsten Bereitstellung verfügbar sind

Für produktionskritische Anwendungen fügen Sie zwischen den Schritten Übersetzen und Kompilieren ein manuelles Genehmigungstor hinzu. Dies gibt Ihrem Team ein Zeitfenster, um Fuzzy-Übersetzungen zu überprüfen, bevor sie veröffentlicht werden.

Pre-commit-Hook für die lokale Entwicklung

Sie können auch einen Pre-commit-Hook hinzufügen, um fehlende Übersetzungen während der Entwicklung abzufangen:

#!/bin/bash
# .git/hooks/pre-commit

# Auf nicht übersetzte Zeichenketten prüfen
python manage.py makemessages --all --no-obsolete 2>/dev/null

if git diff --name-only locale/ | grep -q ".po$"; then
    echo "Warnung: Neue übersetzbare Zeichenketten erkannt."
    echo "Führen Sie 'python scripts/translate_all.py' aus, um sie zu übersetzen."
fi

Wie Better i18n mit Django integriert

Die obigen Skripte funktionieren, erfordern aber die Pflege von benutzerdefiniertem Übersetzungscode, die Verwaltung von API-Schlüsseln, den Umgang mit Rate-Limits und den Aufbau von Review-Workflows von Grund auf. Better i18n bietet eine verwaltete Plattform, die den gesamten Django-Übersetzungslebenszyklus abwickelt.

So passt Better i18n in ein Django-Projekt:

1. .po-Dateien mit Better i18n synchronisieren

Anstatt benutzerdefinierte Parse-Skripte zu schreiben, können Sie Ihre .po-Dateien direkt mit Better i18n synchronisieren. Die Plattform liest das gettext-Format nativ und ordnet jedes msgid/msgstr-Paar Übersetzungsschlüsseln zu.

2. KI-Übersetzung mit Review-Workflow

Better i18n bietet integrierte KI-Übersetzung, die speziell für Software-Lokalisierung optimiert ist. Übersetzungen durchlaufen einen verwalteten Review-Workflow, bei dem Teammitglieder Vorschläge genehmigen, bearbeiten oder ablehnen können — kein benutzerdefiniertes Tooling erforderlich.

3. Übersetzungen veröffentlichen und abrufen

Sobald Übersetzungen genehmigt sind, können Sie sie als aktualisierte .po-Dateien in Ihr Django-Projekt zurückziehen. Der Veröffentlichungsschritt stellt sicher, dass nur überprüfte Übersetzungen Ihre Codebasis erreichen.

4. CI/CD-Integration

Better i18ns CLI kann die benutzerdefinierten Skripte in Ihrer CI-Pipeline ersetzen. Der Sync-Translate-Pull-Zyklus wird zu einem einzigen Befehl in Ihrem GitHub Actions-Workflow.

Für einen tieferen Einblick in Djangos i18n-Fähigkeiten, lesen Sie unseren Django i18n Framework-Leitfaden. Wenn Sie Übersetzungstools für Ihren Workflow evaluieren, deckt unser Leitfaden zu KI-Übersetzungstools die aktuelle Landschaft ab.

FAQ

Was ist der Unterschied zwischen i18n und l10n in Django?

Internationalisierung (i18n) ist der Prozess, Ihre Django-Anwendung übersetzbar zu machen — Zeichenketten markieren, Middleware konfigurieren, URL-Muster einrichten. Lokalisierung (l10n) ist der Prozess, tatsächlich Übersetzungen bereitzustellen und gebietsschemaspezifische Formatierung für eine bestimmte Sprache und Region anzupassen. In Django aktiviert USE_I18N = True das Übersetzungs-Framework, während USE_L10N = True die lokalisierte Formatierung von Daten, Zahlen und Kalendern aktiviert.

Wie behandle ich Pluralisierung in Django?

Django behandelt Pluralisierung durch die ngettext()-Funktion in Python-Code und den {% blocktrans count %}-Template-Tag. Gettext unterstützt komplexe Pluralregeln — im Gegensatz zum Englischen, das zwei Formen hat (Singular/Plural), haben Sprachen wie Arabisch sechs Pluralformen und Polnisch hat drei. Djangos gettext-Integration behandelt all diese durch die Pluralformdefinitionen im .po-Datei-Header.

Python-Beispiel:

from django.utils.translation import ngettext

def item_count_message(count):
    return ngettext(
        "You have %(count)d item.",
        "You have %(count)d items.",
        count,
    ) % {"count": count}

Template-Beispiel:

{% load i18n %}
{% blocktrans count counter=notifications %}
    You have {{ counter }} new notification.
{% plural %}
    You have {{ counter }} new notifications.
{% endblocktrans %}

Kann ich KI verwenden, um Django-.po-Dateien zu übersetzen?

Ja. KI-Übersetzungsmodelle können .po-Dateien analysieren und msgstr-Einträge in großen Mengen übersetzen. Der empfohlene Ansatz ist, eine Bibliothek wie polib zu verwenden, um .po-Dateien programmatisch zu lesen, nicht übersetzte Zeichenketten an eine Übersetzungs-API zu senden, die Ergebnisse mit einem fuzzy-Flag zurückzuschreiben und dann die Ausgabe von Muttersprachlern prüfen zu lassen. Tools wie Better i18n automatisieren diese gesamte Pipeline einschließlich des Review-Workflows, sodass Sie keine benutzerdefinierten Skripte pflegen müssen. Die wichtigste Überlegung ist, KI-Übersetzungen immer für die menschliche Überprüfung zu markieren, bevor sie in der Produktion bereitgestellt werden.

Comments

Loading comments...