Skip Navigation
Updated
November 27, 2023

WPML lets you specify which parts of the custom Gutenberg blocks you develop should be translated. You can do this by configuring settings in the wpml-config.xml file.

The wpml-config.xml file is a configuration document that instructs WPML which elements in your themes and plugins should be translated.

This guide is for developers who create their own custom blocks for Gutenberg. If you’re using core or third-party blocks, read our page about translating content created using the Gutenberg editor.

Need to generate a wpml-config.xml file? Visit our step-by-step guide for automatically generating a configuration file using the Multilingual Tools plugin.

On this page

Registering Gutenberg blocks as translatable

Let’s say that you have an image that is shown using the following code:

Example of image that needs to be translated
<!-- wp:image {"id":3} -->
<figure class="wp-block-image"><img src="http://example.com/wp-content/uploads/2018/07/figure-2.png" alt="Image alt text" class="wp-image-3"/><figcaption>Image Caption</figcaption></figure>
<!-- /wp:image -->

You want to translate the figcaption and the alt attribute values of this image.

To achieve this, you need to insert the following code into wpml-config.xml:

Example of settings for translation of Gutenberg block
<wpml-config>
  <gutenberg-blocks>
    <gutenberg-block type="core/image" translate="1">
        <xpath>//figure/figcaption</xpath>
        <xpath>//figure/img/@alt</xpath>
    </gutenberg-block>
  </gutenberg-blocks>
</wpml-config>

Please bear in mind that the type is core/image and not wp:image since this is the value returned by the block API.

You can specify which Gutenberg block fields are links. WPML will then replace any links with their translations if they are available.

Translation of links in Gutenberg blocks
<wpml-config>
  <gutenberg-blocks>
    <gutenberg-block type="core/some-block" translate="1">
        <xpath type="link">//a/@href</xpath>
    </gutenberg-block>
  </gutenberg-blocks>
</wpml-config>

Translation of block attributes

Here is one example of a format for the definition of an editor block:

Format for the definition of an editor block
<wpml-config>
  <gutenberg-blocks>
    <gutenberg-block type="my-plugin/my-block" translate="1">
        <xpath label="My Block">//p</xpath>
        <key name="title" />
        <key name="foo">
            <key name="bar1" />
            <key name="bar2" />
        </key>
        <key name="/^[^_]\S+$/" search-method="regex" />
        <key name="something" search-method="wildcards" />
    </gutenberg-block>
  </gutenberg-blocks>
</wpml-config>

You can use the key element in the same way as it is used with the Admin texts / wp_options configuration. This also means that you can have key elements inside parent key elements.

You can use the label attribute to add optional custom labels that display in the Advanced Translation Editor next to the block elements. When the label attribute is part of the gutenberg-block tag, it will be used as a fallback label for elements of the block that don’t have a specific label defined.

Example of a fallback label
<wpml-config>
    <gutenberg-blocks>
        <gutenberg-block type="my-plugin/mybutton" translate="1" label="My fallback block label">
            <xpath>//span</xpath>
            <xpath>//a@href</xpath>
        </gutenberg-block>
    </gutenberg-blocks>
</wpml-config>
Fallback label in the Advanced Translation Editor
Fallback label in the Advanced Translation Editor

The attribute search-method can have one of two values:

  • wildcards (default)
  • regex.

You can use wildcards in the same way as for admin texts. This means that an asterisk (*) can be used in the name attribute. Here is an example of one block:

Example of a block
<!-- wp:my-plugin/my-block
    {
        "myp": {
            "mypTitle":"The title",
            "mypContent":"The Content",
            "_mypSystem:"Meta attribute to not translate"
        }
    }
/-->

You can set the block definition using a wildcard:

Block definition using a wildcard
<wpml-config>
  <gutenberg-blocks>
    <gutenberg-block type="my-plugin/my-block" translate="1">
      <key name="myp">
          <key name="myp*" />
      </key>
    </gutenberg-block>
  </gutenberg-blocks>
</wpml-config>

This will allow you to translate “The title” and “The content” since these are the only attributes starting with myp.

The regex allows you to have a regular expression in the name attribute. This can be extremely useful for complex configurations. Here is an example of one block:

