Handledning¶
Den här sidan går från en tom katalog till ett program som hälsar på japanska. Fem steg, ingen gettext-erfarenhet förutsätts, och varje kommando visas med den utdata det faktiskt producerar — så att du i varje steg vet om du är på rätt spår.
Du behöver Python 3.14 eller nyare, eftersom t-strings är ny syntax i 3.14.
Japanska är sidans exempelmål, men ingenting hänger på det valet. För att
använda ett annat språk byter du ut ja i steg 4 — den språkkoden är det enda
som namnger det.
1. Installera¶
Extrat [babel] drar in Babel, verktyget som samlar dina meddelanden i
katalogfiler i steg 3. Det är ett utvecklingsverktyg: produktionskod renderar
med enbart standardbiblioteket.
2. Markera ett meddelande i din kod¶
Skapa app.py:
t"Hello {name}" ser ut som en f-string, men prefixet t håller texten och
värdet åtskilda i stället för att slå ihop dem på plats. Den åtskillnaden är
vad som låter tr() slå upp en översättning för hela meningen Hello {name}
och sätta in värdet efteråt.
Kör det nu:
Inga översättningar är installerade ännu, så källtexten renderas som den är. Ett program som använder det här biblioteket kräver aldrig en katalog för att köra — engelska (eller vad ditt källspråk nu är) är den inbyggda reservlösningen.
3. Extrahera meddelandena¶
Översättare arbetar oftast utifrån kataloger snarare än utifrån källkod, så en liten fil som kallas katalog reser mellan dig och dem. Första steget mot en sådan är att samla ihop varje markerat meddelande ur koden.
Berätta för Babel hur den hittar dina meddelanden genom att skapa babel.cfg:
Extrahera sedan till en mallfil (.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 innehåller nu en post per meddelande:
msgid är nyckeln din kod slår upp. Den tomma msgstr är där en översättning
hamnar — men inte i den här filen: en .pot är en mall, och nästa steg
kopierar den en gång per språk.
4. Översätt och kompilera¶
Skapa den japanska katalogen från mallen:
$ pybabel init -i locales/messages.pot -d locales -l ja
creating catalog locales/ja/LC_MESSAGES/messages.po based on locales/messages.pot
Öppna locales/ja/LC_MESSAGES/messages.po och fyll i msgstr:
Behåll {name} exakt som det är — platshållaren är hur värdet hittar sin
plats i den översatta meningen, och översättningen får fritt flytta den dit
målspråket behöver den. I ett riktigt projekt är den här .po-filen vad du
lämnar över till en översättare eller laddar upp till en
översättningsplattform; formatet är detsamma i båda fallen.
Kataloger redigeras som text men läses in i binär form (.mo), så kompilera:
$ pybabel compile -d locales
compiling catalog locales/ja/LC_MESSAGES/messages.po to locales/ja/LC_MESSAGES/messages.mo
Det här kommandot är också ett skyddsnät. Hade översättningen skadat
platshållaren — säg {nome} i stället för {name} — skulle det vägra
släppa igenom:
$ 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.
En sak värd att känna till redan nu: det rapporterar felet och avslutar med
nollskild status, men skriver .mo-filen ändå. I ett riktigt projekt är det CI
som måste stanna på den statusen — I produktion
sätter upp det.
5. Kör det¶
Steg 2–4 använde tr(), som letar efter en katalog och inte hittar någon. Nu
när det finns en: läs in den och bind den en gång. Translator håller en
katalog så att anropsställena slipper namnge den, och _ är det konventionella
gettext-namnet för resultatet.
Peka app.py mot den kompilerade katalogen. Klicka på markörerna för att se
vad varje rad gör:
import gettext
from gettext_tstrings import Translator
_ = Translator(gettext.translation("messages", localedir="locales", languages=["ja"])) # (1)!
name = "Ada"
print(_(t"Hello {name}")) # (2)!
- Standardbiblioteket läser in den kompilerade
.mo-filen, ochTranslatorbinder den till en anropbar funktion._är det konventionella gettext-namnet för "översätt det här" — kort eftersom det förekommer vid varje sträng som möter användaren. Den utför samma översättning somtr, bunden till en katalog. - Vid anropet: t-strängens text blir uppslagsnyckeln
Hello {name}, katalogen svararこんにちは {name}, svaret kontrolleras mot källans platshållare, och först därefter sätts värdet in.
Det är hela kretsloppet, och det är värt att se som en enda bild:
flowchart LR
mark["1–2 markera<br>t-strings i koden"] --> extract["3 extrahera<br>messages.pot"]
extract --> translate["4 översätt<br>ja/…/messages.po"]
translate --> compile["4 kompilera<br>ja/…/messages.mo"]
compile --> run["5 kör<br>こんにちは Ada"]
Markera → extrahera → översätt → kompilera → kör. Allt annat på den här webbplatsen är en förfining av något av dessa fem steg.
Vart härnäst¶
- Varför t-strings — vad den här designen skyddar dig mot,
jämfört med
%(name)s,.format()och$-strängar. - Guide — pluralformer, språk per förfrågan, uppskjutna strängar, och vad som händer vid körning när en katalog ändå är fel.
- I produktion — samma kretslopp så som ett team kör det, vecka efter vecka: kataloguppdateringar, CI-grindar och översättningsplattformar.
- Extrahering — den fullständiga
pybabel-referensen: egna funktionsnamn, strikt CI-läge och kontrollerna som vaktar dina kataloger. - Migrering — om projektet du egentligen vill göra det här i redan har gettext-kataloger.
- För översättare — den enda sidan att räcka över till den
som fyller i de där
msgstr-raderna.