do_action( 'wpml_switch_language', string|null $language_code )
- Type
- action
- WPML Version
- 3.2.2
Description
This action hook sets the language that WPML uses to filter database queries. It works as a scope: a language code opens the scope, and null closes it.
Switches nest. Since WPML 5.0, WPML keeps the open switches on a stack. Every call with a language code opens a new scope. A call with null closes the last scope that is still open, and gives the language back to the code around you. So null restores the language of your own switch, not the language that the request started in. The two are the same only when your switch is the only one open. When no scope is open, WPML falls back to the language that the request had before its first switch.
Every switch needs its own restore. Pair each call that opens a scope with one call that passes null. Put the restore in a finally block, so it also runs when your code throws an exception. If you leave a scope open, the rest of the request runs in your language, and WPML keeps reporting that the language is switched.
Do not restore by naming the language you came from. A language code always opens a scope. WPML never reads it as a restore. A call like do_action( 'wpml_switch_language', $previous_language ) opens a second scope instead of closing the first one. This is hard to see, because the current language is correct right after the pair. The problem appears later in the request: the scope that you left open is closed by the next restore around you, and that code then runs in the wrong language. Emails, REST responses and admin screens are where it usually shows. This pattern was correct in WPML 4.x, which used one shared slot instead of a stack. If your plugin still uses it, see Restoring the language by name leaves WPML switched.
Change one query at a time. Run your query between the switch and the restore. Do not switch the language in pre_get_posts: that callback ends before the query runs, so you have no place to close the scope.
Arguments
- $language_code
- (string|null) (Optional) The language to switch to. Use the 2-letter (or longer) code of an active language, or ‘all’ to query content from all active languages. Every language code opens a new language scope. Pass
nullto close the scope that your own switch opened. Defaults to null
Only null closes a scope. An empty string, false and 0 open one, like any other value. They do not change the language, so nothing looks wrong at that point, but the scope stays open. Check that your language code is not empty before you pass it.
Example usage
Example
Open a language scope, run your work inside it, and close the scope in a
finally block. The finally block also runs when your code throws an exception.
// Get the 5 latest German posts, then give the language back.
do_action( 'wpml_switch_language', 'de' );
try {
$german_posts = new WP_Query( array(
'post_type' => 'post',
'posts_per_page' => 5,
) );
} finally {
// Closes the scope that the call above opened.
do_action( 'wpml_switch_language', null );
}
Do not restore by naming the language
This pattern was correct in WPML 4.x. Since WPML 5.0 it is a defect: the second call opens a second scope instead of closing the first one.
$current = apply_filters( 'wpml_current_language', null ); do_action( 'wpml_switch_language', 'de' ); // ... do_action( 'wpml_switch_language', $current ); // Wrong: this opens a new scope.
Related hooks
wpml_post_language_details, wpml_switch_language_for_email, wpml_restore_language_from_email, wpml_element_language_code, wpml_element_language_details