WP Manifestindependent plugin directory
manifest / i18n / wpml-cf7-email-fix

WPML CF7 Email Fix

Prevents WPML from auto-translating Contact Form 7 mail template fields, which corrupts mail-tags like [your-name] and [your-email]

by Rob Went · github.com/robwent/wpml-cf7-email-fix · website

0stars
0forks

Install

The author publishes release zips, so WP-CLI can install straight from GitHub:

wp plugin install https://github.com/robwent/wpml-cf7-email-fix/releases/download/1.0.0/wpml-cf7-email-fix.zip

Readme

WPML CF7 Email Fix

Prevents WPML from auto-translating Contact Form 7 mail template fields, which corrupts mail-tags like [your-name] and [your-email].

The problem

Contact Form 7 stores each form's email templates in two serialized postmeta keys: _mail and _mail_2. The subject and body of each template can contain CF7 mail-tags such as [your-first-name], [your-email], or custom tags like [tours]. CF7 substitutes these with the submitted form values when sending notification emails.

WPML's Multilingual for CF7 plugin ships a wpml-config.xml that declares _mail and _mail_2 as action="translate", exposing their subject and body sub-keys as translatable text. When Translate Everything or automatic translation runs against a translated form, the mail-tags inside the subject and body get translated along with the surrounding prose — for example, [your-first-name] becomes [votre-prenom] in French.

CF7 does not recognise the translated tags, so they render literally in notification emails instead of outputting the submitted form data. The corrupted values are stored in the translated form's _mail / _mail_2 postmeta and won't show up in WPML's String Translation admin, making the issue easy to miss until emails start arriving with broken content.

The fix

This plugin hooks WPML's wpml_config_array filter and switches the action on the _mail and _mail_2 custom fields from translate to copy-once.

With copy-once:

  • The first time a CF7 form is translated, the source language's _mail / _mail_2 is duplicated verbatim onto the translated form — every mail-tag is preserved exactly.
  • After that, WPML leaves the translated form's mail config alone. You can hand-edit the subject and body in CF7's per-language form admin (Contact → Edit on the translated form) and your edits won't be overwritten on the next sync.
  • The fields never enter the auto-translation pipeline, so ATE / Translate Everything cannot corrupt the tags.

A runtime safety net on wpml_tm_translation_job_data also flags any field-_mail*-subject / field-_mail*-body job element as non-translatable, in case WPML's cached settings still hold the old translate action before its config has been re-parsed.

Requirements

  • WordPress 5.8+
  • PHP 7.4+
  • WPML (Sitepress Multilingual CMS)
  • Contact Form 7
  • WPML Multilingual for CF7

The plugin only takes effect when WPML's config parser runs and a CF7 translation job is created. If WPML or CF7 are not active, the filters are simply never called.

Installation

  1. Download or clone this repository into wp-content/plugins/wpml-cf7-email-fix/.
  2. Activate the plugin from Plugins → Installed Plugins.

No further configuration is needed. Both filters register on plugin load, so the protection is live immediately.

Verifying it works

_mail and _mail_2 are protected meta keys (underscore-prefixed and registered by WPML's config import as read-only), so they will not appear in the WPML → Settings → Custom Fields Translation admin list. That's a UI filter, not a sign that the setting isn't applied.

To confirm the fix is active, the most reliable test is end-to-end:

  1. Create or pick an English CF7 form whose Mail subject/body contains a tag like [your-first-name].
  2. Translate that form to another language (Translate Everything will pick it up, or trigger it manually).
  3. Open the translated form's Mail tab in CF7 admin. The mail-tags should still be [your-first-name] etc., not their translated equivalents.

For a quick spot-check that the runtime filter is wired, you can also confirm by inspecting WPML's stored settings via WP-CLI:

wp option get icl_sitepress_settings --format=json | \
  jq '.["translation-management"].custom_fields_translation | with_entries(select(.key | test("^_mail")))'

After the plugin is active and any CF7 form has been translated (or WPML has re-parsed its config), this should print {"_mail": 3, "_mail_2": 3}3 is WPML's internal constant for copy-once.

Fixing already-corrupted translations

This plugin prevents future corruption but does not repair forms that have already been translated with broken mail-tags. To fix existing ones, you have two options.

Option 1: Edit in the CF7 admin (recommended for a few forms)

  1. Open the translated form in Contact → Contact Forms (switch the WPML language picker to the language you want to fix).
  2. Open the Mail tab and replace any translated mail-tags in the Subject and Message Body with the originals — e.g. [votre-prenom][your-first-name].
  3. If the form uses Mail (2), repeat for that tab.
  4. Save.

Option 2: Database search and replace (for many forms or sites with many languages)

Run a search and replace against the postmeta rows for _mail and _mail_2. The values are PHP-serialized arrays, but because mail-tags are short bracketed strings of a fixed length, simple string substitution works without breaking the serialization — provided the replacement string is exactly the same byte length as the search string. If the lengths differ, run the replacement through WP-CLI's search-replace instead so it re-serializes safely.

First, find affected forms (replace wp_ with your table prefix):

SELECT post_id, meta_key
FROM wp_postmeta
WHERE meta_key IN ('_mail', '_mail_2')
AND meta_value LIKE '%[votre-prenom]%';

Then fix with WP-CLI (handles serialized data correctly even when lengths change):

wp search-replace '[votre-prenom]' '[your-first-name]' wp_postmeta \
  --include-columns=meta_value --dry-run

Remove --dry-run once you've confirmed the matches. Always back up your database first.

Repeat for every translated mail-tag the auto-translation produced — [votre-email][your-email], [tous-les-champs] → etc. You can build the list by grepping the affected meta_value rows for [...] substrings.

License

GPL-2.0-or-later

Read the full README on GitHub →

Releases

TagPublishedAssetDownloads
1.0.0 Jul 17, 2026 wpml-cf7-email-fix.zip 0