msgctxt:n käyttö: Kontekstin lisääminen Gettext-käännöksiin

Käännät englanninkielisen sanan "Book" saksaksi, ja kääntäjäsi palauttaa luottavaisesti "Buch". Kolme viikkoa myöhemmin virheraportti saapuu: varauslomakkeesi "Book a table" -painike lukee nyt "Buch a table" – siis substantiivi, ei verbi. Sana oli oikea. Konteksti puuttui. Tämä on yksi yleisimmistä hiljaisista virheistä ohjelmistojen lokalisoinnissa, ja korjaus on ollut olemassa Gettextissä vuosikymmeniä: msgctxt.
Jos olet joskus toimittanut käännöksen, jossa yksi englanninkielinen merkkijono oli oikein yhdessä paikassa ja hölynpölyä toisessa, olet törmännyt monitulkintaisuusongelmaan. Sama lähdesana kartoittuu eri käännöksiin riippuen siitä, missä se esiintyy. Ilman msgctxt:tä kääntäjällä (ihmisellä tai tekoälyllä) ei ole tapaa erottaa näitä tapauksia, koska he näkevät vain pelkän merkkijonon msgid "Book". Tämä opas selittää, miten msgctxt toimii Gettextissä, miten merkitset lähdekoodisi _x()- ja _ex()-funktioilla, miten se näkyy .po-tiedostoissasi ja miksi kontekstitietoinen käännösprosessi on ainoa luotettava tapa saada nämä merkkijonot oikein suuressa mittakaavassa.
Monitulkintaisuusongelma: Yksi sana, monta merkitystä
Luonnolliset kielet ovat täynnä sanoja, jotka yhdistyvät yhdeksi englanninkieliseksi merkiksi, mutta jakautuvat useiksi sanoiksi muilla kielillä. Kääntäjä näkee vain lähdemerkkijonon, joten kun kaksi toisiinsa liittymätöntä käyttöliittymäelementtiä jakavat saman englanninkielisen sanan, ne jakavat saman msgid:n – ja Gettext yhdistää ne yhdeksi merkinnäksi.
Kielten välillä jakautuvat sanat
Otetaan kolme klassista esimerkkiä:
- "Book" – substantiivi (esimerkiksi hyllyllä oleva esine) versus verbi ("Book a flight", varaa lento). Saksa: Buch versus buchen.
- "Post" – sisällön julkaiseminen versus postin lähettäminen. Ranska: publier versus courrier.
- "Order" – järjestys/lajittelu versus tilaus. Espanja: orden versus pedido.
Englanniksi koodisi käyttää samaa kirjaimellista merkkijonoa molemmissa paikoissa:
// Somewhere in a library catalog screen
echo __( 'Book', 'mytextdomain' );
// Somewhere in a reservation form button
echo __( 'Book', 'mytextdomain' );
Miten identtiset merkkijonot tiivistyvät yhdeksi merkinnäksi
Kun suoritat wp i18n make-pot tai xgettext, molemmat kutsut tiivistyvät yhdeksi .po-merkinnäksi:
#: catalog.php:42 reservation-form.php:88
msgid "Book"
msgstr ""
Täytettäväksi on tasan yksi msgstr. Mitä tahansa kääntäjä valitseekin, toinen kahdesta näytöstä on väärin. Kääntäjä ei voi korjata tätä, vaikka hän ymmärtäisi ongelman, koska itse muoto ei anna hänen antaa kahta käännöstä yhdelle msgid:lle. Monitulkintaisuus on sisäänrakennettu dataan.
Mitä msgctxt on ja miten se poistaa monitulkintaisuuden?
msgctxt on käännösmerkintään liitetty kontekstimääritys. Lyhyesti sanottuna: se lisää toisen avaimen msgid:n rinnalle, joten Gettext käsittelee (context, msgid):tä yksilöllisenä parina. Kaksi merkintää, joilla on sama msgid mutta eri msgctxt, muuttuvat kahdeksi erilliseksi, itsenäisesti käännettäväksi merkkijonoksi.
Gettextin hakumallissa käännös on normaalisti avainnettu vain lähdemerkkijonon perusteella. msgctxt:n avulla avaimeksi tulee kontekstin ja lähteen yhdistelmä. Se on koko mekanismi, ja siksi se toimii niin puhtaasti: et muuta näytettävää tekstiä, vain sisäistä hakuavainta.
msgctxt-rivi .po-tiedostossa
.po-tiedostossa konteksti esiintyy omalla rivillään suoraan msgid:n yläpuolella:
#: catalog.php:42
msgctxt "noun"
msgid "Book"
msgstr "Buch"
#: reservation-form.php:88
msgctxt "verb"
msgid "Book"
msgstr "Reservieren"
Nyt on kaksi merkintää. Niillä on identtiset msgid-arvot, mutta erilliset msgctxt-arvot, joten kumpikin saa oman msgstr-arvonsa. Katalogi näyttää Buch; varauspainike näyttää Reservieren. Ajonaikainen ohjelma valitsee oikean, koska koodisi kertoi, mitä kontekstia käyttää.
Vertaile tätä yllä olevaan rikkinäiseen yksittäiseen merkintäversioon. Ero ei ole käännöksen laadussa – se on siinä, salliko tietomalli oikean vastauksen olemassaolon ylipäätään.
Koodin merkintä: _x() ja _ex()
Jotta saat msgctxt:n .po-mallipohjaan, kutsut kontekstitietoista käännösfunktiota tavallisen sijaan. WordPressissä nämä ovat _x() ja sen tulostava sisar _ex(); raa'assa Gettextissä ne vastaavat pgettext():iä.
_x() ja _ex() välillä valitseminen
Tavallinen __()-funktio ottaa merkkijonon ja tekstialueen. Kontekstiversio lisää kontekstin toiseksi argumentiksi:
// Without context - ambiguous
__( 'Book', 'mytextdomain' );
// With context - the second argument is the msgctxt
_x( 'Book', 'noun', 'mytextdomain' ); // returns the translated string
_ex( 'Book', 'verb', 'mytextdomain' ); // echoes it directly
// Real-world disambiguation
_x( 'Post', 'verb: publish content', 'mytextdomain' );
_x( 'Post', 'noun: mail item', 'mytextdomain' );
_x( 'Order', 'sequence or sorting', 'mytextdomain' );
_x( 'Order', 'customer purchase', 'mytextdomain' );
Toinen argumentti on kontekstimerkintä. Sitä ei koskaan näytetä käyttäjillesi – se on olemassa puhtaasti monitulkintaisuuden poistamiseksi, sekä Gettext-haun että kääntämistä tekevän tahon (tai tekoälyn) vuoksi. Kirjoita kontekstit lyhyiksi, kuvaaviksi vihjeiksi: 'noun', 'verb', 'button label', 'admin menu'. Epämääräinen konteksti kuten '1' on teknisesti pätevä, mutta kääntäjälle hyödytön.
Kun luot mallipohjan uudelleen, purkuohjelma tunnistaa nämä kutsut ja lähettää msgctxt-rivin. Työkalut kuten Poedit ja muut PO-editorit ryhmittelevät merkinnät visuaalisesti kontekstin mukaan, joten ihminen kääntäjä näkee välittömästi, että "Book (noun)" ja "Book (verb)" ovat kaksi eri tehtävää. Jos vielä yhdistät purkutyökaluketjuasi tai kamppailet sen kanssa, miten muuttujat ovat vuorovaikutuksessa näiden merkkijonojen kanssa, oppaamme PO-tiedostojen kääntämisestä rikkomatta koodimuuttujia käsittelee ympäröivää työnkulkua yksityiskohtaisesti.
Miksi naiivit kääntäjät – ja monet tekoälytyökalut – tekevät tämän väärin
Tässä tulee se epämukava osuus. msgctxt:n lisääminen lähdekoodiin on välttämätöntä, mutta ei riittävää. Konteksti auttaa vain, jos käännöksen tekevä taho todella lukee sen.
Hylätyn kontekstin virhetila
Naiivi eräkäännöskomentosarja toimii näin: se käy läpi merkintöjä, ottaa jokaisen msgid:n, lähettää sen käännös-API:lle ja kirjoittaa tuloksen msgstr:ään. Se ei koskaan katso msgctxt-riviä. Vaikka olisit huolellisesti kirjoittanut _x( 'Book', 'noun' ) ja _x( 'Book', 'verb' ), komentosarja lähettää kaksi identtistä pyyntöä – "translate Book" – ja liittää saman vastauksen molempiin. Kaikki merkintätyösi hylätään viimeisessä vaiheessa.
Monilla yleiskäyttöisillä tekoälykäännöstyökaluilla on sama sokea piste. Ne on rakennettu kääntämään tekstiä, ja msgctxt on metadataa, ei tekstiä. Jos työkalu tasoittaa .po-tiedostosi merkkijonoluetteloksi ennen sen lähettämistä mallille, konteksti ei koskaan pääse mallin kehotteeseen. Malli, josta puuttuu signaali, olettaa sanan tilastollisesti yleisimmän merkityksen – yleensä substantiivin "Book"-sanalle, julkaisemisen "Post"-sanalle – ja kääntää vähemmistötapauksen hiljaisesti väärin. Et näe virhettä. Näet virheraportin saksalaiselta käyttäjältä viikkoja myöhemmin.
Konteksti ja monikot jakavat saman perussyyn
Tässä kohtaa monikkojen käsittely ja konteksti myös kohtaavat, koska molemmat riippuvat siitä, että työkalu ymmärtää Gettextin rakenteen sen sijaan, että käsittelee tiedostoa pelkkänä tekstinä. Jos merkkijonosi sisältävät myös määrään perustuvia muotoja, sama rakenteellinen tietoisuus on tärkeää – puramme tämän Gettext-monikkojen ymmärtämisessä.
Miten kontekstitietoinen käännösprosessi käyttää msgctxt:tä
Käännösprosessi, joka kunnioittaa msgctxt:tä, tekee päinvastoin kuin naiivi komentosarja. Se jäsentää .po-tiedoston jäsenneltynä datana, pitää kunkin merkinnän kontekstin liitettynä sen lähdemerkkijonoon ja välittää tämän kontekstin tekoälylle osana kehotetta – jotta malli tietää kääntävänsä "Book"-sanaa nimenomaan verbinä, ei abstraktisti.
Konteksti ensiluokkaisena signaalina
Tämä on juuri se tapa, jolla SimplePoTranslate lähestyy ongelmaa. Sen kontekstitietoinen tekoäly lukee msgctxt-rivin ensiluokkaisena signaalina: kun kaksi merkintää jakaa msgid:n mutta eroavat kontekstin osalta, ne käännetään erillisinä merkkijonoina, joita ne todella ovat, ja kontekstivihje ohjaa mallin sanavalintaa. Tuloksena on, että "Book (noun)" palautuu Buch:ina, kun taas "Book (verb)" palautuu buchen:ina tai reservieren:ina – automaattisesti, ilman että sinun tarvitsee käsin korjata jokaista monitulkintaista termiä.
Lisäksi, mikä on yhtä tärkeää, prosessi säilyttää msgctxt-rivin tulosteessa. Heikompi työkalu saattaa poistaa kontekstin edestakaisen siirron aikana, yhdistäen hiljaisesti kaksi merkintääsi takaisin yhdeksi ja tuoden monitulkintaisuuden takaisin seuraavassa yhdistämisessä. Täysi Gettext-tuki tarkoittaa, että konteksti säilyy käännöksen, .mo-käännöksen ja myöhempien uudelleenimporttien läpi – joten monitulkintaisuuden poistaminen on kestävää, ei kertaluonteinen manuaalinen korjaus. Yhdistettynä syntaksilukitukseen näiden merkkijonojen sisällä olevien paikkamerkkien osalta saat käännöksiä, jotka ovat sekä kontekstuaalisesti oikeita että rakenteellisesti ehjiä.
Olet edelleen itse vastuussa merkintäpäätöksestä – vain sinä tiedät, että tietty "Book" on verbi. Mutta kun olet annotoinut lähdekoodisi _x()- ja _ex()-funktioilla, kontekstitietoinen prosessi muuttaa tämän annotaation oikeiksi käännöksiksi kaikilla kohdekielillä ilman yksittäisten merkkijonojen vahtimista.
Yhteenveto
Monitulkintaisuusongelma – yksi englanninkielinen sana, monta merkitystä – ei ole outous, jonka voit jättää huomiotta; se on rakenteellinen ominaisuus Gettextin tapaan tallentaa merkkijonoja. Ratkaisu on msgctxt: annotoi monitulkintaiset merkkijonot lähdekoodissasi _x()- ja _ex()-funktioilla, anna jokaiselle esiintymälle selkeä kontekstimerkintä ja anna Gettextin avaintaa käännös (context, msgid)-parin perusteella. Tämä osuus on sinun vastuullasi, ja se vie minuutteja.
Vaikeampi osa on varmistaa, että käännösvaihe todella kunnioittaa tätä kontekstia sen sijaan, että se heitettäisiin pois. Naiivit skriptit ja vain tekstiä käsittelevät tekoälytyökalut hylkäävät msgctxt:n ja tuovat takaisin juuri sen virheen, jota yritit estää. Kontekstitietoinen käännösprosessi lukee kontekstin, kääntää jokaisen monitulkintaisuudesta vapautetun merkinnän oikein ja säilyttää sen käännöksen ja uudelleenimporttien läpi.
Oletko valmis lopettamaan kontekstisokeiden virhekäännösten toimittamisen? Kokeile SimplePoTranslatea ilmaiseksi – luottokorttia ei tarvita. Ilmainen taso käsittelee todellisia .po- ja .pot-tiedostoja täydellä msgctxt-kontekstituella, joten monitulkintaisuudesta vapautetut merkkijonosi kääntyvät oikein heti ensimmäisellä kerralla.