WPML
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.

Tutti i problemi noti →