- Status
- Resolvido
- Tipo
- Não será corrigido
- Relatado para
- WPML Multilingual CMS 5.0
- Tags de tópico
- Compatibility
Visão geral do problema
Desde o WPML 5.0, as trocas de idioma se aninham. Cada código de idioma abre um novo escopo, e apenas null fecha um.
Os plugins escritos para o WPML 4.x frequentemente revertem a troca nomeando o idioma que salvaram:
$current = apply_filters( 'wpml_current_language', null ); do_action( 'wpml_switch_language', 'de' ); // ... do_action( 'wpml_switch_language', $current ); // Meant as "and back".
O WPML 4.x tolerava isso. Ele mantinha um slot de idioma, então o idioma atual acabava ficando correto e a troca desbalanceada passava despercebida. Essa nunca foi uma forma correta de fechar uma troca. O WPML 5.0 não absorve mais isso: a última chamada abre um segundo escopo em vez de fechar o primeiro, e o WPML continua relatando que o idioma está trocado.
O WPML não consegue detectar isso, porque a mesma chamada também é uma troca válida para o idioma de onde veio o código circundante.
O sintoma é adiado. Logo após o par, o idioma atual está correto, então um teste que verifica apenas isso passa. A próxima restauração correta ao seu redor então fecha o seu escopo aberto em vez do dela mesma, e esse código é executado no idioma errado. E-mails, respostas REST e telas do painel de administração são onde isso aparece.
Uma troca sem restauração, ou com um código de idioma vazio, deixa um escopo aberto da mesma forma.
Solução alternativa
Feche cada escopo com null, em um bloco finally:
do_action( 'wpml_switch_language', 'de' );
try {
// ...your work in German...
} finally {
do_action( 'wpml_switch_language', null ); // Closes the scope above.
}
Suporte ao WPML 4.x e 5.0 em uma versão
Copie esses helpers e renomeie o prefixo:
// 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 );
}
Cada local de chamada então se torna:
$previous = myplugin_wpml_open_language_switch( 'de' );
try {
// ... work ...
} finally {
myplugin_wpml_close_language_switch( $previous );
}
Execute grep -rn "wpml_switch_language" . para encontrar cada local de chamada. Cada um precisa de um fechamento correspondente. Nunca restaure nomeando o idioma e nunca altere para um código que possa estar vazio.
Os hooks de e-mail também se aninham: chame wpml_restore_language_from_email uma vez para cada wpml_switch_language_for_email.