- Stato
- Risolto
- Tipo
- Non verrà risolto
- Segnalato per
- WPML Multilingual CMS 5.0
- Tag dell’argomento
- Compatibility
Panoramica del problema
A partire da WPML 5.0, i cambi di lingua si nidificano. Ogni codice di lingua apre un nuovo contesto, e solo null ne chiude uno.
I plugin scritti per WPML 4.x spesso tornano indietro indicando la lingua che hanno salvato:
$current = apply_filters( 'wpml_current_language', null ); do_action( 'wpml_switch_language', 'de' ); // ... do_action( 'wpml_switch_language', $current ); // Meant as "and back".
WPML 4.x lo tollerava. Manteneva un solo slot per la lingua, quindi la lingua corrente risultava corretta e il cambio non bilanciato passava inosservato. Non è mai stato un modo corretto per chiudere un cambio di lingua. WPML 5.0 non lo assorbe più: l’ultima chiamata apre un secondo contesto invece di chiudere il primo, e WPML continua a segnalare che la lingua è cambiata.
WPML non può rilevarlo, perché la stessa chiamata è anche un cambio valido verso la lingua da cui proveniva il codice circostante.
Il sintomo si manifesta in ritardo. Subito dopo la coppia la lingua corrente è corretta, quindi un test che verifica solo questo viene superato. Il successivo ripristino corretto circostante chiude quindi il tuo contesto aperto invece del proprio, e quel codice viene eseguito nella lingua sbagliata. Questo si nota nelle e-mail, nelle risposte REST e nelle schermate dell’area di amministrazione.
Un cambio senza ripristino, o con un codice di lingua vuoto, lascia un contesto aperto allo stesso modo.
Soluzione alternativa
Chiudi ogni ambito con null, in un blocco finally:
do_action( 'wpml_switch_language', 'de' );
try {
// ...your work in German...
} finally {
do_action( 'wpml_switch_language', null ); // Closes the scope above.
}
Supportare WPML 4.x e 5.0 in un’unica versione
Copia questi helper e rinomina il prefisso:
// Opens a scope. Returns the value for the close helper, or false if none opened.
function myplugin_wpml_open_language_switch( $language_code ) {
// '', false and 0 open a scope without changing the language. Only null closes one.
if ( ! $language_code ) {
return false;
}
$previous = apply_filters( 'wpml_current_language', '' );
do_action( 'wpml_switch_language', $language_code );
return $previous;
}
// Closes the scope the open helper opened. WPML 4.x has no stack: there null
// means "the language before the FIRST switch", so restore by name.
function myplugin_wpml_close_language_switch( $previous ) {
if ( ! $previous ) {
return;
}
$has_stack = defined( 'ICL_SITEPRESS_VERSION' )
&& version_compare( ICL_SITEPRESS_VERSION, '5.0', '>=' );
do_action( 'wpml_switch_language', $has_stack ? null : $previous );
}
Ogni punto di chiamata diventa quindi:
$previous = myplugin_wpml_open_language_switch( 'de' );
try {
// ... work ...
} finally {
myplugin_wpml_close_language_switch( $previous );
}
Esegui grep -rn "wpml_switch_language" . per trovare ogni punto di chiamata. Ognuno necessita di una chiusura corrispondente. Non ripristinare mai la lingua per nome e non eseguire mai lo switch su un codice che può essere vuoto.
Anche gli hook delle email si annidano: chiama wpml_restore_language_from_email una volta per ogni wpml_switch_language_for_email.