Polylang admin ajax issue
August 13, 2025 · AI Conversations
default set FR for admin and site
But when admin logged in and we opned
page like /en/event and perform ajax call from a tabl in this page polylang cookie set language FR even we swithced the labguge rto en
but same condition when we open same page without admin login then its work well and cookie set kanguaegre en for en pages
### Quick fix (recommended)
Pass the page language with every AJAX request and switch it server-side.
**1) Localize the current language to JS**
wp_enqueue_script('my-js', get_stylesheet_directory_uri().'/assets/js/my.js', ['jquery'], null, true);
wp_localize_script('my-js', 'PLL', [
'ajax_url' => admin_url('admin-ajax.php'),
'lang' => function_exists('pll_current_language') ? pll_current_language('slug') : ''
]);
**2) Send `lang` in your AJAX call (e.g., DataTables or jQuery)**
$.post(PLL.ajax_url, { action: 'my_action', lang: PLL.lang }, function (resp) {
// handle response
});
**3) In your PHP AJAX handler, force Polylang to that language**
add_action('wp_ajax_my_action', 'my_action_cb');
add_action('wp_ajax_nopriv_my_action', 'my_action_cb');
function my_action_cb() {
if (function_exists('pll_switch_language') && !empty($_POST['lang'])) {
pll_switch_language(sanitize_text_field($_POST['lang']));
}
// Example: make sure queries also respect language
$q = new WP_Query([
'post_type' => 'event',
'lang' => isset($_POST['lang']) ? sanitize_text_field($_POST['lang']) : ''
]);
wp_send_json_success(/* your data */);
}
Polylang explicitly supports this: you can set the language for AJAX by sending a `lang` parameter (GET or POST). citeturn1search1turn1search13
### Alternative/extra tips
– If you’re calling REST endpoints, append `?lang=en` (or `fr`) to the URL; Polylang respects a `lang` query param as well. citeturn1search1
– Keep your admin profile language in FR; the above fix ensures frontend AJAX stays in the page language and the cookie won’t be flipped by admin-ajax. (Per-user admin language is by design.) citeturn1search0
Try the 3-step fix first—usually that’s all you need.
and we are using Confera wordpress theme with Goodlayers Core plugin for event management
### Fix (reliable + minimal change)
#### 1) Force the language early for GoodLayers’ AJAX action (PHP)
Put this in your (child) theme’s `functions.php` or a small mu-plugin:
// Force Polylang language for GoodLayers event AJAX
add_action('wp_ajax_gdlr_core_event_g_ajax', 'nt_fix_gdlr_event_lang', 1);
add_action('wp_ajax_nopriv_gdlr_core_event_g_ajax', 'nt_fix_gdlr_event_lang', 1);
function nt_fix_gdlr_event_lang() {
if ( ! function_exists('pll_switch_language') ) return;
// 1) Prefer explicit lang from request
$lang = isset($_REQUEST['lang']) ? sanitize_text_field($_REQUEST['lang']) : '';
// 2) Fallback: infer from the referring page URL (/en/... or /fr/...)
if ( ! $lang && ! empty($_SERVER['HTTP_REFERER']) ) {
$path = wp_parse_url(wp_unslash($_SERVER['HTTP_REFERER']), PHP_URL_PATH);
if ( preg_match('#^/([a-z]{2}(?:-[a-z]{2})?)(?:/|$)#i', $path, $m) ) {
$lang = strtolower($m[1]);
}
}
// 3) Last resort: whatever Polylang thinks is current
if ( ! $lang && function_exists('pll_current_language') ) {
$lang = pll_current_language('slug');
}
if ( $lang ) {
pll_switch_language($lang);
}
}
That runs **before** GoodLayers’ own callback, so their queries run in the correct language.
#### 2) Always send the page language with the AJAX call (JS)
If you can’t easily edit GoodLayers’ JS, add a small interceptor:
// Make current page language available to JS (set this where you enqueue your script)
window.PLL = window.PLL || {
lang: (document.documentElement.getAttribute('lang') || 'en').toLowerCase().split('-')[0]
};
// Intercept GoodLayers event AJAX and append ?lang=
jQuery(document).ajaxSend(function (e, xhr, settings) {
if (!settings || !settings.url) return;
var isAdminAjax = settings.url.indexOf('admin-ajax.php') !== -1;
var hitsGdlr = settings.data && settings.data.indexOf('action=gdlr_core_event_g_ajax') !== -1;
if (isAdminAjax && hitsGdlr) {
if (settings.data.indexOf('lang=') === -1 && window.PLL && PLL.lang) {
settings.data += '&lang=' + encodeURIComponent(PLL.lang);
}
}
});
> Why this works: Polylang explicitly supports a `lang` GET/POST parameter for frontend AJAX and uses its cookie only as a fallback; when logged in, admin language can override it. Forcing `lang` + switching early prevents FR from leaking into the request or resetting `pll_language`. citeturn0search21turn0search1
—
**Notes**
– No need for the old `pll_load_front` constant; it’s obsolete since Polylang 1.4. citeturn0search21
– This is theme/plugin-agnostic and safe with Confera/GoodLayers because we don’t alter their output—only ensure Polylang is in the right language before their query runs.
– If your site uses subdomains or different domains per language, the `lang` param still works the same way.
### Option A (server-side only — preferred)
Create `wp-content/mu-plugins/gdlr-polylang-ajax-lang.php` (MU plugins load automatically):
<?php
/**
* Force Polylang language for GoodLayers event AJAX without editing core.
*/
if ( ! defined('ABSPATH') ) exit;
add_action('wp_ajax_gdlr_core_event_g_ajax', 'gdlr_fix_event_lang', 0);
add_action('wp_ajax_nopriv_gdlr_core_event_g_ajax', 'gdlr_fix_event_lang', 0);
function gdlr_fix_event_lang() {
if ( ! function_exists('pll_switch_language') ) return;
// 1) Prefer explicit request param (works with GET or POST)
$lang = isset($_REQUEST['lang']) ? sanitize_text_field($_REQUEST['lang']) : '';
// 2) Fallback: infer from referrer path (/en/... or /fr/...)
if ( ! $lang && ! empty($_SERVER['HTTP_REFERER']) ) {
$path = wp_parse_url(wp_unslash($_SERVER['HTTP_REFERER']), PHP_URL_PATH);
if ( preg_match('#^/([a-z]{2}(?:-[a-z]{2})?)(?:/|$)#i', $path, $m) ) {
$lang = strtolower($m[1]);
}
}
// 3) Final fallback: Polylang current page language if available
if ( ! $lang && function_exists('pll_current_language') ) {
$lang = pll_current_language('slug');
}
if ( $lang ) {
// Switch Polylang language for this request (affects queries + locale)
pll_switch_language($lang);
}
// Important: don't echo/exit here; let GoodLayers' handler run next.
}
> This does **not** touch Confera/GoodLayers code. It just switches Polylang **before** their handler runs, so admin profile language (FR) can’t leak into the AJAX request.
### Option B (tiny client-side helper — no plugin edits)
If GoodLayers’ JS doesn’t already send a `lang` param, add this in your **child theme** JS:
// Get current page language from <html lang="...">
window.PLL = window.PLL || {
lang: (document.documentElement.getAttribute('lang') || 'en').toLowerCase().split('-')[0]
};
// Append &lang=xx to GoodLayers AJAX calls only
jQuery(document).ajaxSend(function (_e, _xhr, settings) {
if (!settings || !settings.url) return;
var isAdminAjax = settings.url.indexOf('admin-ajax.php') !== -1;
if (!isAdminAjax) return;
// normalize data to a querystring
var data = settings.data;
var isString = (typeof data === 'string');
if (!data) data = '';
if (!isString) {
// jQuery will serialize objects; add our key
data.lang = data.lang || (window.PLL && PLL.lang);
settings.data = data;
return;
}
// string case
if (data.indexOf('action=gdlr_core_event_g_ajax') !== -1 &&
data.indexOf('lang=') === -1 &&
window.PLL && PLL.lang) {
settings.data += (settings.data ? '&' : '') + 'lang=' + encodeURIComponent(PLL.lang);
}
});
You can use **Option A alone** (usually enough). Option B just guarantees the `lang` param is present, but still no core edits.
### Why this works
– Logged-in AJAX uses the user’s admin locale (your FR). Our hook flips Polylang to the **page’s** language for that specific `gdlr_core_event_g_ajax` call, so the cookie and results stay in EN on `/en/…`.
– Zero changes to Confera or GoodLayers files; everything is reversible and update-safe.
If you want, share a sample AJAX payload from that page (Network tab → Request payload/query string), and I’ll tailor the param detection exactly to how GoodLayers sends it.