We're experiencing a critical bug where translations for custom Gutenberg blocks exist in the database and are marked as complete (status=10), but are never applied to the translated post content.
---
Root Cause
There's an encoding mismatch between string extraction and translation lookup. We have hex dump proof:
WPML icl_strings.value ends with: ...6572207365696e2eC2A0 (NBSP added by WPML)
Actual post_content contains: ...6572207365696e2e20 (normal space)
WPML modifies strings during extraction (adding xC2xA0, decoding & → &), but searches for the modified version when applying translations → no match found → original text displayed.
---
Reproduction Steps
1. Create custom Gutenberg block using RichText.Content
2. Add text containing spaces or & characters
3. Configure block in wpml-config.xml with XPath
4. Translate via WPML, mark as complete
5. View translated post → original language text is displayed
---
Evidence
-- Translations exist and are complete:
SELECT s.value, st.value, st.status
FROM wp_icl_strings s
JOIN wp_icl_string_translations st ON st.string_id = s.id
WHERE s.context LIKE 'gutenberg-%' AND st.status = 10;
-- Returns rows, but translations are never applied
---
Request
We're happy to:
- Replicate on a new sandbox if you provide one
- Provide a screen recording from our environment
- Share our workaround code that tries multiple encoding variants
The fix should ensure consistent encoding: extraction must match lookup.
Thank you for setting up the Sandbox. I've successfully reproduced the bug.
Bug Summary:
Gutenberg block attributes containing ampersand (&) characters are not translated on the frontend. The original language text is displayed instead of the translation.
Reproduction URLs:
- English (original): hidden link
- German (translation): hidden link
What you'll see on the German page:
Fields WITH ampersand - NOT translated (shows English original):
- Headline: "Sauberkeit & Hygiene 2 English" ❌
- Intro: "Müller & Co bietet Service & Support english" ❌
The issue is in wpml-page-builders/classes/Integrations/Gutenberg/strings-in-block/class-html.php around line 200:
if ($type !== 'VISUAL') {
$string = html_entity_decode($string);
}
The Problem:
1. Post content stores: Sauberkeit & Hygiene (HTML encoded)
2. WPML extracts and decodes: Sauberkeit & Hygiene
3. Translation is stored with hash of decoded string
4. On frontend, WPML looks up hash of & encoded string
5. Hash mismatch → translation not found → original displayed
Demo Plugin:
I've uploaded a custom plugin (wpml-encoding-bug-demo) that creates a test block demonstrating this issue.
Please let me know if you need any additional information.
We've checked the custom implementation and plugin. - thanks for bringing that to our attention.
It seems like a hash mismatch caused by inconsistent HTML entity decoding. Here's probably what's happening:
1. WP saves & as & in post_content (expected behavior).
2. WPML extracts the string, decodes & to &, and hashes the decoded version.
3. On frontend render, it tries to look up the translation using the raw &, not the decoded string.
4. Hashes don't match → translation isn't applied.
This is just a guess for now, based on the provided data, and still needs confirming. For the time being, we don't have a deadline on when to fix this.
As a workaround: edit the original content with the "code editor" (instead of the "visual editor"), and replace & with & only on the content.
Hi Lucas,
Thank you for the update and for confirming the root cause analysis.
I have a few follow-up questions:
Bug Tracker: Has an internal bug report been created for this issue? If so, could you share the ticket/issue number so I can track its status?
Public Bug Tracker: Is this issue documented in WPML's public bug tracker or known issues list?
Timeline: I understand there's no deadline yet, but do you have a rough estimate when this might be addressed? This bug affects all our custom Gutenberg blocks containing ampersands, which is a significant portion of our content.
Regarding the suggested workaround (replacing & with & in the code editor): This is unfortunately not feasible for us, as we have hundreds of existing posts and our content editors work exclusively in the visual editor.
We would appreciate any update on the prioritization of this fix.
Best regards,
Kristof
We have created an internal ticket for this issue, but unfortunately it's not public, so I cannot share that here. As for a public 'known issue', we haven't created one so far, as it's still being analyzed.
I'll double-check with the appropriate team, if we can provide you with a more definite timeline and workaround. I'll be back once I have new information.
The issue is enqueued on our next dev cycles, but its implementation depends on its priority. I appreciate your understanding regarding this. Please let me know if you have other questions.