Skip to content Skip to sidebar

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.

Sun Mon Tue Wed Thu Fri Sat
- 10:00 – 17:00 10:00 – 17:00 10:00 – 17:00 10:00 – 17:00 10:00 – 17:00 -
- 18:00 – 19:00 18:00 – 19:00 18:00 – 19:00 18:00 – 19:00 18:00 – 19:00 -

Supporter timezone: Asia/Kathmandu (GMT+05:45)

This topic contains 1 reply, has 0 voices.

Last updated by Shekhar Bhandari 1 month, 2 weeks ago.

Assisted by: Shekhar Bhandari.

Author Posts
February 19, 2026 at 9:52 pm #17837256

Heather

So before your 4.9.0 update I was struggling with setting up Redis Cache for my large multilanguage site. With the help of AI, I was able to get it set up. However, we noticed that WPML was suffering from language contamination on the front end. I would load a taxonomy page in one language and then switch to another one and it would remain in that language of the first. I got Claude Opus 4.6 to write me a plugin workaround that basically excluded many of your queries from being put into the Redis cache.

I see with your latest update, you claim many fixes for issues with Redis. Claude pared down our plugin, but claims that we still need half of it even after your fixes. I wanted to know. Is this accurate or a hallucination?

The rest of this message is written by Claude Opus 4.6.

---

Hi,

First — great work on the object cache fixes in WPML 4.9. The TM/admin improvements (translations updating, post status syncing, reviewed translations saving) are welcome and working well.

However, there's a separate class of object cache bug that remains in 4.9: frontend language contamination. When using a persistent object cache like Redis, WPML caches language-specific data (taxonomy permalink
URLs, string translations, URL conversions) under cache keys that don't include the current language. This means a French URL cached by one request gets served to English visitors on the next.

Example: The taxonomy permalink filter caches /fr/subject/overcoming-anger under the same key as /subject/overcoming-anger, so whichever language is cached first wins.

Reproduction

1. Install WPML with directory-based language URLs
2. Enable Redis or Memcached persistent object cache
3. Flush the cache
4. Visit a page with taxonomy links in English — correct English URLs
5. Visit the same page in French — correct French URLs
6. Visit the English page again — French URLs appear (cached from step 5)

Root cause

WPML_Tax_Permalink_Filters::cached_filter_tax_permalink() builds its cache key from [$tag_id, $taxonomy, $is_language_switcher] — the current language is not included. The key is identical across languages:

$cache = $this->cache_factory->create_cache_item( self::CACHE_GROUP, [
$tag_id,
$taxonomy,
$this->is_link_for_language_switcher()
]);

We verified empirically on WPML 4.9.0 that the resulting cache key (md5(json_encode(...))) is the same regardless of language context.

Affected cache groups

The same pattern (language-dependent data, language-agnostic key) exists in multiple groups:

- icl_tax_permalink_filter — taxonomy permalink URLs (primary culprit)
- convert_url — URL language conversion
- WPML_Name_Query_Filter_Translated / Untranslated — query filters
- WPML_Page_Name_Query_Filter — page name lookups
- WPML_ST_CACHE — string translation cache
- WPML_Register_String_Filter — string registration
- wpml_slug_translation_records--post / --taxonomy — slug translations
- wpml_cache_terms_per_lang — term counts per language
- wpml_endpoints_support, wpml_pre_option_page, wpml_term_translation

Our current workaround

We use a must-use plugin that marks these groups as non-persistent via wp_cache_add_non_persistent_groups(), forcing them to use PHP's in-memory runtime cache (per-request only). This prevents contamination but
sacrifices the Redis performance benefit for these groups.

Suggested fix

Include the current language in the cache key for all language-sensitive groups. For example, in cached_filter_tax_permalink:

$cache = $this->cache_factory->create_cache_item( self::CACHE_GROUP, [
$tag_id,
$taxonomy,
$this->is_link_for_language_switcher(),
apply_filters( 'wpml_current_language', '' ),
]);

This would allow each language to cache separately in Redis, giving both correctness and performance.

Alternatively, WPML could register these groups as non-persistent internally (as you already do for ls_languages), though that's less optimal than language-aware keys.

February 20, 2026 at 7:28 am #17837533

Shekhar Bhandari
WPML Supporter since 03/2015

Languages: English (English )

Timezone: Asia/Kathmandu (GMT+05:45)

Hello,

Thank you for contacting WPML support. I’ll be happy to help you with this issue.

I appreciate the detailed description you provided. Before I escalate this to our second-tier team for further evaluation, could you please confirm whether you have a staging site available where I can reproduce the issue using the steps you outlined?

I look forward to your reply.

Thank you.

The topic ‘[Closed] Redis Cache – Language contamination.’ is closed to new replies.