WPML

Before You Start

Install and activate these plugins:

  • Advanced Custom Fields or ACF Pro.
  • WPML and WPML String Translation.
  • ACFML (the add-on this page covers).

Your Field Groups should already be configured in ACF. You can change the per-field translation preferences after the fact, so the order of operations doesn’t matter. Set up the Field Groups, then come back to ACFML.

Pick a Translation Option for Each Field Group

ACF Field Groups don’t all behave the same way under translation. ACFML offers three translation options for each Field Group. To pick one:

  1. Go to ACFField Groups and edit the Field Group.
  2. In the Multilingual Setup section, under Select a translation option for this field group, click Choose on the option you want.
  3. Save the Field Group.

ACFML marks the option it suggests for your site as recommended for this site. To pick another option later, click Change option. Older ACFML versions call the first two options Same fields across languages and Different fields across languages.

Same Content in Every Language, Translated

The typical setting for most ACF sites. Visitors in every language see the same pages, in their own language. The text translates, and the layout and settings stay the same. The Our Team page is the usual example. Your team is the same in every language, so each team member’s name and bio translate, and the field structure stays the same. You enter the team in the default language, then send the post for translation from WPMLTranslationsDashboard. The translated values come back into the same fields. This option works with automatic translation and Translate Everything.

Each Language Has Its Own Content

Use this option when each language shows different content in the same Field Group. The usual example is a company that runs local events. The English Events page shows events for an English audience, and the French page shows events for a French audience. The fields start as a copy of the original. After that, each language keeps its own values. You edit each language in the WordPress editor: open the post, click the plus icon for the target language in the Language box, fill in the values for that language, and publish. WPML does not sync the language versions afterwards, and automatic translation does not apply.

Expert

Use this option when you need a mix: some fields translate, some stay the same, and some copy once and then change in each language. Pick Expert and set the translation preference of each field by hand. In the Events example, the title and the description use Translate, and the price, the date and the address use Copy. ACFML does not recommend this option for new Field Groups. A Field Group defined in PHP or Local JSON can have no translation option. Then it uses Expert only when the Field Group exists before your site updates to WPML 5.2.

Translation Preferences for Each ACF Field Type

Every field that stores a value has one of four translation preferences:

  • Translate. Visitors see the value in their own language. WPML fills it with the translation. You edit it in the translation editor.
  • Copy. Visitors in every language see exactly what the original shows. The field is locked in the other languages.
  • Copy once. The value starts as a copy of the original. After that, you edit it in each language by hand. If you empty the field in a translation, it stays empty. WPML does not copy the original value into it again.
  • Don’t translate. Translations start without this value. You can fill it in each language by hand.

When you pick Same content in every language, translated or Each language has its own content, ACFML gives each field the recommended preference for its field type. The tables below show these recommended preferences. To set a different preference for one field, use Expert. To change the recommended preference of a field type on the whole site, use the acfml_field_group_mode_field_translation_preference filter (see Developer Hooks for Edge Cases below).

Tab, Accordion, Message and Separator fields do not store a value, so they have no translation preference. A field type that is not in the tables, for example a field type from another plugin, gets Copy with both translation options.

Repeater, Flexible Content, Group and Clone Fields

These fields hold other fields. The recommended preference of the container field is Copy or Copy once. ACFML does not offer Translate for the container field itself. Each sub-field has its own translation preference.

With Same content in every language, translated, the rows of Repeater and Flexible Content fields stay in the same order as in the default language. With Expert, or when a post uses Field Groups with different options, the post editor shows an ACFML Synchronise translations box. It shows on the original post when the post has translations and a Repeater or Flexible Content field. Select Keep repeater and flexible sub-fields in the same order as the default language to keep the rows aligned in all languages.

Basic Fields

TypeSame content in every language, translatedEach language has its own content
TextTranslateTranslate
Text AreaTranslateTranslate
NumberCopyCopy once
RangeCopyCopy once
EmailCopyCopy once
URLTranslateTranslate
PasswordCopyCopy once

Content Fields

TypeSame content in every language, translatedEach language has its own content
ImageCopyCopy once
FileCopyCopy once
Wysiwyg EditorTranslateTranslate
oEmbedCopyCopy once
GalleryCopyCopy once

