Utilizarea msgctxt: Adăugarea de context traducerilor Gettext

Traduceți cuvântul englezesc „Book” în germană, iar traducătorul dvs. returnează cu încredere „Buch”. Trei săptămâni mai târziu, apare un raport de erori: butonul „Book a table” din formularul dvs. de rezervare afișează acum „Buch a table” – substantivul, nu verbul. Cuvântul era corect. Contextul lipsea. Aceasta este una dintre cele mai frecvente erori silențioase în localizarea software, iar soluția există în Gettext de zeci de ani: msgctxt.
Dacă ați livrat vreodată o traducere în care o singură șir de caractere în engleză era corectă într-un loc și fără sens în altul, ați întâmpinat problema ambiguității. Același cuvânt sursă se mapează la traduceri diferite, în funcție de locul în care apare. Fără msgctxt, traducătorul (uman sau AI) nu are cum să distingă aceste cazuri, deoarece tot ce vede este șirul simplu msgid "Book". Acest ghid explică modul în care funcționează msgctxt în Gettext, cum să vă marcați codul sursă cu _x() și _ex(), cum apare în fișierele dvs. .po și de ce un pipeline de traducere conștient de context este singura modalitate fiabilă de a obține aceste șiruri de caractere corect la scară.
Problema ambiguității: un cuvânt, mai multe sensuri
Limbajul natural este plin de cuvinte care se reduc la un singur token englezesc, dar se împart în mai multe cuvinte în alte limbi. Traducătorul vede doar șirul sursă, așa că atunci când două elemente UI fără legătură împărtășesc același cuvânt englezesc, ele împărtășesc același msgid – iar Gettext le combină într-o singură intrare.
Cuvinte care se scindează în mai multe limbi
Luați în considerare trei exemple clasice:
- „Book” – substantivul (un obiect pe un raft) versus verbul („Book a flight”). Germană: Buch versus buchen.
- „Post” – a publica conținut versus a trimite poștă. Franceză: publier versus courrier.
- „Order” – o secvență/sortare versus o achiziție. Spaniolă: orden versus pedido.
În engleză, codul dvs. utilizează același șir literal în ambele locuri:
// Somewhere in a library catalog screen
echo __( 'Book', 'mytextdomain' );
// Somewhere in a reservation form button
echo __( 'Book', 'mytextdomain' );
Cum se reduc șirurile identice la o singură intrare
Când rulați wp i18n make-pot sau xgettext, ambele apeluri se reduc la o singură intrare .po:
#: catalog.php:42 reservation-form.php:88
msgid "Book"
msgstr ""
Există exact un msgstr de completat. Indiferent ce alege traducătorul, unul dintre cele două ecrane va fi greșit. Traducătorul nu poate remedia acest lucru chiar dacă înțelege problema, deoarece formatul în sine nu le permite să ofere două traduceri pentru un singur msgid. Ambiguitatea este inerentă datelor.
Ce este msgctxt și cum disambiguizează?
msgctxt este un șir de context atașat unei intrări de traducere. Pe scurt: adaugă o a doua cheie alături de msgid, astfel încât Gettext tratează (context, msgid) ca o pereche unică. Două intrări cu același msgid, dar cu msgctxt diferit devin două șiruri de caractere separate, traductibile independent.
În modelul de căutare al Gettext, o traducere este, în mod normal, indexată doar de șirul sursă. Cu msgctxt, cheia devine combinația de context plus sursă. Acesta este întregul mecanism și de aceea funcționează atât de curat: nu modificați textul afișat, ci doar cheia de căutare internă.
Linia msgctxt într-un fișier .po
Într-un fișier .po, contextul apare pe propria sa linie direct deasupra msgid:
#: catalog.php:42
msgctxt "noun"
msgid "Book"
msgstr "Buch"
#: reservation-form.php:88
msgctxt "verb"
msgid "Book"
msgstr "Reservieren"
Acum există două intrări. Acestea au valori msgid identice, dar valori msgctxt distincte, astfel încât fiecare își primește propriul msgstr. Catalogul randează Buch; butonul de rezervare randează Reservieren. Runtime-ul o alege pe cea corectă deoarece codul dvs. i-a spus ce context să utilizeze.
Comparați aceasta cu versiunea cu o singură intrare, defectă, de mai sus. Diferența nu este calitatea traducerii – ci dacă modelul de date permite chiar și existența răspunsului corect.
Marcarea codului dvs.: _x() și _ex()
Pentru a emite msgctxt în șablonul dvs. .po, apelați o funcție de traducere conștientă de context în loc de cea simplă. În WordPress, acestea sunt _x() și „sora” sa de ecou _ex(); în Gettext-ul brut, ele se mapează la pgettext().
Alegerea între _x() și _ex()
Funcția simplă __() preia șirul și domeniul de text. Varianta cu context inserează contextul ca al doilea 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' );
Al doilea argument este eticheta de context. Nu este niciodată afișată utilizatorilor dvs. – există pur și simplu pentru a disambiguiza, atât pentru căutarea Gettext, cât și pentru oricine (sau orice) efectuează traducerea. Scrieți contexte ca indicii scurte și descriptive: 'noun', 'verb', 'button label', 'admin menu'. Un context vag precum '1' este valid din punct de vedere tehnic, dar inutil pentru un traducător.
Când regenerați șablonul, extractorul recunoaște aceste apeluri și emite linia msgctxt. Instrumente precum Poedit și alți editori PO grupează apoi intrările vizibil după context, astfel încât un traducător uman vede imediat că „Book (substantiv)” și „Book (verb)” sunt două sarcini diferite. Dacă încă vă configurați lanțul de instrumente de extragere sau vă confruntați cu modul în care variabilele interacționează cu aceste șiruri de caractere, ghidul nostru despre traducerea fișierelor PO fără a afecta variabilele de cod acoperă în detaliu fluxul de lucru înconjurător.
De ce traducătorii naivi – și multe instrumente AI – greșesc acest lucru
Iată partea incomodă. Adăugarea msgctxt la sursa dvs. este necesară, dar nu suficientă. Contextul ajută doar dacă cel care efectuează traducerea îl citește efectiv.
Modul de eșec „context eliminat”
Un script naiv de traducere în masă face acest lucru: iterează prin intrări, preia fiecare msgid, o trimite către o API de traducere și scrie rezultatul în msgstr. Nu se uită niciodată la linia msgctxt. Deci, chiar dacă ați scris cu atenție _x( 'Book', 'noun' ) și _x( 'Book', 'verb' ), scriptul trimite două solicitări identice – „translate Book” – și inserează același răspuns în ambele. Toate eforturile dvs. de marcare sunt eliminate în ultimul pas.
Multe instrumente AI de traducere de uz general au aceeași problemă. Sunt construite pentru a traduce text, iar msgctxt sunt metadate, nu text. Dacă instrumentul aplatizează fișierul .po într-o listă de șiruri de caractere înainte de a-l trimite modelului, contextul nu ajunge niciodată la promptul modelului. Modelul, lipsit de orice semnal, se bazează pe sensul cel mai comun statistic al cuvântului – de obicei substantivul pentru „Book”, sensul de publicare pentru „Post” – și traduce greșit, în mod silențios, cazul minoritar. Nu veți vedea o eroare. Veți vedea un raport de erori de la un utilizator german săptămâni mai târziu.
Contextul și Pluralele au aceeași cauză principală
Acesta este și punctul în care se intersectează gestionarea pluralelor și contextul, deoarece ambele depind de înțelegerea structurii Gettext de către instrument, mai degrabă decât de tratarea fișierului ca text simplu. Dacă șirurile dvs. implică și forme bazate pe număr, aceeași conștientizare structurală contează – detaliem acest aspect în înțelegerea pluralelor Gettext.
Cum utilizează msgctxt un pipeline conștient de context
Un pipeline de traducere care respectă msgctxt face opusul scriptului naiv. Parsează fișierul .po ca date structurate, păstrează contextul fiecărei intrări atașat șirului său sursă și transmite acel context către AI ca parte a promptului – astfel încât modelul știe că traduce „Book” în mod specific ca verb, nu în abstract.
Contextul ca semnal de primă clasă
Acesta este exact modul în care SimplePoTranslate abordează problema. AI-ul său conștient de context citește linia msgctxt ca un semnal de primă clasă: atunci când două intrări împărtășesc un msgid, dar diferă în context, ele sunt traduse ca șirurile distincte care sunt de fapt, iar indiciul de context informează alegerea cuvântului de către model. Rezultatul este că „Book (substantiv)” revine ca Buch, în timp ce „Book (verb)” revine ca buchen sau reservieren – automat, fără să corectați manual fiecare termen ambiguu.
La fel de important, pipeline-ul păstrează linia msgctxt în ieșire. Un instrument mai slab ar putea elimina contextul în timpul procesului de round-trip, combinând discret cele două intrări într-una singură și reintroducând ambiguitatea la următoarea îmbinare. Suportul complet Gettext înseamnă că contextul supraviețuiește traducerii, compilării .mo și oricăror reimporturi ulterioare – astfel încât disambiguizarea dvs. este durabilă, nu o corecție manuală unică. Combinat cu Syntax Locking pentru placeholder-urile din interiorul acelor șiruri de caractere, obțineți traduceri care sunt atât corecte contextual, cât și intacte structural.
Încă vă aparține decizia de marcare – doar dvs. știți că un anumit „Book” este un verb. Dar, odată ce ați adnotat sursa cu _x() și _ex(), un pipeline conștient de context transformă acea adnotare în traduceri corecte în fiecare limbă țintă, fără o gestionare individuală a fiecărui șir.
Concluzie
Problema ambiguității – un cuvânt englezesc, multe sensuri – nu este o ciudățenie pe care o puteți ignora; este o caracteristică structurală a modului în care Gettext stochează șirurile de caractere. Soluția este msgctxt: adnotați șirurile ambigue din sursa dvs. cu _x() și _ex(), dați fiecărei apariții o etichetă de context clară și lăsați Gettext să cheieze traducerea pe perechea (context, msgid). Această parte depinde de dvs. și durează minute.
Partea mai dificilă este să vă asigurați că etapa dvs. de traducere respectă de fapt acel context, în loc să-l ignore. Scripturile naive și instrumentele AI bazate doar pe text ignoră msgctxt și reintroduc exact eroarea pe care încercați să o preveniți. Un pipeline conștient de context citește contextul, traduce corect fiecare intrare disambiguizată și o păstrează prin compilare și reimporturi.
Gata să opriți livrarea de traduceri greșite, fără context? Încercați SimplePoTranslate gratuit — nu este necesar un card de credit. Nivelul gratuit gestionează fișiere
.poși.potreale cu suport complet pentru contextul msgctxt, astfel încât șirurile dvs. disambiguizate se traduc corect de prima dată.