Kwa nini t-strings¶
Njia nne za kuweka thamani ndani ya ujumbe unaotafsirika, zikilinganishwa kwenye ujumbe uleule. Zote nne huyapa vishika nafasi vyake majina na humruhusu mfasiri kuvipanga upya; hutofautiana katika kinachotokea tafsiri inapokuwa na kasoro, katika kiasi cha programu yako ambacho katalogi inaweza kukifikia, na katika gharama ya kuzitumia.
Majedwali huja kwanza, ili uweze kupata safu inayokuhusu na kusoma sehemu iliyo nyuma yake pekee.
Pande tatu hugusa kila ujumbe uliotafsiriwa
Katalogi ni faili la tafsiri — .po wakati binadamu wanalihariri,
likikusanywa kuwa .mo ili programu ilipakie (mafunzo
hupitia zote mbili). Pande tatu hugusa kila ujumbe: msanidi huandika
mfuatano chanzo, mfasiri huhariri katalogi — mara nyingi kwenye jukwaa
la nje, mbali na mapitio yoyote ya msimbo — na programu huvionyesha
vyote viwili pamoja wakati wa utekelezaji. Kila mtindo wa uumbizaji hapa
chini hujibu swali lilelile kwa njia tofauti: ni kiasi gani cha lugha ya
umbizo ambacho katalogi hupewa kudhibiti? Katika mifano, _ ni jina la
kawaida la kitendakazi cha kutafsiri, na tr ni la maktaba hii.
Ubavu kwa ubavu¶
Mfasiri anapofanya kosa. Katalogi husafiri kupitia mikono mingi, na mengi ya yanayoharibika ndani yake ni ya bahati mbaya:
%(name)s |
.format() |
flufl.i18n $name |
t"…" |
|
|---|---|---|---|---|
| Tafsiri huondoa kishika nafasi — nini huonyeshwa? | thamani hutoweka kimyakimya | thamani hutoweka kimyakimya | thamani hutoweka kimyakimya | ujumbe chanzo, pamoja na onyo (kwa chaguo-msingi) |
| Tafsiri huongeza kishika nafasi kisichojulikana — nini huonyeshwa? | hitilafu | hitilafu | kishika nafasi hubaki kikionekana kama maandishi | ujumbe chanzo, pamoja na onyo (kwa chaguo-msingi) |
| Tafsiri huumbiza upya kishika nafasi — nini huonyeshwa? | kile katalogi ilichoomba, au hitilafu ikiwa herufi ya aina haiendani tena na thamani | kile katalogi ilichoomba | hakielezeki katika $-strings |
ujumbe chanzo, pamoja na onyo |
| Je, vishika nafasi hukaguliwa wakati wa kuonyesha? | hapana | hapana | hapana | ndiyo (ona hapa chini) |
Mamlaka ambayo katalogi inayo. Tafsiri ni data inayotoka nje ya hazina yako, nao kila mtindo hupewa kiasi tofauti cha nguvu:
%(name)s |
.format() |
flufl.i18n $name |
t"…" |
|
|---|---|---|---|---|
| Thamani hutoka wapi? | ramani iliyo wazi | hoja zilizo wazi | vigezo vya ndani na vya jumla vya kinachoita, pamoja na extras ya hiari |
thamani zilizonaswa ndani ya t-string |
| Je, katalogi inaweza kubadilisha jinsi thamani inavyoumbizwa? | ndiyo | ndiyo | hapana | hapana |
| Je, katalogi inaweza kufikia ndani ya vitu (ufikiaji wa sifa)? | hapana | ndiyo | ndiyo, kwa majina yenye vitone | hapana |
| "Lugha ya sasa" hukaa wapi? | popote programu inapoiweka | popote programu inapoiweka | rundo la misimbo ya lugha kwenye kitu cha programu kinachoshirikiwa | ContextVar, kwa kila kazi au ombi |
Gharama ya kuunganisha. Kila kilicho hapo juu ni bure ikiwa zana zinafaa; hapa ndipo huenda zisifae:
%(name)s |
.format() |
flufl.i18n $name |
t"…" |
|
|---|---|---|---|---|
| Python ya chini kabisa | yoyote | yoyote | 3.10 | 3.14 |
| Ukomavu | maktaba sanifu | maktaba sanifu | toleo thabiti | alpha |
| Je, hutumia katalogi za kawaida za PO/MO? | ndiyo | ndiyo | ndiyo | ndiyo |
| Je, huhitaji kitoaji maalum cha chanzo? | hapana | hapana | hapana | ndiyo, kwa sasa |
| Ni bendera gani ya PO ambayo Babel huidokeza, ili zana zilizopo zithibitishe? | python-format |
python-brace-format |
hakuna | python-brace-format |
Kuhusu ukaguzi wa wakati wa kuonyesha: jumbe za umoja hukaguliwa kwa ulinganifu kamili wa vishika nafasi. Jumbe za wingi hukaguliwa pia, dhidi ya kanuni ya muungano/mwingiliano inayoruhusu maumbo ya wingi ya lugha lengwa kutofautiana na ya chanzo; ukaguzi mkali zaidi wa kila umbo huendeshwa katalogi zinapokusanywa (Utoaji).
Safu ya bendera ya umbizo inahusu uthibitishaji unaotambua vishika nafasi, si
uoanifu wa katalogi. hakuna humaanisha zana sanifu za gettext bado husoma na
kukusanya ujumbe, lakini msgfmt --check-format haina sarufi ya kishika nafasi
cha $ ya kuitumia.
Uoanifu na ukomavu¶
Safu mbili za kwanza za jedwali la mwisho ndizo huamua matumizi, hivyo zinastahili kusemwa waziwazi badala ya kama visanduku.
%-format na .format() zimejengwa ndani ya Python nazo hazihitaji utegemezi
wowote. flufl.i18n ni kifurushi kilichokomaa, kilichotolewa na
kinachotumika katika uzalishaji, kinachoendeshwa kwenye Python 3.10 na baadaye.
gettext-tstrings ni alpha nayo huhitaji Python 3.14 au mpya zaidi, kwa
sababu t-strings ni sintaksia mpya katika 3.14 — hakuna urudishaji nyuma wala
hauwezi kuwepo. Ainisho lake ndiyo sehemu yake thabiti; API ya
Python bado inaweza kuhama kabla ya 1.0.
Kile ambacho hakuna hata mmoja wao anakigharimu ni uoanifu wa katalogi. Zote nne huzalisha mafaili ya kawaida ya POT/PO/MO ambayo kila kihariri cha PO, kila jukwaa la tafsiri, na kila zana ya GNU gettext tayari husoma, hivyo chaguo lililo hapa chini linaweza kurudishwa nyuma kwa namna ambayo kubadilisha miundo ya katalogi lisingeweza. Uhamiaji hufafanua kuhamisha mradi uliopo.
Sehemu zilizo hapa chini huonyesha kila muamala kwa kina, njia moja baada ya nyingine.
%-format¶
Kinachoweza kwenda vibaya: kishika nafasi kilichoharibika huwa hitilafu ya wakati wa utekelezaji, isipokuwa uthibitishaji wa katalogi ukikinasa kwanza.
Mfuatano wa katalogi hubeba sintaksia ya printf, ikiwa ni pamoja na herufi ya
aina mwishoni — ile s ndani ya %(name)s — ambayo ni rahisi kuipuuza na
rahisi kuiharibu:
>>> "Hello %(name)" % {"name": "Ada"} # the trailing "s" was deleted
Traceback (most recent call last):
...
ValueError: incomplete format
Uhariri wa herufi moja katika kihariri cha PO huwa hitilafu ya wakati wa
utekelezaji isipokuwa uthibitishaji wa katalogi uinase kwanza. GNU
msgfmt --check-format huikamata hii kweli, lakini kwa jumbe zilizowekwa alama
ya python-format tu, na tu ikiwa katalogi hupita kwelikweli kwenye msgfmt
njiani kuelekea programu yako.
str.format¶
Huondoa herufi ya aina ya mwishoni huku ikihifadhi kishika nafasi chenye jina kinachoweza kupangwa upya kwa uhuru. Kinachoweza kwenda vibaya huhamia upande mwingine wa muamala: tafsiri hupata nguvu juu ya vitu vyako.
str.format ni lugha ndogo ya misemo, na kuiita juu ya mfuatano kunamaanisha
kuukabidhi mfuatano huo haki ya kuitumia:
>>> "{name.__class__.__mro__}".format(name="Ada")
"(<class 'str'>, <class 'object'>)"
>>> settings.api_key = "sk-live-…"
>>> "{conf.api_key}".format(conf=settings)
'sk-live-…'
Sasa badilisha mifuatano hiyo halisi na chochote _() inachorudisha. Ikiwa
tafsiri ya Hello {name} inarudi kama {conf.api_key}, kuionyesha huchapisha
ufunguo wako wa API — katalogi, si msimbo wako, ndiyo iliyoamua kilichosomwa.
Katalogi si msimbo, lakini husafiri kama data: nje hadi jukwaa la tafsiri,
kupitia mikono kadhaa, kurudi kama .po, ikikusanywa kuwa .mo, mara nyingine
ikiletwa kutoka nje ya mradi wako kabisa. .format() huipa kila hatua ya safari
hiyo ufikiaji wa sifa za vitu unavyopitisha.
$-strings na flufl.i18n¶
from flufl.i18n import initialize
_ = initialize("example")
name = "Ada"
print(_("Hello $name")) # Hello Ada — the value came from the caller's locals
string.Template ya maktaba sanifu hutoa lugha ya uingizaji
ya $name, lakini yenyewe si API ya kutafsiri. flufl.i18n
huunganisha mtindo huo na utafutaji wa katalogi ya gettext. Zingatia kwamba
thamani haipitishwi kamwe: flufl.i18n hujenga nafasi ya majina ya ubadilishaji
kutoka vigezo vya jumla na vya ndani vya kinachoita — vigezo vyovyote
vilivyopo mahali pa wito vinapatikana kwa ujumbe. Ramani ya hiari ya extras
hutangulia vyote viwili. Sintaksia yake inayomkabili mfasiri haina herufi ya
aina ya mwishoni wala kiainishi cha umbizo, na vishika nafasi hubaki
vinapangika upya kwa uhuru.
Ubadilishaji usiopatikana hauinui hitilafu. Kwa name = "Ada" na bila
nombre katika nafasi ya majina ya kinachoita, tafsiri ya katalogi ya
Hello $nombre huonyeshwa kama Hello $nombre: kishika nafasi kisichotatuliwa
hubaki kikionekana. Tabia hiyo iliyoandikwa huhifadhi
sehemu iliyobaki ya ujumbe uliotafsiriwa badala ya kuufanya wito ushindwe.
Hitilafu zinazoinuliwa wakati wa kutatua sifa au kubadilisha thamani bado
zinaweza kuenea.
flufl.i18n ina uwezo zaidi kuliko string.Template tupu kwa njia moja
inayohusika. Template yake maalum hukubali vishika nafasi
vyenye vitone kama $settings.api_key, na mfasiri wake hutatua
njia hizo dhidi ya thamani za kinachoita. Kishika nafasi kilichotafsiriwa
kinaweza kutaja kigezo chochote cha ndani au cha jumla kinachopatikana kwa
kinachoita na, kwa sintaksia ya vitone, kupitia sifa zake. Hilo ni jambo la
urahisi wakati ujumbe unahitaji sifa, huku pia likifanya fremu ya kinachoita
kuwa sehemu ya nafasi ya majina ya ubadilishaji ya katalogi. Ulinganisho wa hapa
unaelezea flufl.i18n 6.0.0, si kila matumizi yanayowezekana ya
string.Template.
Pia hujibu swali ambalo mitindo mingine miwili ya kuumbiza huliachia programu
kabisa: ni lugha ipi iliyo ya sasa, na jinsi ya kuibadilisha. Kitu cha
programu hushikilia rundo la lugha, _.push(code) na
_.pop() hulisogeza, with _.using(code): huweka kimoja ndani ya kingine, na
mkakati hutafuta katalogi ya msimbo wa lugha ili programu
isishughulike kamwe na vitu vya katalogi yenyewe. Seva inayopaswa kutoa
maandishi kwa lugha zaidi ya moja ndani ya kipande kimoja cha kazi — ukurasa
kwa msomaji, arifa kwa mtu ambaye akaunti yake imewekwa tofauti — ndicho kisa
ambacho hii ipo kwa ajili yake.
Rundo hukaa kwenye kitu hicho cha programu, ambacho mchakato mzima hukishirikiana. Kwa hiyo maombi mawili yanayopishana hushiriki rundo moja, nayo vizuizi ambavyo havijawekwa ndani kwa ndani kwa ukamilifu kwa wakati hukabidhiana lugha isiyo sahihi:
async def greet(code, delay):
with _.using(code):
await asyncio.sleep(delay)
return _("Hello $name")
async def main():
return await asyncio.gather(greet("fr", 0.01), greet("ja", 0.02))
>>> asyncio.run(main()) # "fr" entered first and left first, so it read "ja" off the top
['こんにちは Ada', 'Bonjour Ada']
Maktaba hii huhifadhi uwezo uleule — ufungaji huwekwa ndani kwa ndani na
kufunguka kwa namna ileile — ndani ya ContextVar badala ya rundo
linaloshirikiwa, hivyo mpishano wa hapo juu hutatuliwa kwa kila kazi.
Vilinganishi vyake viko kwenye Lugha kadhaa kwa wakati
mmoja. Kile ambacho haitoi ni utafutaji wa
katalogi kutokana na msimbo wa lugha: wewe hupitisha kitu cha translations,
ambacho kwa hali ya kawaida ni wito mmoja wa gettext.translation(), nayo
maktaba sanifu huhifadhi katalogi iliyochanganuliwa.
t-strings¶
Katalogi bado huona Hello {name} na hubaki katalogi ya kawaida ya PO/MO.
Tofauti ni kile ambacho tafsiri inaruhusiwa kusema, na nani anayekikagua.
Maktaba hii huthibitisha kila tafsiri dhidi ya vishika nafasi vya ujumbe chanzo
kabla ya kuonyesha, nayo hukubali majina matupu na hakuna kingine. Dhidi ya
t"Hello {name}":
| Tafsiri iliyo na | hukataliwa kwa |
|---|---|
{name.__class__.__mro__} |
placeholder {name.__class__.__mro__} must be a plain name, copied from the source message unchanged |
{name!r} |
placeholder {name} adds formatting; write {name} on its own, because the source message decides how the value is formatted |
{0} |
placeholder {0} must be a plain name, copied from the source message unchanged |
{nombre} |
translation does not match the source placeholders: {name} is missing; {nombre} is not in the source message |
Kukataliwa hakumaanishi kuanguka: kwa chaguo-msingi maktaba huandika onyo na kuonyesha ujumbe chanzo, hivyo katalogi mbaya kamwe haiiangushi programu — mkataba uleule ambao gettext yenyewe huutunza.
Uumbizaji hubaki pale ulipoandikwa, ndani ya msimbo:
:,.2f haifiki kamwe kwenye katalogi, hivyo hakuna tafsiri inayoweza kuibadili,
na hakuna mfasiri anayelazimika kuiangalia. Hata hivyo ni umbizo lisilobadilika,
si lililotafsiriwa kwa eneo — kuchagua tarakimu na vitenganishi kwa kila lugha
ni kazi ya Babel, kabla ya wito.
Tofauti nyingine ni zana: t-strings ni sintaksia mpya, hivyo kuzitoa ndani ya
.pot kwa sasa kunahitaji kitoaji kinachotambua t-string, kama kile ambacho
kifurushi hiki hukitoa kwa Babel.
Gharama ya kizuizi¶
Zaidi ya sharti la Python, bei ya haya yote ni kanuni moja: uingizaji lazima uwe jina tupu.
Hilo ni kizuizi halisi, nacho ndicho kizuizi kilekile kinachozalisha dhamana zilizo hapo juu. Pamoja na ufungaji wa thamani upande wa chanzo na ukaguzi wa vishika nafasi wakati wa utekelezaji, huzuia mifuatano ya katalogi kutathmini misemo na huyafanya majina ya vishika nafasi yaendelee kuwa na maana kwa mtu anayeyatafsiri.
f-string haiwezi kutumika hivi hata kidogo — kufikia wakati maktaba yoyote inaiona tayari ni mfuatano uliokamilika, hivyo kuitafsiri kunamaanisha kutafsiri kipande. t-strings (PEP 750) hutenganisha maandishi tuli na thamani huku zikihifadhi sintaksia inayofanana na ya f-string na ufungaji wa thamani ulio wazi.
Jinsi Python ilivyofika hapa — PEP mbili zenye tofauti ya miaka kumi, na mjadala wa stdlib uliofungwa bila jibu — imesimuliwa pamoja na vyanzo katika Usuli.