Choice Fields

TypeSame content in every language, translatedEach language has its own content
SelectCopyCopy once
CheckboxCopyCopy once
Radio ButtonCopyCopy once
Button GroupCopyCopy once
True / FalseCopyCopy once

jQuery Fields

TypeSame content in every language, translatedEach language has its own content
Google MapCopyCopy once
Date PickerCopyCopy once
Date Time PickerCopyCopy once
Time PickerCopyCopy once
Color PickerCopyCopy once
Icon PickerCopyCopy once

Layout Fields

TypeSame content in every language, translatedEach language has its own content
GroupCopyCopy once
RepeaterCopyCopy once
Flexible ContentCopyCopy once
CloneCopyCopy once

Relational Fields

TypeSame content in every language, translatedEach language has its own content
LinkTranslateTranslate
Post ObjectCopyCopy once
Page LinkCopyCopy once
RelationshipCopyCopy once
TaxonomyCopyCopy once
UserCopyCopy once

For a Link field, the translation covers the link text and the URL. When the URL points to a page on your site and you do not change it, WPML shows the page in the visitor’s language.

Starting with ACFML 5.0, URL and Link fields use the Translate preference by default.

TypeSame content in every language, translatedEach language has its own content
URLTranslateTranslate
LinkTranslateTranslate

Bidirectional Relationships

Since ACF 6.2, Relationship, Post Object, Taxonomy and User fields can be bidirectional. When you select a target in the field, ACF adds your post to the paired field of the target. For example, the book Dune sets its Author field to Frank Herbert. ACF then adds Dune to the Books field of Frank Herbert.

ACFML keeps the pair in each language:

  • When WPML copies the field to a translation, ACFML points the field to the target in the same language. Then ACFML adds the translation to the paired field of that target. The Spanish Dune shows the Spanish Frank Herbert, and the Spanish Frank Herbert lists the Spanish Dune.
  • When the field uses Copy and you change the target in the original post, WPML updates the translation. ACFML adds the translation to the new target in that language and removes it from the old target.
  • ACFML changes only the targets in the language of the translation. The posts in the original language keep their own pair.
  • When the target has no translation yet, the translation points to the original target, and ACFML does not change the original target. When you translate the target later, ACFML points the field to the new translation and adds the post to its paired field. The field lists the target one time.
  • Users have no translations, so ACFML does not add translations to the paired field of a user. That field keeps the original post. In another language, ACFML shows the translation of that post, unless the field uses Copy.

This works for the Copy and Copy once preferences, which are the recommended preferences for these field types. It also works when you duplicate a post with WPML.

Translate ACF Blocks

By default, ACF blocks save their field values inside the block, in the post content, not as custom fields. ACFML sends these values for translation together with the rest of the post, in the same translation job.

  • The block uses the translation option and the field preferences of the Field Group whose location rule is this block.
  • ACFML sends only the fields that use Translate. Fields that use Copy, Copy once or Don’t translate keep the value from the original block.
  • Repeater and Flexible Content fields inside a block translate too, also when they are nested. Each sub-field uses its own translation preference.
  • A block with "usePostMeta": true in the acf section of its block.json saves its values as custom fields of the post, not in the block. These values translate like any other custom field of the post, with the translation option and the field preferences of the Field Group.
  • When you change a translation preference in a Field Group that you use on blocks, WPML asks if you want to update the existing translations. If you confirm, WPML marks the translations of these posts as needing an update. Send them for translation again to apply the change. A change to Don’t translate does not mark them.

Fields Declared in block.json

Since ACF 6.8.1, a block can declare its fields in its block.json file, in acf.fields. ACF creates a Field Group for these fields, and you cannot edit this Field Group in the admin. ACFML gives it the Same content in every language, translated option and the recommended preference for each field type, like a Field Group registered in PHP.

To use another option for the whole group, add acfml_field_group_mode to the acf section of block.json, or to acf_register_block_type(). The accepted values are translation (Same content in every language, translated), localization (Each language has its own content) and advanced (Expert). ACFML ignores any other value.

{
    "name": "acme/event-card",
    "title": "Event Card",
    "acf": {
        "mode": "preview",
        "acfml_field_group_mode": "localization",
        "fields": [ ... ]
    }
}

