This is the technical support forum for WPML - the multilingual WordPress plugin.
Everyone can read, but only WPML clients can post here. WPML team is replying on the forum 6 days per week, 22 hours per day.
Tagged: Documentation request
This topic contains 5 replies, has 1 voice.
Last updated by HANS 2 months, 2 weeks ago.
Assisted by: Claudio Palacios.
| Author | Posts |
|---|---|
| January 19, 2026 at 2:57 pm #17743037 | |
|
HANS |
When I reload a post in gutenberg, the admin language cookie is not being set correctly. The wrong language in the cookie regularly causes WooCommerce variations to not load, because they do not match the language in the cookie. But even if setting the post language during load would work, we still have the issue that the cookie can change, and if we then try to load the variations, the ajax call will return an empty body because the language of the cookie and the language of the variation do not match. |
| January 20, 2026 at 3:38 pm #17747331 | |
|
Claudio Palacios Supporter Languages: English (English ) Timezone: America/La_Paz (GMT-04:00) |
I understand you are reporting an issue related to the Language Cookie/Multi-tab Issue. |
| January 21, 2026 at 3:02 pm #17750991 | |
|
Claudio Palacios Supporter Languages: English (English ) Timezone: America/La_Paz (GMT-04:00) |
Hello, Thank you for the detailed bug report. I’m a developer on the WPML Dev Team. To help you as quickly as possible, could you please share the exact steps to reproduce the issue? Please also provide temporary admin access and confirm that you authorize us to clone your website using Duplicator for troubleshooting purposes. Thank you, |
| January 22, 2026 at 11:30 am #17753508 | |
|
HANS |
Hi Claudio, To comply with the data protection laws, I can't give you admin access. The main issue is that because of the cookie, it's not really possible to edit multiple posts in parallel, because the language cookie is always only correct for one of the tabs. What's especially annoying is that simply reloading the tab, does not set the cookie to the language of the post, being edited in the tab. I had a look at the implementation and the SitePress class' maybe_set_this_lang() method sets the cookie, but when determining the language, it does not look at the language of the post where the id is passed via the "post" query var, that only happens when the post id is passed via the "p" query var. I already tested this by replacing the line "->map( Obj::path( [ 'get', 'p' ] ) )" with "->map( Obj::path( [ 'get', 'post' ] ) )" and it works. Thanks for your help! Regards |
| January 22, 2026 at 1:04 pm #17754002 | |
|
Claudio Palacios Supporter Languages: English (English ) Timezone: America/La_Paz (GMT-04:00) |
Hi, Thank you for testing this! I really appreciate you taking the time to validate the fix. You're absolutely right about the implementation - and excellent work identifying the exact issue. I can provide you with the complete solution that works for both `post` and `p` query parameters. The Solution The key is to check for `post` first, then fall back to `p` if not found. Here's exactly how to implement it: Fix 1: Backend.php (The one you tested) File: Find (around line 73): private function getPostElementLanguage() {
return function ( $system ) {
/** @var \WPML_Post_Translation $wpml_post_translations */
global $wpml_post_translations;
return Maybe::of( $system )
->map( Obj::path( [ 'get', 'p' ] ) )
->filter( Relation::gt( Fns::__, 0 ) )
->map( [ $wpml_post_translations, 'get_element_lang_code' ] )
->getOrElse( null );
};
}
Replace with: private function getPostElementLanguage() {
return function ( $system ) {
/** @var \WPML_Post_Translation $wpml_post_translations */
global $wpml_post_translations;
$post_id = Maybe::of( $system )
->map( Obj::path( [ 'get', 'post' ] ) )
->getOrElse(
Maybe::of( $system )
->map( Obj::path( [ 'get', 'p' ] ) )
->getOrElse( null )
);
return Maybe::of( $post_id )
->filter( Relation::gt( Fns::__, 0 ) )
->map( [ $wpml_post_translations, 'get_element_lang_code' ] )
->getOrElse( null );
};
}
How it works: This ensures reloading the editor always sets the cookie to match the post's language. Fix 2: Ajax.php (For WooCommerce variations) This addresses the woocommerce_load_variations issue you mentioned. File: Step 1 - Add import (around line 5): Find: use WPML\FP\Maybe; use WPML\FP\Obj; use WPML\FP\Lst; use WPML\FP\Str; use WPML\FP\Fns; use \WPML_Request; Replace with: use WPML\FP\Maybe; use WPML\FP\Obj; use WPML\FP\Lst; use WPML\FP\Str; use WPML\FP\Fns; use WPML\FP\Relation; use \WPML_Request; Step 2 - Update method (around line 14): Find: public function get_requested_lang() {
return Maybe::of( $_REQUEST )
->map( Obj::prop( 'lang' ) )
->filter( Lst::includes( Fns::__, $this->active_languages ) )
->map( 'sanitize_text_field' )
->getOrElse(
function () {
return $this->get_cookie_lang();
}
);
}
Replace with: public function get_requested_lang() {
return Maybe::of( $_REQUEST )
->map( Obj::prop( 'lang' ) )
->filter( Lst::includes( Fns::__, $this->active_languages ) )
->map( 'sanitize_text_field' )
->getOrElse(
function () {
$post_lang = $this->get_post_lang_from_request();
return $post_lang ? $post_lang : $this->get_cookie_lang();
}
);
}
private function get_post_lang_from_request() {
global $wpml_post_translations;
$post_id_keys = [ 'post_id', 'product_id', 'post', 'p', 'id' ];
foreach ( $post_id_keys as $key ) {
$post_id = Maybe::of( $_REQUEST )
->map( Obj::prop( $key ) )
->filter( Relation::gt( Fns::__, 0 ) )
->getOrElse( null );
if ( $post_id ) {
$lang = $wpml_post_translations->get_element_lang_code( $post_id );
if ( $lang && isset( $this->active_languages[ $lang ] ) ) {
return $lang;
}
}
}
return null;
}
How it works: About the FP Library You mentioned wanting documentation. The FP functions you're seeing are from WPML\FP (functional programming helpers). Here's a quick reference for the pattern used: Maybe::of( $value ) // Wraps value in Maybe monad ->map( function ) // Transforms if value exists ->filter( predicate ) // Keeps value if predicate true ->getOrElse( fallback ) // Returns value or fallback Obj::path( ['key', 'subkey'] ) // Gets nested array value Obj::prop( 'key' ) // Gets array property Relation::gt( Fns::__, 0 ) // Greater than 0 check Your specific case: $post_id = Maybe::of( $system )
->map( Obj::path( [ 'get', 'post' ] ) ) // Try $_GET['post']
->getOrElse( // If not found...
Maybe::of( $system )
->map( Obj::path( [ 'get', 'p' ] ) ) // Try $_GET['p']
->getOrElse( null ) // If not found, return null
);
This is equivalent to: $post_id = $_GET['post'] ?? $_GET['p'] ?? null; Next Steps 1. Apply both fixes (make a backup first) Thank you again for the excellent bug report and for testing the fix. Your technical analysis really helped us identify and solve this quickly. Best regards, |
| February 2, 2026 at 3:53 pm #17784640 | |
|
HANS |
Hi Claudio, Thanks for your help, your solution was mostly working. If you want, I can send you the whole patch. Kind Regards |