Handbók¶
Þessi síða er uppflettiritið um keyrslutímann: allt sem forritskóðinn þinn gerir með þessu safni þegar þýðingaskrár eru til. Hafir þú ekki enn séð alla hringrásina — merkja, draga út, þýða, vistþýða, keyra — þá gengur kennsluefnið hana einu sinni á fimm mínútum; að búa til og staðfesta þýðingaskrár er tekið fyrir í Útdrætti, og hvernig teymi heldur hringrásinni gangandi — uppfærsluferli, CI, þýðingavettvangar — er Í rekstri.
Hvaða aðgangsstað ætti ég að nota?¶
Pakkinn flytur út nokkrar leiðir til að þýða skilaboð af því að forrit binda tungumál á nokkra ólíka vegu. Veldu eftir því hvernig forritið þitt ákveður á hvaða tungumáli það er:
| Aðstæður þínar | Notaðu |
|---|---|
| Eitt tungumál fyrir allt ferlið — skipanalínutól, skjáborðsforrit, skrifta | Translator, kallað sem _ |
| Eitt tungumál fyrir hverja beiðni eða hvert ósamstillt verk — vefforrit | use_translations() utan um verkið, síðan tr() |
| Skilaboð skilgreind við innflutning — merking á reit, talnaruna, fasti | lazy_gettext() eða lazy_pgettext() |
| Fjöldi ræður orðalaginu | ngettext() / npgettext(), í hvaða mynd sem er hér að ofan |
| Mynstur birt án þess að þýðingaskrá komi við sögu | compile_template() |
Allt hér að neðan eru þessi fimm, í þessari röð.
Að binda þýðingaskrá¶
Ráðlagða lagið speglar klasabundna notkun gettext: bittu eitt staðlað
þýðingahlutfall einu sinni og notaðu kallanlega vinnsluhlutinn sem _.
import gettext
from gettext_tstrings import Translator
translations = gettext.translation("messages", localedir="locales", languages=["ja"])
_ = Translator(translations)
name = "Ada"
print(_(t"Hello {name}")) # こんにちは Ada
n = 3
print(_.ngettext(t"One file", t"{n} files", n)) # picks the right plural form for n
filename = "report.txt"
print(_.pgettext("button", t"Open {filename}")) # "button" disambiguates homonyms
Föllin á einingarsviði fylgja nöfnum staðalsafnsins og kallvenju þess um viðföng eingöngu eftir stöðu:
from gettext_tstrings import gettext, ngettext, npgettext, pgettext
gettext(t"Hello {name}", translations=translations)
ngettext(t"One file", t"{n} files", n, translations=translations)
pgettext("button", t"Open {filename}", translations=translations)
npgettext("inbox", t"One message", t"{n} messages", n, translations=translations)
tr og ntr eru nákvæm samheiti gettext og ngettext.
Tungumál eftir beiðni¶
Vefumgjörð velur tungumál fyrir hverja beiðni. Bittu þýðingar beiðninnar við núverandi samhengi og hvert kall á einingarsviði leysist yfir í það tungumál, með öruggum hætti þvert á samhliða beiðnir:
from gettext_tstrings import tr, use_translations
def handle(request):
name = request.user.display_name
translations = load_translations(request.locale)
with use_translations(translations):
return render(tr(t"Hello {name}"))
set_translations(translations) bindur án with-blokkar, fyrir umgjarðir
sem stýra líftíma beiðninnar sjálfar; get_translations() les núverandi
bindingu. Skýrt translations=-viðfang gengur alltaf framar samhenginu, og
óbundið samhengi fellur aftur í altækt uppsettu gettext-föllin úr
staðalsafninu. Útfærð dæmi fyrir Flask og ASGI-millilag eru á síðunni
Í rekstri.
Frestuð þýðing¶
t-strengur grípur gildi sín strax, sem er rangt fyrir streng sem er skilgreindur við innflutning — merking á eyðublaði, gildi í talnaupptalningu, fasti á einingarsviði — og þarf að birtast á því tungumáli sem er virkt þegar hann er notaður.
from gettext_tstrings import lazy_gettext, lazy_pgettext, use_translations
SAVE = lazy_gettext(t"Save changes") # defined once, at import
OPEN = lazy_pgettext("button", t"Open file")
with use_translations(japanese):
assert str(SAVE) == "変更を保存" # rendered here, in this language
LazyString birtist gegnum str(), format() og f-strengi, og telst jafn
birtum texta sínum.
Af ásettu ráði ekki tætanlegt
Texti LazyString veltur á virka tungumálinu, svo tætigildi myndi
breytast við tungumálaskipti og skemma hljóðlaust hvert mengi eða
orðabók sem geymdi hann. Kallaðu á str() fyrst ef þú þarft lykil.
strict er ákveðið þar sem skilaboðin eru skrifuð, ekki þar sem þau eru birt:
Frestaður strengur er birtur þar sem hann er á endanum notaður — inni í
sniðmáti, í eyðublaði, í línu í atburðaskrá — og sá staður veit sjaldnast
hvort um prófkeyrslu eða rekstur er að ræða. Að gefa strict=True við
skilgreininguna er það sem lætur sama valið um
hávært í CI, eftirgefanlegt í rekstri
gilda líka um streng sem er ekki birtur á kallstað sínum.
Fleirtölumyndir velta á fjölda sem er þekktur á keyrslutíma, svo birtu þær
strax með ngettext þar sem fjöldinn er kunnur.
Mörg tungumál í einu¶
Ein beiðni þarf oft fleiri en eitt tungumál: síða sem er birt fyrir lesandann og setur um leið tilkynningu í röð til reiknings sem er stilltur á annað, eða samantekt sem vitnar í hvern þátttakanda á hans eigin. Bindingar hreiðrast, og þegar innri blokkinni sleppir tekur sú ytri aftur við.
with use_translations(reader):
page = tr(t"Hello {name}")
with use_translations(recipient):
notice = tr(t"Hello {name}") # the recipient's language
footer = tr(t"Hello {name}") # the reader's again
Þegar listi af viðtakendum á í hlut vinna frestaðir strengir verkið: skilaboðin eru skrifuð einu sinni, við innflutning, og birt einu sinni fyrir hvert tungumál.
SUBJECT = lazy_gettext(t"Your order shipped")
for user in users:
with use_translations(load_translations(user.locale)):
send(user.email, str(SUBJECT))
Bindingin er ContextVar, ekki stafli á sameiginlegum hlut, svo að beiðnir
sem skarast geta ekki gripið tungumál hver annarrar — þar með talið tilvikið
þar sem þær yfirgefa blokkirnar sínar í sömu röð og þær gengu inn í þær, en
það er einmitt fléttan sem stafli af þessu tagi ræður ekki við. Það er ódýrt
að hlaða þýðingaskrá fyrir hvert tungumál: gettext.translation() þáttar
hverja .mo-skrá einu sinni og réttir út afrit sem deila þáttuðu skránni.
Hvort vinnuþráður erfir bindinguna fer eftir byggingunni
Ber threading.Thread, eða ThreadPoolExecutor.submit, byrjar annaðhvort
með afriti af samhengi kallandans eða með tómu samhengi, og hvort þeirra
það verður ræðst af sys.flags.thread_inherit_context — sem er satt
sjálfgefið í free-threaded byggingum en ósatt í öllum öðrum. Sami kóðinn
birtir því bundna tungumálið á 3.14t en altæku gettext-þýðingaskrá
ferlisins á 3.14. Sendu samhengið með í stað þess að reiða þig á
sjálfgefna hegðun:
asyncio.to_thread gerir þetta þegar fyrir þig.
Staðfærð gildi¶
Þetta safn ákveður hvar gildi birtist í þýddum skilaboðum. Það staðfærir
ekki gildið sjálft. {amount:,.2f} er Python-sniðlýsing með fastri hegðun —
komma á hverja þrjá tölustafi og punktur á undan aukastöfunum — og hún
framleiðir sömu stafina á hvaða tungumáli sem skilaboðin eru:
Þýska ritar þá tölu 1.234,50, franska 1 234,50, og hindí flokkar
1234567 sem 12,34,567 fremur en 1,234,567. Tölur, gjaldmiðlar,
dagsetningar, tímar og einingar heyra undir Babel. Sníddu
gildið fyrst, settu svo fullgerða strenginn á sinn stað:
from babel.numbers import format_currency
total = format_currency(amount, "EUR", locale=locale)
tr(t"Your order comes to {total}")
Í skilaboðum sem telja gegnir talan tveimur hlutverkum — hún velur fleirtölumyndina og hún birtist í textanum — og aðeins hið síðara er staðfært. Haltu hráa fjöldanum fyrir valið og réttu sniðna strenginn til birtingar:
from babel.numbers import format_decimal
shown = format_decimal(n, locale=locale)
_.ngettext(t"One file", t"{shown} files", n)
Að sníða á undan kallinu er líka það sem heldur sniðlýsingu utan þýðingaskrárinnar: það sem þýðandi sér er fullgerður textabútur, ekki tala ásamt fyrirmælum um hvernig eigi að birta hana.
Hvað gerist þegar þýðingaskrá er röng¶
Ef staðgenglar þýðingar stemma ekki við frumtextann — reitur sem vantar, er óþekktur eða hefur fengið nýtt snið og slapp gegnum athugunina, úr handritaðri MO-skrá, þýðingaskrá frá þriðja aðila eða keðju sem sleppir athuguninni — þá er sjálfgefið að birta frumtextaskilaboðin fremur en að varpa. Þetta speglar samning gettext sjálfs um að léleg þýðingaskrá brjóti aldrei forritið.
Þegar Hello {name} er þýtt sem こんにちは {nombre} tekst birtingin og ein
viðvörun fer í atburðaskrárrit gettext_tstrings:
WARNING gettext_tstrings: invalid translation for msgid 'Hello {name}'; using
source text: translation does not match the source placeholders: {name} is
missing; {nombre} is not in the source message
Viðvörunin kemur einu sinni fyrir hver skilaboð og hvert mynstur, ekki einu sinni við hverja birtingu, svo að biluð færsla í þýðingaskrá flæðir ekki yfir atburðaskrána.
Veldu að falla hávært fyrir prófanir og CI:
strict = Translator(translations, strict=True)
tr(t"Hello {name}", translations=translations, strict=True)
Sama uppfletting varpar þá, með sömu setningu án helmingsins um „using source text“:
>>> strict(t"Hello {name}")
Traceback (most recent call last):
...
gettext_tstrings.errors.InvalidTranslationError: translation does not match the
source placeholders: {name} is missing; {nombre} is not in the source message
Þessi skilaboð eru skrifuð fyrir þann sem getur brugðist við þeim, og þegar
þýðingaskrá á í hlut er það oftar þýðandi en forritari — svo að þar sem
staðgengill sýnist vera til staðar en er það ekki útskýra skilaboðin hvers
vegna fremur en að endurtaka að hann vanti. Breiðir slaufusvigar, tvöfaldað
{{name}}, ósýnilegt óskiptanlegt bil, kýrillískur stafur innan um latneska:
hvert um sig hefur sitt eigið orðalag, talið upp með dæmum á
Fyrir þýðendur. Sú síða er skrifuð
til að rétta þeim sem ritstýrir .po-skránni.
Að birta mynstur án þýðingaskrár¶
compile_template opinberar sama vélbúnað einu lagi neðar: það breytir
t-streng í msgid hans ásamt bundnu mengi gilda, og birtir hvaða mynstur sem
þú réttir því.
from gettext_tstrings import compile_template
name = "Ada"
compiled = compile_template(t"Hello {name}")
compiled.msgid # "Hello {name}"
compiled.placeholders # ("name",)
compiled.render("こんにちは {name}") # "こんにちは Ada"
render athugar eftir sömu reglum og varpar alltaf ef ekki stemmir. Hér
er enginn eftirgefanlegur hamur: eftirgefanleikinn er til svo að uppfletting
í þýðingaskrá geti hrörnað yfir í frumtextann, og mynstur sem þú réttir
sjálfur hefur ekkert til að hrörna frá.
Öryggi og umfang¶
Þetta er gilt:
Þessu er hafnað af ásettu ráði:
Reiknaðu fyrst út merkingarbært gildi:
Takmörkunin skilar stöðugum lyklum í þýðingaskrá, gefur þýðendum gagnleg nöfn og kemur í veg fyrir að þýddur strengur verði að segðamáli.
Ábyrgðin nær til byggingar og sniðs: þýðing er aldrei reiknuð út og getur aldrei bætt við aðgangi að eigindum, köllum, umbreytingum eða sniðlýsingum. Tvennt er áfram á ábyrgð kallandans, nákvæmlega eins og með gettext úr staðalsafninu — escape-ritun á birtu úttaki fyrir viðtakanda þess (HTML, skel, skjáhermi) og heilleiki þýðingaskrárinnar, því fjandsamleg þýðingaskrá getur endurtekið staðgengil til að magna upp stærð úttaksins, sem er innbyggt í hverja i18n-aðferð sem byggir á staðgenglum.