To set the preference of one field, add wpml_cf_preferences to that field. ACFML keeps this preference with every option. With Expert, only the fields that declare wpml_cf_preferences get a preference.

When block.json does not name an option, ACFML stores the option it gives the group the first time it sees the group, and keeps it after that. On sites that used these blocks with an older ACFML version, the stored option is Expert.

Setting Preferences for Fields Registered in PHP or JSON

ACF Field Groups registered in PHP (with acf_add_local_field_group()) or through ACF’s Local JSON feature don’t take translation preferences from the admin screens, because the admin doesn’t manage them. Set the preferences in the same place where you register the fields.

To set the translation option of the Field Group, add the acfml_field_group_mode key to the definition, with translation, localization or advanced (Expert). When the definition sets no translation option, ACFML gives the Field Group the Same content in every language, translated option the first time it sees the group. ACFML stores this option and keeps it after that. Field Groups that exist before your site updates to WPML 5.2 keep Expert.

For each field in the field-group definition, add a wpml_cf_preferences key. The value is an integer that maps to the four translation preferences: 0 for Don’t translate (WPML ignores the field), 1 for Copy (the value stays in sync across languages), 2 for Translate (the value goes through translation), and 3 for Copy once (the value copies to new translations, then each language can be edited independently).

A minimal example:

acf_add_local_field_group( [
    'key'    => 'group_1',
    'title'  => 'My Group',
    'fields' => [
        [
            'key'                 => 'field_1',
            'label'               => 'Sub Title',
            'name'                => 'sub_title',
            'type'                => 'text',
            'wpml_cf_preferences' => 2, // Translate.
        ],
    ],
    // ...rest of the field-group config
] );

After you define the fields in code, sync the preferences into WPML so the admin recognizes them:

  1. Go to ACFTools.
  2. Scroll to Translate ACF Local JSON and PHP-Registered Fields.
  3. In Sync Translation Preferences for Local Fields, select Sync once now and click Apply.

WPML reads the preferences from your field definitions and stores them. Sync once now runs one time. If you change the definitions often, select Sync on every request (may affect performance) instead. This option runs the sync on every admin request.

If you use ACF’s Local JSON feature to share field groups between sites, ACFML writes the translation preferences into the JSON files automatically. Export a JSON file from one site, import it on another, and the destination site picks up the preferences once ACFML is active on both ends.

Field Groups that ACF creates with the wp acf json import WP-CLI command, or through its Abilities API for AI tools, are stored in the database. ACFML gives them the Same content in every language, translated option and the recommended preference for each field type. When the imported JSON already has an acfml_field_group_mode key, ACFML uses that option instead.

Field Groups in Local JSON Files

ACF loads the Field Groups of the acf-json folder very early in each request. Starting with WPML 5.2, ACFML reads these Field Groups at the same time. So when you sync the translation preferences, the sync covers JSON Field Groups too. WPML then uses the preferences in the JSON files.

In the JSON file, add wpml_cf_preferences to each field, with the same values as in PHP. This key sets the preference of each field, whatever the translation option of the Field Group. The example uses Expert:

{
    "key": "group_event",
    "title": "Event",
    "acfml_field_group_mode": "advanced",
    "fields": [
        {
            "key": "field_event_title",
            "label": "Event Title",
            "name": "event_title",
            "type": "text",
            "wpml_cf_preferences": 2
        },
        {
            "key": "field_event_price",
            "label": "Price",
            "name": "event_price",
            "type": "number",
            "wpml_cf_preferences": 1
        }
    ]
}

To send the preferences and the labels of JSON Field Groups to WPML:

  1. Go to ACFTools.
  2. Scroll to Translate ACF Local JSON and PHP-Registered Fields.
  3. In Sync Translation Preferences for Local Fields, select Sync once now or Sync on every request (may affect performance).
  4. In Register Labels for Translation, select Register labels now.
  5. Click Apply.

To check the result, go to WPMLSettings and find the fields in Custom Fields Translation. Each field shows the preference from the JSON file. ACFML also registers the labels of the Field Groups, post types, taxonomies and Options Pages that exist only in code: in the acf-json folder or registered in PHP. Translate them like the labels of any other Field Group (see Translate ACF Field Labels below).

