Jeśli kiedykolwiek wdrażałeś aplikację Django w więcej niż jednym języku, znasz tę procedurę. Opakowujesz swoje ciągi znaków w gettext(), uruchamiasz makemessages, otwierasz plik .po z setkami wpisów i zaczynasz tłumaczyć linia po linii. Dla dwóch języków i pięćdziesięciu ciągów jest to do zniesienia. Dla sześciu języków i pięciuset ciągów to cały dzień pracy, którego nigdy nie odzyskasz.
Ten przewodnik obejmuje pipeline internacjonalizacji (i18n) Django od początku do końca, wyjaśnia, gdzie się załamuje, i pokazuje, jak zautomatyzować bolesną część za pomocą tłumaczenia opartego na AI.
Standardowy workflow Django i18n
Wbudowany system i18n Django jest dobrze zaprojektowany. Główna pętla wygląda tak:
Krok 1: Oznacz ciągi do tłumaczenia w kodzie Python i szablonach:
from django.utils.translation import gettext as _
def dashboard(request):
welcome = _("Welcome back, %(name)s!") % {"name": request.user.first_name}
return render(request, "dashboard.html", {"welcome": welcome})
{% load i18n %}
<h1>{% trans "Account Settings" %}</h1>
<p>{% blocktrans %}You have {{ count }} unread messages.{% endblocktrans %}</p>
Krok 2: Wyodrębnij ciągi do plików .po:
python manage.py makemessages -l de -l fr -l nl
To skanuje cały kod źródłowy i generuje jeden plik .po na język, zawierający każdy tłumaczalny ciąg:
#: myapp/views.py:4
msgid "Welcome back, %(name)s!"
msgstr ""
#: templates/dashboard.html:2
msgid "Account Settings"
msgstr ""
Krok 3: Przetłumacz każdy pusty msgstr ręcznie.
Krok 4: Skompiluj gotowe pliki .po do binarnych plików .mo:
python manage.py compilemessages
Kroki 1, 2 i 4 są szybkie. Krok 3 to miejsce, gdzie proces się załamuje.
Dlaczego ręczne tłumaczenie się nie skaluje
Typowa aplikacja Django ma od 200 do 2000 tłumaczalnych ciągów. Pomnóż to przez liczbę języków docelowych, a zobaczysz poważne zaangażowanie czasowe.
To nie jest teoretyczna skarga. W znanym wątku Django Forum programista zgłosił, że spędza ponad 8 godzin na plik .po na ręcznych tłumaczeniach. Główny kontrybutor Django opisał ponad 10 godzin spędzonych na włączaniu tłumaczeń przesłanych przez społeczność do jednego wydania, głównie na przeglądzie, poprawkach formatowania i naprawianiu uszkodzonych placeholderów.
Problemy narastają z czasem:
- Placeholdery się psują. Skopiuj ciąg jak
Welcome, %(name)s!do Google Translate, a często dostaniesz z powrotemWillkommen, %(Name)s!lubBienvenue, %(nom)s!. Ta subtelna korupcja powoduje błędy w czasie wykonywania. - Spójność się rozmywa. Bez glosariusza "dashboard" jest tłumaczony jako "Instrumententafel" w jednym pliku i "Dashboard" w innym. Trzy miesiące później nikt nie pamięta, które było zamierzone.
- Sprinty dodają ciągi. Każdy branch z nową funkcjonalnością dodaje nowe tłumaczalne ciągi. Nawet jeśli zapłaciłeś za pełne tłumaczenie w poprzednim kwartale, teraz masz 40 nieprzetłumaczonych wpisów rozrzuconych po plikach
.po. - Asystenci AI pomagają raz. Możesz wkleić plik
.podo ChatGPT lub Claude i uzyskać przyzwoite wyniki. Ale w następnym sprincie, gdy pojawi się 15 nowych ciągów, promptujesz od zera, tłumaczysz cały plik od nowa i masz nadzieję, że zachowa spójność z tym, co już było.
Główna przyczyna polega na tym, że tłumaczenie jest traktowane jako jednorazowe zdarzenie, a nie jako przyrostowy, powtarzalny proces.
Automatyzacja tłumaczenia z AI
Idea jest prosta: zamiast człowieka otwierającego każdy plik .po i wypełniającego wartości msgstr, narzędzie czyta plik, wysyła nieprzetłumaczone ciągi do modelu AI lub API tłumaczeniowego, zapisuje wyniki z powrotem i zachowuje wszystko inne (komentarze, strukturę pliku, placeholdery, formy liczby mnogiej).
TranslateBot Django to pakiet open-source, który robi dokładnie to. Wpina się w system komend zarządzania Django, więc pasuje do workflow, który już masz.
Konfiguracja krok po kroku
1. Zainstaluj pakiet
pip install translatebot-django
Lub, jeśli używasz uv (zalecane):
uv add --dev translatebot-django
Instalacja jako zależność deweloperska jest celowa. TranslateBot jest potrzebny tylko podczas generowania tłumaczeń, nie w czasie wykonywania na produkcji.
2. Dodaj do INSTALLED_APPS
# settings.py
INSTALLED_APPS = [
# ...
"translatebot_django",
]
3. Skonfiguruj dostawcę AI
# settings.py
import os
TRANSLATEBOT_API_KEY = os.getenv("OPENAI_API_KEY")
TRANSLATEBOT_MODEL = "gpt-4o-mini"
TranslateBot używa LiteLLM pod spodem, co oznacza, że możesz podmienić dowolny z ponad 100 modeli, zmieniając jeden ciąg:
| Dostawca | Wartość TRANSLATEBOT_MODEL |
|---|---|
| OpenAI | gpt-4o-mini, gpt-4o |
| Anthropic | claude-sonnet-4-5-20250929 |
gemini/gemini-2.5-flash |
|
| Azure OpenAI | azure/gpt-4o-mini |
| DeepL | Użyj TRANSLATEBOT_PROVIDER = "deepl" zamiast tego |
Dla DeepL zainstaluj dodatkowy pakiet: pip install translatebot-django[deepl]. Darmowy plan DeepL daje 500 000 znaków miesięcznie bez kosztów, co wystarcza dla większości małych i średnich projektów.
4. Zdefiniuj swoje języki
# settings.py
LANGUAGES = [
("en", "English"),
("de", "German"),
("fr", "French"),
("nl", "Dutch"),
("ja", "Japanese"),
]
5. Uruchom tłumaczenie
python manage.py translate
To wszystko. TranslateBot skanuje projekt w poszukiwaniu plików .po, identyfikuje nieprzetłumaczone wpisy, wysyła je do skonfigurowanego modelu AI w zoptymalizowanych partiach i zapisuje wyniki. Istniejące tłumaczenia pozostają nietknięte.
Aby przetłumaczyć jeden język:
python manage.py translate --target-lang nl
Wynik wygląda tak:
Translating to Dutch (nl)...
Found 42 strings to translate
Translating batch 1/2...
Translating batch 2/2...
Successfully translated 42 strings
6. Skompiluj jak zwykle
python manage.py compilemessages
Twój pełny workflow to teraz:
python manage.py makemessages -l de -l fr -l nl -l ja
python manage.py translate
python manage.py compilemessages
Trzy komendy. Każdy język. Każdy sprint.
Przyrostowy z założenia
Najważniejsza cecha dla powtarzalnego workflow to tłumaczenie przyrostowe. TranslateBot tłumaczy tylko wpisy, gdzie msgstr jest puste. Jeśli masz 500 ciągów i 15 jest nowych w tym sprincie, tylko te 15 zostanie wysłanych do API.
Ma to znaczenie z praktycznych powodów:
- Koszt. Płacisz tylko za nowe ciągi, nie za cały plik.
- Szybkość. Tłumaczenie 15 ciągów trwa sekundy, nie minuty.
- Stabilność. Tłumaczenia, które już przejrzałeś i zatwierdziłeś, nigdy nie zostaną nadpisane (chyba że jawnie użyjesz
--overwrite).
Bezpieczeństwo placeholderów
Django używa kilku formatów placeholderów: %(name)s, %s, %d, {0}, {name} oraz inline'owe tagi HTML jak <strong> lub <a href="...">. Jeśli którykolwiek z nich zostanie uszkodzony w tłumaczeniu, otrzymasz błędy w czasie wykonywania lub uszkodzony markup.
TranslateBot instruuje model AI, aby zachował wszystkie formaty placeholderów i waliduje wynik. Ciąg taki jak:
Welcome to %(site_name)s! You have <strong>%(count)d</strong> new messages.
Jest tłumaczony na holenderski jako:
Welkom bij %(site_name)s! Je hebt <strong>%(count)d</strong> nieuwe berichten.
Każdy placeholder przetrwa nienaruszony.
Kontrola jakości z TRANSLATING.md
Modele AI tłumaczą lepiej, gdy rozumieją kontekst. TranslateBot szuka pliku TRANSLATING.md w katalogu głównym projektu i dołącza jego zawartość do każdego żądania tłumaczenia.
# Translation Context
## About This Project
A B2B project management tool for construction companies.
## Terminology
- "project" means a construction project, not a software project
- "plan" means a building plan/blueprint, not a subscription plan
- Keep "Gantt chart" as-is in all languages
## Tone
- German: use formal "Sie" form (business context)
- French: use formal "vous" form
- Dutch: use informal "je" form
## Do Not Translate
- Brand name: "BuildFlow"
- Feature names: "SmartSchedule", "CostTracker"
Ten plik jest wersjonowany razem z kodem, więc cały zespół dzieli ten sam kontekst tłumaczenia. Możesz również umieszczać pliki TRANSLATING.md dla poszczególnych aplikacji ze specjalistyczną terminologią. Moduł dokumentacji medycznej i moduł rozliczeniowy mogą mieć własne glosariusze.
Podgląd przed zatwierdzeniem
Flaga --dry-run pokazuje dokładnie, co zostałoby przetłumaczone, bez wykonywania jakichkolwiek wywołań API ani modyfikowania plików:
python manage.py translate --target-lang fr --dry-run
Found 15 untranslated entries
Dry run mode: skipping LLM translation
Would translate 'Welcome to our site'
Would translate 'Hello, %(name)s!'
...
Dry run complete: 15 entries would be translated
Jest to przydatne przed dużym przebiegiem tłumaczeń lub podczas wdrażania nowego członka zespołu, który chce zrozumieć, co komenda robi, zanim zobowiąże się do kosztów API.
Integracja CI/CD
Dezaktualizacja tłumaczeń jest nieunikniona bez egzekwowania. TranslateBot zawiera komendę zarządzania check_translations zaprojektowaną dla pipeline'ów CI:
# .github/workflows/ci.yml
jobs:
translations:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: astral-sh/setup-uv@v4
with:
enable-cache: true
- run: uv python install
- run: uv sync --frozen
- name: Install gettext
run: sudo apt-get update && sudo apt-get install -y --no-install-recommends gettext
- name: Check translations
run: uv run python manage.py check_translations --makemessages
Flaga --makemessages najpierw uruchamia makemessages -a --no-obsolete, upewniając się, że pliki .po odzwierciedlają aktualny kod źródłowy przed sprawdzeniem. Jeśli jakiekolwiek wpisy są nieprzetłumaczone lub rozmyte, komenda kończy działanie z kodem 1 i powoduje niepowodzenie buildu:
locale/de/LC_MESSAGES/django.po: 2 untranslated, 0 fuzzy
locale/nl/LC_MESSAGES/django.po: 0 untranslated, 1 fuzzy
CommandError: Translation check failed
Typowy workflow programisty staje się:
- Dodaj nowe tłumaczalne ciągi w branchu z nową funkcjonalnością.
- CI nie przechodzi, ponieważ te ciągi są nieprzetłumaczone.
- Uruchom
python manage.py translatelokalnie. - Zatwierdź zaktualizowane pliki
.po. - CI przechodzi.
Tłumaczenia nigdy nie rozjeżdżają się po cichu.
Tłumaczenie zawartości bazy danych
Jeśli twoja aplikacja przechowuje tłumaczalną zawartość w bazie danych (nazwy produktów, tytuły wpisów blogowych, etykiety kategorii), TranslateBot integruje się również z django-modeltranslation:
pip install translatebot-django[modeltranslation]
# Translate all registered model fields
python manage.py translate --target-lang de --models
# Translate specific models only
python manage.py translate --target-lang de --models Product Category
Ta sama logika przyrostowa obowiązuje: tłumaczone są tylko pola, w których wartość języka docelowego jest pusta.
Porównanie kosztów
Jednym z najczęstszych pytań jest to, czy tłumaczenie AI jest opłacalne w porównaniu z alternatywami. Oto przybliżone porównanie dla projektu z 500 tłumaczalnymi ciągami w 5 językach:
| Podejście | Szacunkowy koszt | Nakład czasu |
|---|---|---|
| Ręczne (czas programisty) | $0 z kieszeni, 20-40+ godzin | Bardzo wysoki |
| Profesjonalna usługa tłumaczeniowa | $500-2000+ | Niski (ale wolny zwrot) |
| Platforma lokalizacyjna SaaS | $50-200/miesiąc | Średni |
| TranslateBot + GPT-4o-mini | ~$0,05 (jednorazowo) | Minuty |
| TranslateBot + DeepL Free | $0 (do 500 tys. znaków/miesiąc) | Minuty |
| TranslateBot + Claude/GPT-4o | ~$0,30 (jednorazowo) | Minuty |
Liczby zmieniają się w zależności od liczby ciągów i języków docelowych, ale różnica rzędu wielkości jest stała. Dla bieżącej konserwacji (tłumaczenie 20-50 nowych ciągów dodawanych w każdym sprincie) koszt AI jest zasadniczo zerowy.
Najlepsze praktyki
Zacznij od --dry-run. Przed pierwszym prawdziwym uruchomieniem tłumaczenia podejrzyj, co się stanie. To buduje pewność i wyłapuje problemy konfiguracyjne na wczesnym etapie.
Zatwierdź pliki .po przed tłumaczeniem. Jeśli coś pójdzie nie tak, git checkout natychmiast przywraca czysty stan.
Napisz TRANSLATING.md od pierwszego dnia. Nawet krótki plik z opisem projektu i kilkoma regułami terminologicznymi mierzalnie poprawia jakość tłumaczenia.
Dodaj check_translations do CI. Ten pojedynczy krok zapobiega najczęstszemu trybowi awarii i18n: ciągom oznaczonym do tłumaczenia, ale nigdy faktycznie nieprzetłumaczonym.
Używaj gpt-4o-mini lub DeepL dla efektywności kosztowej. Zachowaj modele premium jak GPT-4o lub Claude dla projektów, gdzie precyzja ma znaczenie, takich jak teksty marketingowe, prawne lub specjalistyczna terminologia domenowa.
Przeglądaj krytyczne ciągi. Tłumaczenia AI są wystarczająco dobre dla większości tekstu UI, ale poproś native speakera o przegląd wszystkiego, co jest prawnie wiążące, krytyczne dla bezpieczeństwa lub skierowane do klienta w kontekście wysokiego ryzyka.
Od godzin do sekund
Framework i18n Django doskonale radzi sobie z wyodrębnianiem i kompilowaniem tłumaczeń. Luka zawsze była w samym kroku tłumaczenia, żmudnej i podatnej na błędy pracy polegającej na wypełnianiu setek wartości msgstr w wielu językach.
TranslateBot zamyka tę lukę. Zainstaluj go, skieruj na dostawcę AI i uruchom jedną komendę. Nowe ciągi zostają przetłumaczone. Istniejące ciągi pozostają nietknięte. Placeholdery pozostają nienaruszone. CI wyłapuje wszystko, co się wymknie.
Twoje pliki .po przestają być uciążliwym obowiązkiem i stają się po prostu kolejną częścią buildu.
pip install translatebot-django
Zacznij na translatebot.dev.