Brug af msgctxt: Tilføjelse af kontekst til Gettext-oversættelser

Du oversætter det engelske ord "Book" til tysk, og din oversætter returnerer med sikkerhed "Buch". Tre uger senere dukker en fejlrapport op: "Book a table"-knappen på din reservationsformular lyder nu "Buch a table" – substantivet, ikke verbet. Ordet var rigtigt. Konteksten manglede. Dette er en af de mest almindelige tavse fejl i softwarelokalisering, og løsningen har eksisteret i Gettext i årtier: msgctxt.
Hvis du nogensinde har udgivet en oversættelse, hvor en enkelt engelsk streng var korrekt ét sted og vrøvl et andet, er du stødt på tvetydighedsproblemet. Det samme kildeord svarer til forskellige oversættelser afhængigt af, hvor det vises. Uden msgctxt har oversætteren (menneske eller AI) ingen måde at skelne disse tilfælde fra hinanden, fordi alt, hvad de ser, er den bare streng msgid "Book". Denne guide forklarer, hvordan msgctxt fungerer i Gettext, hvordan du markerer din kildekode med _x() og _ex(), hvordan det vises i dine .po-filer, og hvorfor en kontekstbevidst oversættelsespipeline er den eneste pålidelige måde at få disse strenge rigtigt i stor skala.
Tvetydighedsproblemet: Ét ord, mange betydninger
Naturligt sprog er fuld af ord, der kollapser til et enkelt engelsk token, men splittes til flere ord på andre sprog. Oversætteren ser kun kildestrengen, så når to uafhængige UI-elementer deler det samme engelske ord, deler de samme msgid – og Gettext fletter dem til én post.
Ord, der splittes på tværs af sprog
Overvej tre klassiske eksempler:
- "Book" – substantivet (en genstand på en hylde) versus verbet ("Book a flight"). Tysk: Buch versus buchen.
- "Post" – udgive indhold versus sende mail. Fransk: publier versus courrier.
- "Order" – en sekvens/sortering versus et køb. Spansk: orden versus pedido.
På engelsk bruger din kode den samme bogstavelige streng begge steder:
// Somewhere in a library catalog screen
echo __( 'Book', 'mytextdomain' );
// Somewhere in a reservation form button
echo __( 'Book', 'mytextdomain' );
Hvordan identiske strenge kollapser til én post
Når du kører wp i18n make-pot eller xgettext, kollapser begge kald til én .po-post:
#: catalog.php:42 reservation-form.php:88
msgid "Book"
msgstr ""
Der er præcis én msgstr at udfylde. Uanset hvad oversætteren vælger, vil en af de to skærme være forkert. Oversætteren kan ikke rette dette, selvom de forstår problemet, fordi selve formatet ikke tillader dem at levere to oversættelser for en msgid. Tvetydigheden er indlejret i dataene.
Hvad er msgctxt, og hvordan fjerner det tvetydighed?
msgctxt er en kontekststreng, der er knyttet til en oversættelsespost. Det korte svar: det tilføjer en anden nøgle ud over msgid, så Gettext behandler (context, msgid) som et unikt par. To poster med samme msgid, men forskellige msgctxt, bliver til to separate, uafhængigt oversætbare strenge.
I Gettexts opslagsmodel er en oversættelse normalt kun nøglebundet af kildestrengen. Med msgctxt bliver nøglen kombinationen af kontekst plus kilde. Det er hele mekanismen, og det er derfor, det fungerer så rent: du ændrer ikke den viste tekst, kun den interne opslagsnøgle.
msgctxt-linjen i en .po-fil
I en .po-fil vises konteksten på sin egen linje direkte over msgid:
#: catalog.php:42
msgctxt "noun"
msgid "Book"
msgstr "Buch"
#: reservation-form.php:88
msgctxt "verb"
msgid "Book"
msgstr "Reservieren"
Nu er der to poster. De har identiske msgid-værdier, men forskellige msgctxt-værdier, så hver får sin egen msgstr. Kataloget gengiver Buch; reservationsknappen gengiver Reservieren. Runtime vælger den rigtige, fordi din kode fortalte den, hvilken kontekst der skulle bruges.
Sammenlign det med den ødelagte enkeltpostversion ovenfor. Forskellen er ikke oversættelseskvaliteten – det er, om datamodellen overhovedet tillader det korrekte svar at eksistere.
Markering af din kode: _x() og _ex()
For at udsende msgctxt til din .po-skabelon kalder du en kontekstbevidst oversættelsesfunktion i stedet for den almindelige. I WordPress er disse _x() og dens søskende _ex(), der ekkoer; i rå Gettext mapper de til pgettext().
Valg mellem _x() og _ex()
Den almindelige __()-funktion tager strengen og tekstdomænet. Kontekstvarianten indsætter konteksten som det andet argument:
// 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' );
Det andet argument er kontekstetiketten. Den vises aldrig for dine brugere – den eksisterer udelukkende for at fjerne tvetydighed, både for Gettext-opslaget og for den (eller det), der foretager oversættelsen. Skriv kontekster som korte, beskrivende hints: 'noun', 'verb', 'button label', 'admin menu'. En vag kontekst som '1' er teknisk gyldig, men ubrugelig for en oversætter.
Når du regenererer skabelonen, genkender udtrækkeren disse kald og udsender msgctxt-linjen. Værktøjer som Poedit og andre PO-editorer grupperer derefter posterne synligt efter kontekst, så en menneskelig oversætter straks ser, at "Book (noun)" og "Book (verb)" er to forskellige opgaver. Hvis du stadig forbinder din udtrækningsværktøjskæde eller kæmper med, hvordan variabler interagerer med disse strenge, dækker vores guide om oversættelse af PO-filer uden at ødelægge kodevariabler den omkringliggende arbejdsgang i dybden.
Hvorfor naive oversættere – og mange AI-værktøjer – tager fejl
Her er den ubehagelige del. Tilføjelse af msgctxt til din kilde er nødvendig, men ikke tilstrækkelig. Konteksten hjælper kun, hvis den ting, der oversætter, faktisk læser den.
Fejltilstanden med kasseret kontekst
Et naivt batchoversættelsesscript gør dette: det løber over poster, tager hver msgid, sender den til en oversættelses-API og skriver resultatet til msgstr. Det kigger aldrig på msgctxt-linjen. Så selvom du omhyggeligt skrev _x( 'Book', 'noun' ) og _x( 'Book', 'verb' ), sender scriptet to identiske anmodninger – "translate Book" – og indsætter det samme svar i begge. Al din markeringsindsats kasseres i det sidste trin.
Mange generelle AI-oversættelsesværktøjer har den samme blinde vinkel. De er bygget til at oversætte tekst, og msgctxt er metadata, ikke tekst. Hvis værktøjet udjævner din .po til en liste over strenge, før det sendes til modellen, når konteksten aldrig modellens prompt. Modellen, der mangler ethvert signal, falder tilbage til den mest statistisk almindelige betydning af ordet – normalt substantivet for "Book", udgivelsesbetydningen for "Post" – og oversætter lydløst mindretalstilfældet forkert. Du vil ikke se en fejl. Du vil se en fejlrapport fra en tysk bruger uger senere.
Kontekst og pluralis deler den samme grundårsag
Det er også her, flertalshåndtering og kontekst krydser hinanden, fordi begge afhænger af, at værktøjet forstår Gettexts struktur i stedet for at behandle filen som flad tekst. Hvis dine strenge også involverer tællingsbaserede former, er den samme strukturelle bevidsthed vigtig – vi nedbryder det i forståelse af Gettext-pluralis.
Hvordan en kontekstbevidst pipeline bruger msgctxt
En oversættelsespipeline, der respekterer msgctxt, gør det modsatte af det naive script. Den parser .po-filen som strukturerede data, holder hver posts kontekst knyttet til dens kildestreng og sender den kontekst til AI som en del af prompten – så modellen ved, at den oversætter "Book" specifikt som et verbum, ikke i abstrakt.
Kontekst som et førsteklasses signal
Det er præcis sådan, SimplePoTranslate nærmer sig problemet. Dens kontekstbevidste AI læser msgctxt-linjen som et førsteklasses signal: når to poster deler en msgid, men adskiller sig i kontekst, oversættes de som de forskellige strenge, de faktisk er, og kontekst-hintet informerer modellens ordvalg. Resultatet er, at "Book (noun)" kommer tilbage som Buch, mens "Book (verb)" kommer tilbage som buchen eller reservieren – automatisk, uden at du manuelt retter hvert tvetydigt udtryk.
Lige så vigtigt er det, at pipelinen bevarer msgctxt-linjen i outputtet. Et svagere værktøj kan strippe kontekst under round-tripping, stille kollapse dine to poster tilbage til én og genintroducere tvetydigheden ved den næste fletning. Fuld Gettext-understøttelse betyder, at konteksten overlever oversættelsen, .mo-kompileringen og eventuelle senere genimport – så din tvetydighedsopløsning er holdbar, ikke en engangs manuel patch. Kombineret med Syntax Locking for pladsholdere inde i disse strenge får du oversættelser, der er både kontekstuelt korrekte og strukturelt intakte.
Du ejer stadig markeringsbeslutningen – kun du ved, at en given "Book" er et verbum. Men når du har annoteret din kilde med _x() og _ex(), omdanner en kontekstbevidst pipeline denne annotation til korrekte oversættelser på tværs af hvert målsprog uden per-streng barnepige.
Konklusion
Tvetydighedsproblemet – ét engelsk ord, mange betydninger – er ikke et særegent træk, du kan ignorere; det er en strukturel egenskab ved, hvordan Gettext gemmer strenge. Løsningen er msgctxt: annoter tvetydige strenge i din kilde med _x() og _ex(), giv hver forekomst en klar kontekstetiket, og lad Gettext nøgle oversættelsen på (context, msgid)-parret. Den del er op til dig, og det tager minutter.
Den sværere del er at sikre, at dit oversættelsestrin faktisk respekterer denne kontekst i stedet for at smide den væk. Naive scripts og tekstbaserede AI-værktøjer kasserer msgctxt og genintroducerer den præcise fejl, du forsøgte at forhindre. En kontekstbevidst pipeline læser konteksten, oversætter hver disambiguerede post korrekt og bevarer den gennem kompilering og genimport.
Klar til at stoppe med at udgive kontekstblinde fejloversættelser? Prøv SimplePoTranslate gratis — intet kreditkort påkrævet. Den gratis plan håndterer rigtige
.po- og.pot-filer med fuld msgctxt-kontekststøtte, så dine tvetydighedsopløste strenge oversættes korrekt første gang.