Translate ACF Field Labels

ACF field labels are the names that identify each custom field in the WordPress editor and on the front-end (e.g., Phone number, Address). They translate separately from the field values, and they live in WPML String Translation, not in the post’s translation job.

To send field labels for translation:

  1. Open WPMLTranslationsDashboard.
  2. Expand the ACF Field Group section.
  3. Select the Field Group Labels item for the Field Group you want to translate.
  4. Pick a translation method (PTC, your translator, or Translate myself) and send.

The translated labels appear on the front-end automatically once the translation completes.

Stop Translating Field Labels

By default, the translation job of a post does not include the field labels. You translate them only when you send the Field Group Labels item from the Dashboard. If you do not send it, ACF shows the original labels. To show the original labels even when translations exist, use the acfml_should_translate_acf_entity filter and return false for the fields or the Field Groups that you want to skip. The ACFML hooks and constants reference has an example.

Translate ACF Field Choices

Choice fields (Select, Checkbox, Radio Button, Button Group) carry their own option labels (e.g., Small / Medium / Large). These also live alongside the field labels rather than inside the post translation. Send them the same way:

  1. Open WPMLTranslationsDashboard.
  2. Expand the ACF Field Group section.
  3. Select the Field Group whose choice values you want to translate.
  4. Pick a translation method and send.

Translate ACF Options Pages

ACF Options Pages (global settings screens like Contact details, Header settings, Footer links) translate as their own object type, separately from posts:

  1. Open WPMLTranslationsDashboard.
  2. Expand the ACF Options section.
  3. Select the Options Page you want to translate.
  4. Pick a translation method and send.

Each language’s Options Page values appear automatically when ACF reads the option in that language’s context.

The translation option of the Field Group on the Options Page decides what happens to each field:

  • Fields that use Translate go into the ACF Options item that you send from the Translation Dashboard. When the translation is complete, ACFML writes the values to the Options Page of that language. Repeater and Flexible Content fields get the same rows as the original.
  • Fields that use Copy get the value of the original in every language. When you save the original, ACFML updates the other languages.
  • Fields that use Copy once start as a copy of the original. After that, you edit them on the Options Page of each language.

Use Each language has its own content when the options differ by language. For example, an Options Page lists three sales agents in English and two in Spanish. To pick the option, edit the Field Group, like for any other Field Group.

To change a finished translation, go to WPMLTranslationsTranslation Jobs and click Edit on the ACF Options job. You can also edit the translated values in WPMLString Translation. When you save a translation there, ACFML writes it to the Options Page of that language.

When you change the default language of the site, the existing Options Page values stay in the language that you wrote them in. ACF reads the same values as before the change.

In code, get_field( 'my_field', 'option' ) returns the value of the current language. After do_action( 'wpml_switch_language', 'fr' ), it returns the French value. This also works for Options Pages with a custom post_id.

Common Pitfalls

  • Field labels look untranslated. They live in String Translation, not the post translation. Send the Field Group’s Field Group Labels item from the Dashboard (see Translate ACF field labels above).
  • Choice values look untranslated. Same shape. Send the Field Group from the Dashboard’s ACF Field Group section so the option values get included.
  • Repeater rows fall out of sync. The Field Group probably uses Expert. Edit the original post, select Keep repeater and flexible sub-fields in the same order as the default language in the ACFML Synchronise translations box, and update the post. Or switch the Field Group to Same content in every language, translated.
  • Conditional logic behaves unexpectedly. When the controlling field is set to Copy or Don’t translate, the conditional behavior follows the source-language value across all translations. Set the controlling field to Translate if its value should differ per language.
  • Local fields (PHP-registered) ignore translation preferences set in the admin. Set the wpml_cf_preferences key in the field-group definition itself and sync from ACFTools. The procedure is in Setting Preferences for Fields Registered in PHP or JSON above.

Developer Hooks for Edge Cases

For programmatic control (opt specific fields out of translation, override the default preference for a field type site-wide, hide annotations from translators, or exclude field group strings from post translation jobs), ACFML has two filters and four constants. The full reference with code examples lives at ACFML hooks and constants reference.

Written byAmir