__(): Cum trec o variabilă ca parametru?
În documentația pentru funcția de traducere __( $text, $domain )
, se menționează că trebuie să pui șirul direct în locul $text și nu poți face ceva mai complex precum __( $my_text, 'text-domain' );
.
Totuși, scriu o metodă care primește un șir și trebuie să-l trimit cumva către __(
... )
. Există vreo modalitate, de exemplu folosind printf
sau sprintf
pentru a rezolva această situație?
Ceva de genul...
function print_description( $text ) {
echo '<p>' . __( printf( '%s', $text ), 'text-domain' ) . '</p>';
}
Pentru a traduce un șir de caractere în WordPress, ca în majoritatea CMS-urilor care folosesc PHP, trebuie să încadrați șirul într-o funcție de traducere GetText (adică __ (), _e (), _n (), _x () ... etc.).
Șirul trebuie să fie inclus și într-un fișier PO (fișiere GetText Portable Object, standardul industriei pentru site-uri web multilingvistice în PHP - https://www.gnu.org/software/gettext/manual/html_node/PO-Files.html). Acest fișier include perechi de șiruri, unul dintre ele este șirul în limba originală, iar celălalt este traducerea sa în limba țintă.
Pentru a construi aceste fișiere PO pentru fiecare limbă (de ex. my-text-domain-es_ES.po pentru spaniolă, my-text-domain-fr_FR.po pentru franceză ... etc.) în care trebuie să traducem pluginul sau tema, translatorul va folosi un fișier POT (șablon PO) care conține toate șirurile de tradus în limba originală și va adăuga un șir tradus pentru fiecare dintre ele. Fișierele PO sunt compilate în fișiere binare MO, care pot fi procesate mult mai rapid.
La momentul execuției, șirurile de tradus sunt preluate prin fișierele MO și înlocuite cu traducerea lor.
Fișierele POT sunt de obicei generate folosind instrumente speciale care analizează fișierele de cod sursă și extrag șirurile traductibile.
Dacă scriem cod ca acesta:
$translated_text = __( $text, 'my_text_domain');
Când codul este analizat de instrumentele speciale, valoarea șirului de tradus ($text) nu este încă definită și, prin urmare, nu este prezentă în cod. Ca urmare, instrumentele de căutare automată nu vor include acest șir în fișierul POT și, prin urmare, nu vor fi incluse în fișierele PO sau MO.
La momentul execuției, când valoarea șirului $text va fi presupusă deja definită, nu va exista corespondență pentru această valoare în fișierele de traducere și traducerea nu va fi posibilă.
Cu toate acestea, dacă setul de valori posibile pentru acea variabilă este limitat și le cunoaștem, avem două opțiuni pentru a depăși această problemă:
Opțiunea 1: Editați manual fișierul POT pentru a adăuga intrările cu valorile posibile ale lui $text. Această opțiune este simplă și ușor de implementat. Orice editor de cod și cunoștințe minime despre formatul POT vor fi suficiente. Dar are un dezavantaj. De fiecare dată când folosim instrumentele de căutare automată pentru a actualiza traducerile după modificarea codului nostru, modificările pe care le-am făcut ar fi pierdute și ar trebui să le includem manual din nou.
Opțiunea 2: includeți în codul nostru toate valorile posibile ale lui $text încadrate de funcții de traducere. Să vedem un exemplu. Să presupunem că $text poate lua valorile: măr, portocală, banană, piersică și pară. Am avea nevoie să scriem următorul cod:
// această variabilă este folosită doar pentru a include ca parametri în
// funcțiile de traducere toate valorile posibile ale lui $text
$locale = __('măr', 'my_text_domain') .
__('portocală', 'my_text_domain') .
__('banană', 'my_text_domain') .
__('piersică', 'my_text_domain') .
__('pară', 'my_text_domain');
$translated_text = __( $text, 'my_text_domain');
Această opțiune este, de asemenea, ușor de implementat și are avantajul că nu se va pierde atunci când folosim instrumentele de căutare automată pentru a actualiza traducerile.
Dacă avem, în tema sau pluginul nostru, mai multe variabile pe care dorim să le traducem și acestea au un set limitat de valori posibile cunoscute, le-am putea include pe toate într-un fișier separat care trebuie să fie în folderul rădăcină sau într-un subfolder (de ex. folderul 'includes' sau 'assets') al temei sau pluginului, așa cum este arătat mai jos:
<?php
//valorile variabilelor de tradus
$locale_var1 = __('text-of-var1_val1', 'my_text_domain') .
__('text-of-var1_val2', 'my_text_domain') .
__('text-of-var1_val3', 'my_text_domain') .
.......
__('text-of-var1_valn', 'my_text_domain');
$locale_var2 = __('text-of-var2_val1', 'my_text_domain') .
__('text-of-var2_val2', 'my_text_domain') .
.......
__('text-of-var2_valn', 'my_text_domain');
.............
$locale_varn = __('text-of-varn_val1', 'my_text_domain') .
__('text-of-varn_val2', 'my_text_domain') .
.......
__('text-of-varn_valn', 'my_text_domain');
Aceasta este o abordare curată și ușor de întreținut care păstrează definirea acestor șiruri într-un fișier separat care poate fi modificat fără a afecta alte fișiere de cod.

Mulțumesc pentru asta @Juan Guerrero. Nu sunt sigur de ce acest răspuns nu a primit câteva aprecieri - cred că ideea ta de a folosi un fișier de resurse pentru seturi predictibile de șiruri este foarte bună - după cum spui, este o abordare "curată și ușor de întreținut". O voi folosi și eu.

Nu
Instrumentele care ajută în generarea unei traduceri nu pot analiza codul tău și decide care sunt șirurile care necesită traducere atunci când șirurile transmise rutinelor de traducere sunt complet dinamice.
În exemplul tău, modalitatea corectă de a codifica această funcție este
function print_description( $text ) {
echo '<p>' . $text . '</p>';
}
și apelează-o astfel
print_description(__('descriere specifică','text_domain'));

Nu, pentru că nu poți traduce text atunci când nu știi cu adevărat care este acel text.
Traducerea funcționează, în esență, ca un tablou mare. Îți iei codul, găsești toate șirurile de text din el, apoi construiești o listă mare de șiruri. Un traducător le traduce în altă limbă. Apoi, diferitele funcții de traducere fac o căutare în acel tablou mare și returnează șirul tradus.
Dacă folosești o variabilă pentru a stoca șirul de text, atunci nu există nicio modalitate de a ști în avans care este acesta și de a-l include în lista inițială de șiruri de tradus.
Variabilele nu pot fi utilizate în funcțiile de traducere, pentru că acest lucru nu are sens. Nu poți traduce o variabilă.

Din anumite motive, pentru mine funcționează să transmit variabile la _e():
$string = 'ciao';
_e($string, 'textdomain'); // înlocuiește cu propriul tău textdomain..
// va afișa 'ciao' sau 'hello', în funcție de limba curentă
Evident, trebuie să-ți creezi textdomain-ul înainte, ideal în yourtheme/functions.php:
add_action( 'after_setup_theme', 'theme_setup' );
function theme_setup() {
load_theme_textdomain( 'yourtextdomain', TEMPLATEPATH . '/languages' );
// [...] alt cod de inițializare
}
Dacă traduc cuvântul 'ciao' în fișierul .po, acesta va fi tradus corect în frontend. Folosește Poedit sau un utilitar similar pentru a compila fișierul .mo. Ambele fișiere, .po și .mo, trebuie plasate în /wp-content/yourtheme/languages (conform codului de mai sus).
#. Test en_EN.po
msgid "ciao"
msgstr "hello"
Nu sunt sigur de motivul pentru care funcționează, dar o face - va afișa 'ciao' în italiană și 'hello' în engleză.

Acest lucru funcționează doar pentru că adaugi manual traducerea. Dacă folosești un instrument care caută în codul tău șirurile de tradus, acesta nu va reuși să găsească șirul corect.

Da, desigur, dar cred că aceasta nu este problema din întrebarea originală

După cum menționez aici http://www.westofwonder.com/2013/12/whats-with-all-the-double-underscores-everywhere/ (scuzați tema, am făcut îmbunătățiri, dar nu le-am publicat încă), o posibilă soluție pentru aceasta este crearea unei funcții pentru text:
function yourtheme_thisisthetext() {
return __( 'Acesta este textul.', 'yourthemetextdomain' );
}
În sine nu este elegant, dar pentru un șir de traducere lung sau folosit frecvent, compromisul poate fi justificat pentru lizibilitatea codului.
(Este permis acest lucru? Să fac legătura către blogul meu într-un răspuns direct la o întrebare? Dacă nu, îmi cer scuze și nu voi mai face acest lucru.)
