Polylang admin ajax issue

User
Polylang wordpress
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
Assistant
This happens because logged-in users hit `admin-ajax.php` in an **admin context**, so WordPress uses the admin’s profile language (your FR) and Polylang follows that for the AJAX request—then your `pll_language` cookie flips to FR. Logged-out users don’t have a profile language, so the URL `/en/…` wins. (WP added per-user admin language in 4.7, so this behavior is expected.) citeturn1search0turn1search4

### 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). citeturn1search1turn1search13

### 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. citeturn1search1
– 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.) citeturn1search0

Try the 3-step fix first—usually that’s all you need.

User
we are calling gdlr_core_event_g_ajax
and we are using Confera wordpress theme with Goodlayers Core plugin for event management
Assistant
Got it—since you’re using GoodLayers’ AJAX endpoint `gdlr_core_event_g_ajax` (Confera + GoodLayers Core), your calls go through `admin-ajax.php`. When you’re logged in, WordPress runs in the admin user’s language (FR), and Polylang uses that for AJAX—so the request (and cookie) flip to FR even on `/en/…`. Polylang allows forcing the language per-request via a `lang` parameter; we’ll use that and also switch the language **before** GoodLayers’ handler runs. citeturn0search1turn0search21

### 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`. citeturn0search21turn0search1

**Notes**
– No need for the old `pll_load_front` constant; it’s obsolete since Polylang 1.4. citeturn0search21
– 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.

User
but we don't want to edit core functionalities
Assistant
Totally—no core edits needed. We’ll fix it with **additive hooks** + optional JS, all in your child theme or (better) a tiny MU-plugin.

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

Leave a Comment

Your email address will not be published. Required fields are marked *