Migracija¶
Če vaš projekt gettext že uporablja, so vprašanja, ki odločijo, ali je to knjižnico mogoče prevzeti, ozka: ali razveljavi kataloge, ki jih imate, ali lahko sobiva s kodo, ki je še niste pripravljeni spremeniti, in koliko selitve se mora zgoditi naenkrat. Odgovori, najkrajši najprej:
| Vprašanje | Odgovor |
|---|---|
Ali obstoječe datoteke .po in .mo še delujejo? |
Da. Iste datoteke, ista orodja. |
| Ali lahko stari in novi klici živijo v eni datoteki? | Da, in ena preslikava ekstraktorja pokrije oboje. |
| Ali se msgid spremeni? | Iz .format() ne. Iz %-oblikovanja da. |
| Ali se mora ves projekt preseliti naenkrat? | Ne. Eno klicno mesto je veljavna sprememba. |
| Kaj pa Jinja, Djangove predloge, JavaScript? | Nedotaknjeni, isti katalogi. |
Preostanek te strani so podrobnosti za vsakim od teh odgovorov.
Iz .format(): msgid se ne spremeni¶
To je primer, pri katerem migracija ne stane skoraj nič. Sporočilo iz
str.format in sporočilo iz t-niza izpeljeta isti katalogni ključ, saj je
ključ v obeh primerih besedilo, v katerem ostane {name}:
# Before
_("Hello {name}").format(name=name)
# After — the msgid is still "Hello {name}"
tr(t"Hello {name}")
Obstoječi prevod torej ostane pripet. Če izhajate iz kataloga, ki vsebuje
spremenite klic, znova izvlecite in posodobite:
$ pybabel extract -F babel.cfg -o locales/messages.pot .
extracting messages from app.py (encoding="utf-8")
writing PO template file to locales/messages.pot
$ pybabel update -i locales/messages.pot -d locales
updating catalog locales/ja/LC_MESSAGES/messages.po based on locales/messages.pot
Vnos, ki se vrne, se razlikuje v dveh vrsticah metapodatkov in v ničemer drugem — v označevalnem komentarju, ki ga prepozna kot sporočilo iz t-niza, in v številki izvorne vrstice:
Nobene zastavice fuzzy, nobenega ponovnega prevajanja, v nobenem jeziku.
Sporočilo se izriše takoj:
$ pybabel compile -d locales
compiling catalog locales/ja/LC_MESSAGES/messages.po to locales/ja/LC_MESSAGES/messages.mo
$ python app.py
こんにちは Ada
update --check bo kataloge javil kot zastarele
Tisti označevalni komentar in premaknjene številke vrstic zadoščajo, da
pybabel update --check pove, da je treba katalog obnoviti, saj primerja
celoten vnos in ne le prevoda. Resnični pybabel update poženite v istem
commitu kot spremembo kode in kataloge commitajte skupaj z njo — ista
navada, kot jo zaščita v CI zahteva že
zdaj.
Iz %-oblikovanja: msgid se spremeni, zato prevodi postanejo ohlapni¶
Sintaksa printf živi znotraj sporočila, zato njena zamenjava prepiše
katalogni ključ. Tega ni mogoče zaobiti in to je poštena cena slovesa od
%(name)s:
pybabel update novo sporočilo prepozna kot bližnjega sorodnika
odstranjenega in stari prevod prenese s sabo, označen kot ohlapen:
#. gettext-tstrings
#: app.py:4
#, fuzzy, python-brace-format, python-format
msgid "Hello {name}"
msgstr "こんにちは %(name)s"
O tem stanju je treba vedeti troje:
- Med izvajanjem se ne pokvari nič. Ohlapni vnosi so izključeni iz
kompiliranega
.mo, zato aplikacija izrisuje izvorno sporočilo, dokler par ne potrdi človek — ista poslabšava, skozi katero gre vsako preoblikovano sporočilo. - CI ostane zelen, dokler so ohlapni. Preverjevalnik ograd ohlapne vnose
preskoči, natanko kot
msgfmt --check-format, ker vnos, ki ne more doseči izvajanja, ne sme podreti gradnje. V trenutku, ko prevajalec zastavico izbriše, je vnos preverjen kot vsak drug — tako se%(name)s, pozabljen v potrjenem prevodu, ujame prav takrat, ko bi se sicer začel izrisovati. - Stara zastavica
python-formatpotuje zraven in jo je treba izbrisati skupaj z zastavicofuzzy, sicer bomsgfmt --check-formatna sporočilo z zavitimi oklepaji še naprej uporabljal pravila printf.
Pri imenovanih ogradah printf je urejanje mehansko — %(name)s postane
{name} in nič drugega se ne premakne —, zato je velik katalog en skriptni
prehod, ki mu sledi prevajalčev pregled, in ne ponovno prevajanje. Pozicijski
%s ni mehanski: nima imena, ki bi ga prenesli, in prav izbira tega imena je
bistvo spremembe.
Migracija lahko zato napreduje s hitrostjo, ki jo dopušča pregled: nepretvorjen ohlapen vnos je viden kos dela v katalogu, ne pokvarjena gradnja.
Stari in novi klici sobivajo¶
Ekstraktor, ki bere t-nize, bere tudi običajne klice gettexta, zato ena preslikava pokrije datoteko sredi migracije:
from gettext_tstrings import tr
from myapp.i18n import _
name = "Ada"
print(_("Save changes"))
print(tr(t"Hello {name}"))
Obe sporočili pristaneta v isti predlogi in le tisto iz t-niza nosi označevalni komentar, ki vklopi dodatno preverjanje te knjižnice:
#: app.py:5
msgid "Save changes"
msgstr ""
#. gettext-tstrings
#: app.py:6
#, python-brace-format
msgid "Hello {name}"
msgstr ""
Prepozna _(), štiri standardna imena gettexta, vzdevka tr() / ntr() in
odložena lazy_gettext() / lazy_pgettext(). Lastnega pomočnika je treba
imenovati v preslikavi.
Med izvajanjem sta sloga enako neodvisna: gettext.translation() vrne en
prevodni objekt, iz njega pa berejo tako _ kot vstopne točke te knjižnice.
Kaj se ne premakne¶
- Predlogni jeziki. Jinja2
{% trans %}, Djangove predlogne značke in njihovi Babelovi ekstraktorji delujejo nespremenjeni naprej in še vedno polnijo iste kataloge PO. T-nizi so pythonska sintaksa; veljajo za pythonsko izvorno kodo. - Vaše katalogne datoteke. Nobene spremembe formata, nobene nove datoteke, nobenega koraka pretvorbe.
- Vaša prevajalska platforma. Izmenjava prek
.poje enaka, zastavicapython-brace-format, ki jo nosi sporočilo iz t-niza, pa je ista zastavica, kot jo nosi sporočilo iz.format()— zato nadzor kakovosti ograd deluje naprej. - Koda, ki ni pythonska. Katalog za JavaScript ali C v istem projektu ostane neprizadet.
Kontrolni seznam za migracijo¶
- Dodajte dodatek
babeltam, kjer tečepybabel, in preslikavopythonvbabel.cfgspremenite v metodogettext_tstrings— ena preslikava tedaj pokrije oba sloga,-kpa za običajne klice deluje naprej. - Najprej pretvorite klicna mesta z
.format(). Znova izvlecite, poženitepybabel updatein kataloge commitajte skupaj s kodo; ohlapnih vnosov ne pričakujte. - Klicna mesta z
%-oblikovanjem pretvarjajte v svežnjih, ki jih zmorete spraviti skozi pregled, pri čemer prenesene ograde prepišete ter zastavicifuzzyinpython-formatizbrišete. - Popravite, kar omejitev zavrne: interpolacija mora biti preprosto ime, zato
t"Hello {user.name}"najprej postane lokalna spremenljivka. To je urejanje klicnega mesta, ne kataloga. - Ko je pometanje končano, v preslikavi ekstraktorja vklopite
strict = true, da sporočilo, ki ga ni mogoče izvleči, podre gradnjo, namesto da bi izginilo iz predloge. - Dodajte preverjanje med izvajanjem iz V produkciji:
po eno sporočilo na odpremljeni jezik izrišite skozi strogi
Translator.
Koraka 2 in 3 sta običajna commita. Nič na tem seznamu ne potrebuje enega samega velikega preklopnega dne.