__(): Come passare una variabile?
Nella documentazione della funzione di traduzione __( $text, $domain )
, è indicato che devi inserire la stringa direttamente al posto di $text, e che non puoi fare operazioni creative come __( $my_text, 'text-domain' );
.
Tuttavia, sto scrivendo un metodo che riceve una stringa e deve passarla a __(
... )
in qualche modo. C'è un modo, ad esempio tramite printf
o sprintf
, per aggirare questo problema?
Qualcosa del tipo...
function print_description( $text ) {
// Stampa un paragrafo con il testo tradotto
echo '<p>' . __( printf( '%s', $text ), 'text-domain' ) . '</p>';
}

Per tradurre una stringa in WordPress, come nella maggior parte dei CMS che utilizzano PHP, è necessario racchiudere la stringa in una funzione di traduzione GetText (ad esempio __(), _e(), _n(), _x()... ecc.).
La stringa deve inoltre essere inclusa in un file PO (GetText Portable Object files, lo standard del settore per i siti web multilingue in PHP - https://www.gnu.org/software/gettext/manual/html_node/PO-Files.html). Questo file include coppie di stringhe, una di esse è la stringa nella lingua originale e l'altra è la sua traduzione nella lingua di destinazione.
Per creare questi file PO per ogni lingua (ad esempio my-text-domain-it_IT.po per l'italiano, my-text-domain-fr_FR.po per il francese... ecc.) in cui è necessario tradurre il plugin o il tema, il traduttore utilizzerà un file POT (template PO) che contiene tutte le stringhe da tradurre nella lingua originale e aggiungerà una stringa tradotta per ognuna di esse. I file PO vengono compilati in file MO binari, che possono essere elaborati molto più velocemente.
Durante l'esecuzione, le stringhe da tradurre vengono recuperate tramite i file MO e sostituite con la loro traduzione.
I file POT vengono solitamente generati utilizzando strumenti speciali che analizzano i file del codice sorgente ed estraggono le stringhe traducibili.
Se scriviamo codice come questo:
$translated_text = __( $text, 'my_text_domain');
Quando il codice viene analizzato dagli strumenti speciali, il valore della stringa da tradurre ($text) non è ancora definito e quindi non è presente nel codice. Di conseguenza, gli strumenti di ricerca automatica non includeranno questa stringa nel file POT e quindi non sarà inclusa nei file PO né MO.
Durante l'esecuzione, quando il valore della stringa $text presumibilmente sarà già definito, non ci sarà corrispondenza per questo valore nei file di traduzione e la traduzione non sarà possibile.
Tuttavia, se l'insieme dei valori possibili per quella variabile è limitato e li conosciamo, abbiamo due opzioni per superare questo problema:
Opzione 1: Modificare manualmente il file POT per aggiungere le voci con i valori possibili di $text. Questa opzione è semplice e facile da implementare. Qualsiasi editor di codice e una conoscenza minima del formato POT saranno sufficienti. Ma ha un inconveniente. Ogni volta che utilizziamo gli strumenti di ricerca automatica per aggiornare le traduzioni dopo aver modificato il nostro codice, le modifiche che abbiamo apportato andranno perse e dovremo includerle nuovamente manualmente.
Opzione 2: includere nel nostro codice tutti i valori possibili di $text racchiusi da funzioni di traduzione. Vediamo un esempio. Supponiamo che $text possa assumere i valori: mela, arancia, banana, pesca e pera. Dovremmo scrivere il seguente codice:
// questa variabile viene utilizzata solo per includere come parametri nelle
// funzioni di traduzione tutti i valori possibili di $text
$locale = __('mela', 'my_text_domain') .
__('arancia', 'my_text_domain') .
__('banana', 'my_text_domain') .
__('pesca', 'my_text_domain') .
__('pera', 'my_text_domain');
$translated_text = __( $text, 'my_text_domain');
Questa opzione è anche facile da implementare e ha il vantaggio che non andrà persa quando utilizzeremo gli strumenti di ricerca automatica per aggiornare le traduzioni.
Se nel nostro tema o plugin abbiamo diverse variabili che vogliamo siano tradotte e hanno un insieme limitato di valori possibili conosciuti, potremmo includerle tutte in un file separato che deve essere nella cartella principale o in una sottocartella (ad esempio cartella 'includes' o 'assets') del tema o del plugin come mostrato di seguito:
<?php
//valori delle variabili da tradurre
$locale_var1 = __('testo-di-var1_val1', 'my_text_domain') .
__('testo-di-var1_val2', 'my_text_domain') .
__('testo-di-var1_val3', 'my_text_domain') .
.......
__('testo-di-var1_valn', 'my_text_domain');
$locale_var2 = __('testo-di-var2_val1', 'my_text_domain') .
__('testo-di-var2_val2', 'my_text_domain') .
.......
__('testo-di-var2_valn', 'my_text_domain');
.............
$locale_varn = __('testo-di-varn_val1', 'my_text_domain') .
__('testo-di-varn_val2', 'my_text_domain') .
.......
__('testo-di-varn_valn', 'my_text_domain');
Questo è un approccio pulito e mantenibile che mantiene la definizione di queste stringhe in un file separato che può essere modificato senza influenzare altri file di codice.

Grazie per questo @Juan Guerrero. Non sono sicuro del perché questa risposta non abbia ricevuto qualche pollice in su - penso che la tua idea di un file di risorse per insiemi prevedibili di stringhe sia davvero ottima - come dici tu, è un approccio "pulito e mantenibile". Lo userò.

No
Gli strumenti che aiutano nella generazione di una traduzione non possono analizzare il tuo codice e decidere quali sono le stringhe che necessitano di traduzione quando le stringhe passate alle routine di traduzione sono totalmente dinamiche.
Nel tuo esempio, il modo corretto di codificare questa funzione è
function print_description( $text ) {
echo '<p>' . $text . '</p>';
}
e chiamarla
print_description(__('specific description','text_domain'));

No, perché non si può tradurre un testo quando non si sa effettivamente quale sia quel testo.
La traduzione funziona, in sostanza, tramite un grande array. Si prende il codice, si trovano tutte le stringhe in esso contenute, poi si costruisce una grande lista di stringhe. Un traduttore le traduce in un'altra lingua. Poi le varie funzioni di traduzione fanno una ricerca nell'array e restituiscono la stringa tradotta.
Se si usa una variabile per contenere la stringa di testo, allora non c'è modo di sapere in anticipo cosa sia e inserirla nella lista iniziale delle stringhe da tradurre.
Le variabili non possono essere usate nelle funzioni di traduzione, perché questo non ha alcun senso. Non si può tradurre una variabile.

Per qualche motivo, per me funziona passare variabili a _e():
$string = 'ciao';
_e($string, 'textdomain'); // inserisci il tuo textdomain..
// restituirà 'ciao' o 'hello', in base alla lingua corrente
Ovviamente, devi creare il tuo textdomain prima, idealmente nel file yourtheme/functions.php:
add_action( 'after_setup_theme', 'theme_setup' );
function theme_setup() {
load_theme_textdomain( 'yourtextdomain', TEMPLATEPATH . '/languages' );
// [...] altro codice di inizializzazione
}
Se traduco la parola 'ciao' nel file .po, verrà tradotta correttamente nel frontend. Usa Poedit o simili per compilare il .mo. Sia .po che .mo devono essere posizionati in /wp-content/yourtheme/languages (come da codice sopra).
#. Test en_EN.po
msgid "ciao"
msgstr "hello"
Non sono sicuro del motivo per cui funziona, ma funziona, restituirà 'ciao' in italiano e 'hello' in inglese.

Questo funziona solo perché stai aggiungendo manualmente la traduzione. Se usi uno strumento che cerca nel tuo codice le stringhe da tradurre, non troverà la stringa corretta.

Sì certo, ma penso che non sia il problema della domanda originale

Come ho menzionato qui http://www.westofwonder.com/2013/12/whats-with-all-the-double-underscores-everywhere/ (scusate il tema, ho apportato miglioramenti ma non li ho ancora pubblicati), una possibile soluzione a questo problema è creare una funzione per il testo:
function yourtheme_thisisthetext() {
return __( 'Questo è il testo.', 'yourthemetextdomain' );
}
Brutta di per sé, ma per una stringa di traduzione lunga o usata frequentemente, il compromesso potrebbe valere la pena per la leggibilità del codice.
(È permesso? Linkare al mio blog in risposta diretta a una domanda? Se non lo è, mi scuso e non lo farò più.)
