Oktatóanyag¶
Ez az oldal üres könyvtárból indul, és egy japánul köszönő programig jut el. Öt lépés, gettext-tapasztalat nélkül is követhető, és minden parancs azzal a kimenettel szerepel, amelyet ténylegesen ad — így minden lépésnél tudod, hogy jó úton jársz-e.
Python 3.14 vagy újabb kell hozzá, mert a t-string a 3.14 új szintaxisa. A
japán csak ennek az oldalnak a példacélnyelve, semmi sem múlik ezen a
választáson. Ha másik nyelvet szeretnél, cseréld ki a ja kódot a 4.
lépésben — az a területi kód az egyetlen dolog, amely megnevezi.
1. Telepítés¶
A [babel] extra behozza a Babelt, azt az eszközt, amely a 3. lépésben
katalógusfájlokba gyűjti az üzeneteidet. Ez fejlesztésidejű eszköz: az éles
kód a standard könyvtárral egymagában renderel.
2. Jelölj meg egy üzenetet a kódodban¶
Hozd létre az app.py fájlt:
A t"Hello {name}" úgy néz ki, mint egy f-string, de a t előtag külön
tartja a szöveget és az értéket ahelyett, hogy azon nyomban összeolvasztaná
őket. Épp ez a szétválasztás teszi lehetővé, hogy a tr() a teljes
Hello {name} mondathoz keressen fordítást, és csak utána illessze be az
értéket.
Futtasd is le rögtön:
Fordítás még nincs telepítve, ezért a forrásszöveg úgy jelenik meg, ahogy van. Az ezt a könyvtárat használó program soha nem igényel katalógust a futáshoz — az angol (vagy bármi legyen is a forrásnyelved) a beépített tartalék.
3. Nyerd ki az üzeneteket¶
A fordítók rendszerint katalógusokból dolgoznak, nem forráskódból, ezért egy katalógusnak nevezett kis fájl jár közted és köztük. Az első lépés efelé az, hogy összegyűjtsük a kódból az összes megjelölt üzenetet.
Mondd meg a Babelnek, hol találja az üzeneteidet: hozd létre a babel.cfg
fájlt:
Ezután nyerd ki őket egy sablonfájlba (.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
A locales/messages.pot mostantól üzenetenként egy bejegyzést tartalmaz:
A msgid az a kulcs, amelyet a kódod ki fog keresni. Az üres msgstr helyére
kerül a fordítás — de nem ebben a fájlban: a .pot egy sablon, a következő
lépés pedig nyelvenként egyszer lemásolja.
4. Fordítás és bináris fordítás¶
Hozd létre a japán katalógust a sablonból:
$ pybabel init -i locales/messages.pot -d locales -l ja
creating catalog locales/ja/LC_MESSAGES/messages.po based on locales/messages.pot
Nyisd meg a locales/ja/LC_MESSAGES/messages.po fájlt, és töltsd ki a
msgstr értékét:
A {name} maradjon pontosan úgy, ahogy van — a helyőrző az, ami révén az
érték megtalálja a helyét a lefordított mondaton belül, a fordítás pedig
szabadon oda mozgathatja, ahová a célnyelvnek kell. Valódi projektben ezt a
.po fájlt adod oda egy fordítónak, vagy töltöd fel egy fordítási
platformra; a formátum mindkét esetben ugyanaz.
A katalógusokat szövegként szerkesztjük, de bináris formában (.mo) töltődnek
be, ezért fordítsd le őket:
$ pybabel compile -d locales
compiling catalog locales/ja/LC_MESSAGES/messages.po to locales/ja/LC_MESSAGES/messages.mo
Ez a parancs egyben biztonsági háló is. Ha a fordítás megrongálta volna a
helyőrzőt — mondjuk {name} helyett {nome} szerepelne —, nem engedné át:
$ 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.
Egy fenntartást érdemes már most tudni: jelenti a hibát és nem nulla
kilépési kóddal áll le, de a .mo fájlt attól még kiírja. Valódi projekten a
CI-nak kell megállnia ezen a kilépési kódon — az Éles
üzemben ezt állítja be.
5. Futtasd¶
A 2–4. lépés a tr() függvényt használta, amely katalógust keres, és nem
talál egyet sem. Most, hogy van, töltsd be és kösd be egyszer: a Translator
tartja a katalógust, hogy a hívási helyeknek ne kelljen megnevezniük, a _
pedig az eredmény szokásos gettext-neve.
Irányítsd az app.py fájlt a lefordított katalógusra. Kattints a jelölőkre,
hogy lásd, melyik sor mit csinál:
import gettext
from gettext_tstrings import Translator
_ = Translator(gettext.translation("messages", localedir="locales", languages=["ja"])) # (1)!
name = "Ada"
print(_(t"Hello {name}")) # (2)!
- A standard könyvtár betölti a lefordított
.mofájlt, aTranslatorpedig egy hívható objektumhoz köti. A_a gettext szokásos neve arra, hogy „fordítsd le ezt” — azért rövid, mert minden felhasználónak szánt szövegnél megjelenik. Ugyanazt a fordítást végzi, mint atr, csak egyetlen katalógushoz kötve. - A híváskor: a t-string szövegéből lesz a
Hello {name}keresőkulcs, a katalógus aこんにちは {name}választ adja, a választ összeveti a rendszer a forrás helyőrzőivel, és csak ezután kerül be az érték.
Ez az egész ciklus, és megéri egyetlen képként is látni:
flowchart LR
mark["1–2 megjelölés<br>t-stringek a kódban"] --> extract["3 kinyerés<br>messages.pot"]
extract --> translate["4 fordítás<br>ja/…/messages.po"]
translate --> compile["4 bináris fordítás<br>ja/…/messages.mo"]
compile --> run["5 futtatás<br>こんにちは Ada"]
Megjelölés → kinyerés → fordítás → bináris fordítás → futtatás. Ezen a webhelyen minden más ennek az öt lépésnek valamelyikét finomítja.
Merre tovább¶
- Miért t-string? — mitől véd meg ez a felépítés a
%(name)s, a.format()és a$-stringek mellett. - Kézikönyv — többes számok, kérésenkénti nyelvek, késleltetett szövegek, és mi történik futásidőben, ha egy katalógus mégis hibás.
- Éles üzemben — ugyanez a ciklus úgy, ahogy egy csapat működteti, hétről hétre: katalógusfrissítés, CI-kapuk és fordítási platformok.
- Kinyerés — a teljes
pybabel-referencia: saját függvénynevek, szigorú CI-mód, és a katalógusaidat őrző ellenőrzések. - Migráció — ha abban a projektben, amelyben valójában csinálni szeretnéd, már vannak gettext-katalógusok.
- Fordítóknak — az az egy oldal, amelyet oda kell adni
annak, aki azokat a
msgstrsorokat kitölti.