Complex configuration - example
<!-- wp:my-plugin/my-block
    {
        "data": {
            "title":"The title",
            "_title":"e980759463943209f6f1ae09a239e353",
            "content":"The Content",
            "_content":"1502a7b825dfe7b789c63830609f1701"
        }
    }
/-->

You can set the block definition with a regular expression:

Block definition with a regular expression
<wpml-config>
  <gutenberg-blocks>
    <gutenberg-block type="my-plugin/my-block" translate="1">
        <key name="data">
            <key name="/^[^_]\S+$/" search-method="regex" />
        </key>
    </gutenberg-block>
  </gutenberg-blocks>
</wpml-config>

This will allow you to translate “The title” and “The content” since these are the only attributes not starting with underscore (_).

Some block plugins save data in a URL-encoded JSON string inside a block’s attribute. The encoding attribute allows you to decode the string and register its subkeys for translation.

For example, the LazyBlocks plugin stores repeater field content in an encoded JSON string:

Example of LazyBlocks block with URL-encoded JSON string
<!-- wp:lazyblock/testwpml {"name":"%5B%7B%22firstname%22:%22Shekhare%22,%22lastname%22:%22Bhandari%22%7D,%7B%22firstname%22:%22Compatibility%22,%22lastname%22:%22Escalation%22%7D%5D","blockId":"Z169b0O","blockUniqueClass":"lazyblock-testwpml-Z169b0O"} /-->

You can register the firstname and lastname subkeys using the following XML configuration:

Example of registering URL-encoded JSON strings inside a block's attribute
<wpml-config>
  <gutenberg-blocks>
    <gutenberg-block type="lazyblock/team" translate="1">
      <key name="name" encoding="json">
        <key name="*">
          <key name="firstname" />
          <key name="lastname" />
        </key>
      </key>
    </gutenberg-block>
  </gutenberg-blocks>
</wpml-config>

Block Namespace

You can have a global configuration for the block namespace.

Block name is no longer a required part of the definition.

If the block configuration is the same for all blocks in a namespace you can write it like this:

Blocks in a namespace
<wpml-config>
  <gutenberg-blocks>
    <gutenberg-block type="my-plugin" translate="1">
        <key name="data">
            <key name="/^[^_]\S+$/" search-method="regex" />
        </key>
    </gutenberg-block>
  </gutenberg-blocks>
</wpml-config>

Automatically converting IDs in blocks

The ID conversion is versatile and tries to adapt to most possible formats of IDs (single ID, list of IDs, serialized array, JSON encoded array).

Consider the following block:

Automatically converting IDs in blocks - Block Example
<!-- wp:foo/form {"ids":[27,28]} -->
<div class="wp-block-foo-form-wrap">
  <form class="foo-form" action="" method="post">
    <input type="hidden" name="foo_form_post_ids" value="27,28" />
    <input type="submit" />
  </form>
</div>
<!-- /wp:foo/form -->

You can declare, as post IDs, the block attribute IDs and the HTML tag attribute value foo_form_post_ids as below:

Block attribute ids and the HTML tag attribute value
<gutenberg-block type="foo/form" translate="0">
  <key name="ids">
      <key name="*" type="post-ids" sub-type="post" />
  </key>
  <xpath type="post-ids" sub-type="post">//*[@name="foo_form_post_ids"]/@value</xpath>
</gutenberg-block>

The block will be converted with the highest priority on the filter render_block_data as below:

Block converted by the render_block_data filter
<!-- wp:foo/form {"ids":[42,43]} -->
<div class="wp-block-foo-form-wrap">
    <form class="foo-form" action="" method="post">
        <input type="hidden" name="foo_form_post_ids" value="42,43" />
        <input type="submit" />
    </form>
</div>
<!-- /wp:foo/form -→

You can use the following config attributes:

  • type – can be post-ids or taxonomy-ids
  • sub-type (optional): can be the specific entity of the type if it’s already known. For instance, product for the Product custom post type. If not defined, the specific entity will be guessed.

Additional Resources

To learn more about the wpml-config.xml file, visit the Language Configuration Files guide.

For customizing other elements using the wpml-config.xml file, visit our additional guides: