Tutorial¶
Deze pagina gaat van een lege map naar een programma dat in het Japans groet. Vijf stappen, geen gettext-ervaring verondersteld, en elk commando wordt getoond met de uitvoer die het werkelijk produceert — zodat je bij elke stap weet of je op koers ligt.
Je hebt Python 3.14 of nieuwer nodig, omdat t-strings nieuwe syntaxis zijn in
3.14. Japans is het voorbeelddoel van deze pagina, maar niets hangt van die
keuze af. Wil je een andere taal gebruiken, vervang dan ja in stap 4 — die
locale-code is het enige dat haar benoemt.
1. Installeren¶
De [babel]-extra haalt Babel binnen, de tool die in stap 3 je berichten in
catalogusbestanden verzamelt. Het is een tool voor ontwikkeltijd:
productiecode rendert met alleen de standaardbibliotheek.
2. Markeer een bericht in je code¶
Maak app.py aan:
t"Hello {name}" ziet eruit als een f-string, maar het voorvoegsel t houdt
de tekst en de waarde gescheiden in plaats van ze ter plekke samen te voegen.
Die scheiding is wat tr() in staat stelt een vertaling op te zoeken voor de
hele zin Hello {name} en de waarde er daarna in te voegen.
Voer het nu uit:
Er zijn nog geen vertalingen geïnstalleerd, dus de brontekst wordt ongewijzigd gerenderd. Een programma dat deze bibliotheek gebruikt vereist nooit een catalogus om te draaien — Engels (of wat je brontaal ook is) is de ingebouwde fallback.
3. Extraheer de berichten¶
Vertalers werken meestal vanuit catalogi in plaats van vanuit broncode, dus een klein bestand dat een catalogus heet, reist tussen jou en hen. De eerste stap ernaartoe is elk gemarkeerd bericht uit de code verzamelen.
Vertel Babel hoe het je berichten vindt door babel.cfg aan te maken:
Extraheer vervolgens naar een sjabloonbestand (.pot):
$ mkdir -p locales
$ pybabel extract -F babel.cfg -c "Translators:" -o locales/messages.pot .
extracting messages from app.py (encoding="utf-8")
writing PO template file to locales/messages.pot
locales/messages.pot bevat nu één entry per bericht:
msgid is de sleutel die je code zal opzoeken. De lege msgstr is waar een
vertaling komt te staan — maar niet in dit bestand: een .pot is een
sjabloon, en de volgende stap kopieert het één keer per taal.
4. Vertaal en compileer¶
Maak de Japanse catalogus aan vanuit het sjabloon:
$ pybabel init -i locales/messages.pot -d locales -l ja
creating catalog locales/ja/LC_MESSAGES/messages.po based on locales/messages.pot
Open locales/ja/LC_MESSAGES/messages.po en vul de msgstr in:
Houd {name} exact zoals hij is — de placeholder is hoe de waarde zijn plek
vindt in de vertaalde zin, en de vertaling mag hem vrij verplaatsen naar waar
de doeltaal hem nodig heeft. In een echt project is dit .po-bestand wat je
aan een vertaler overhandigt of naar een vertaalplatform uploadt; het formaat
is in beide gevallen hetzelfde.
Catalogi worden als tekst bewerkt maar in binaire vorm (.mo) geladen, dus
compileer:
$ pybabel compile -d locales
compiling catalog locales/ja/LC_MESSAGES/messages.po to locales/ja/LC_MESSAGES/messages.mo
Dit commando is ook een vangnet. Had de vertaling de placeholder beschadigd —
bijvoorbeeld {nome} in plaats van {name} — dan zou het weigeren door te
laten:
$ pybabel compile -d locales
error: locales/ja/LC_MESSAGES/messages.po:24: translation does not match the
source placeholders: {name} is missing; {nome} is not in the source message
1 errors encountered.
Eén kanttekening die je nu al moet kennen: hij meldt de fout en eindigt met
een niet-nul exitstatus, maar schrijft de .mo toch. Op een echt project is
het CI die op die exitstatus moet stoppen —
In productie zet dat op.
5. Voer het uit¶
Stap 2–4 gebruikten tr(), die naar een catalogus zoekt en er geen vindt. Nu
er een bestaat, laad je hem en bind je hem één keer: Translator houdt een
catalogus vast zodat de aanroeplocaties hem niet hoeven te benoemen, en _
is de conventionele gettext-naam voor het resultaat.
Richt app.py op de gecompileerde catalogus. Klik op de markeringen om te
zien wat elke regel doet:
import gettext
from gettext_tstrings import Translator
_ = Translator(gettext.translation("messages", localedir="locales", languages=["ja"])) # (1)!
name = "Ada"
print(_(t"Hello {name}")) # (2)!
- De standaardbibliotheek laadt de gecompileerde
.mo, enTranslatorbindt hem aan een aanroepbaar object._is de conventionele gettext-naam voor "vertaal dit" — kort omdat hij bij elke gebruikersgerichte string voorkomt. Hij voert dezelfde vertaling uit alstr, gebonden aan één catalogus. - Bij de aanroep: de tekst van de t-string wordt de opzoeksleutel
Hello {name}, de catalogus antwoordtこんにちは {name}, het antwoord wordt gecontroleerd tegen de bron-placeholders, en pas dan wordt de waarde ingevoegd.
Dat is de hele lus, en het is de moeite waard hem als één plaatje te zien:
flowchart LR
mark["1–2 markeren<br>t-strings in code"] --> extract["3 extraheren<br>messages.pot"]
extract --> translate["4 vertalen<br>ja/…/messages.po"]
translate --> compile["4 compileren<br>ja/…/messages.mo"]
compile --> run["5 uitvoeren<br>こんにちは Ada"]
Markeren → extraheren → vertalen → compileren → uitvoeren. Al het andere op deze site is een verfijning van een van die vijf stappen.
Waar nu heen¶
- Waarom t-strings — waar dit ontwerp je tegen beschermt,
vergeleken met
%(name)s,.format()en$-strings. - Handleiding — meervouden, talen per request, uitgestelde strings, en wat er tijdens runtime gebeurt als een catalogus toch fout is.
- In productie — dezelfde lus zoals een team hem draait, week na week: catalogi bijwerken, CI-poorten en vertaalplatforms.
- Extractie — de volledige
pybabel-referentie: eigen functienamen, strikte CI-modus, en de controles die je catalogi bewaken. - Migratie — als het project waarin je dit echt wilt doen al gettext-catalogi heeft.
- Voor vertalers — de ene pagina die je overhandigt aan wie
die
msgstr-regels invult.