Skip Navigation
Updated
September 9, 2022

Elementor is a popular page builder plugin that integrates with WPML. Using its API functions, developers can create additional Elementor widgets. This page explains how to make these custom widgets translatable using WPML filters.

This documentation covers how to register custom Elementor widgets for translation using custom PHP code. However, the recommended way is to add them to your language configuration file. This makes it easier to maintain compatibility. Please see our tutorial on how to register page builder widgets for translation using your wpml-config.xml file.

To make it easier to follow this page, we took one of Elementor’s widgets and extended it to include WPML support. You can find it on this GitHub page.

Adding WPML Translation Support

Widget plugins should add the wpml_elementor_widgets_to_translate filter during their “init” action. WPML calls this filter to get further information about the different widget texts that need to be translated.

WPML filter for Elementor widgets
add_filter( 'wpml_elementor_widgets_to_translate', [ $this, 'wpml_widgets_to_translate_filter' ] );

This filter passes the array that lists all the widget types that need to be translated. This array includes default Elementor parts and information about what needs translating.

Any new widget types should be added to this structure, as in the following example.

Adding Elementor widgets
public function wpml_widgets_to_translate_filter( $widgets ) {
  $widgets[ $this->get_name() ] = [
     'conditions' => [ 'widgetType' => $this->get_name() ],
     'fields'     => [
        [
           'field'       => 'title',
           'type'        => __( 'Hello World Title', 'hello-world' ),
           'editor_type' => 'LINE'
        ],
     ],
  ];

  return $widgets;
}

Translation Support for Simple Fields

The code example above shows how translation support is added for simple fields. As you can see, there are some guidelines you should follow:

  • Use the widget name as the key to the new structure that is added to the nodes array.
  • The new structure needs two further items:
    • conditions – an array of conditions to meet. Usually, it is ‘widgetType’widget name.
    • fields – an array of fields that have text that needs translation.

Each of these fields requires the following elements:

  1. field – The id of the field. This is the same as the id used when adding a control via the Control_stack::add_control function.
  2. type – The type of field. This is the text displayed in the WPML Translation Editor to help the translator know what field is to be translated.
  3. editor_type – This is the type of text field used in the WPML translation editor. Valid values are LINE, AREA, and VISUAL.

Translation of More Complicated Widgets

Some widgets have more complicated structures. To add translation support to these widgets, you can create a custom class for handling the translations and implement the IWPML_Page_Builders_Module interface.

You can find more examples in the following folder of the WPML core plugin:

  • ..\wp-content\plugins\sitepress-multilingual-cms\vendor\wpml\page-builders-elementor\src\modules\

First, use the integration-class field to specify the class name that will be used.

Specifying a custom class that features more complicated widgets
public function wpml_widgets_to_translate_filter( $widgets ) {
  $widgets[ $this->get_name() ] = [
     'conditions' => [ 'widgetType' => $this->get_name() ],
     'fields'     => [],
      'integration-class' => 'My_Custom_Widget_WPML_Support’,
     ],
  ];

  return $widgets;
}

The integration class needs to implement the get and update functions. The get function returns the list of strings that need translation and the update function updates the Elementor data when a translation is received.

The following code provides an example of such a custom class.

Example of a custom class that features more complicated widgets
/**
* Class IWPML_Page_Builders_Module
*/
interface IWPML_Page_Builders_Module {
  /**
   * @param string|int $node_id
   * @param mixed $element
   * @param WPML_PB_String[] $strings
   *
   * @return WPML_PB_String[]
   */
  public function get( $node_id, $element, $strings );

  /**
   * @param string|int $node_id
   * @param mixed $element
   * @param WPML_PB_String $string
   *
   * @return array
   */
  public function update( $node_id, $element, WPML_PB_String $string );
}

Multiple Occurrences of the Same Field

If you have multiple occurrences of the same field inside a block, use the field_id to describe a field inside an Elementor block. This allows you to differentiate occurrences of the same field in a node.

Multiple occurrences of the same field
public function wpml_widgets_to_translate_filter( $widgets ) {
 $widgets[ $this->get_name() ] = [
    'conditions' => [ 'widgetType' => $this->get_name() ],
    'fields'     => [
       'title_1' => [
          'field'       => 'title',
          'field_id'   => 'title_1',
          'type'        => __( 'Hello World Title', 'hello-world' ),
          'editor_type' => 'LINE'
       ],
       'title_2' => [
          'field'       => 'title',
          'field_id'   => 'title_2',
          'type'        => __( 'Hello World Title', 'hello-world' ),
          'editor_type' => 'LINE'
       ],
    ],
 ];

 return $widgets;
}

Some widgets can feature lists of other elements, for example, the Elementor Slides widget. Custom widgets like these can extend the WPML_Elementor_Module_With_Items class.

The following WPML_Elementor_Slides class example shows how to do this.

Make sure to load the classes on the init hook. As of WPML 4.5, loading the classes before the init action hook results in a fatal error.

Widgets With Lists of Other Elements

Example of a custom class that features a list of other elements
/**
* Class WPML_Elementor_Slides
*/
class WPML_Elementor_Slides extends WPML_Elementor_Module_With_Items {

  /**
   * @return string
   */
  public function get_items_field() {
     return 'slides';
  }

  /**
   * @return array
   */
  public function get_fields() {
     return array( 'heading', 'description', 'button_text' );
  }

  /**
   * @param string $field
   *
   * @return string
   */
  protected function get_title( $field ) {
     switch( $field ) {
        case 'heading':
           return esc_html__( 'Slides: heading', 'wpml-string-translation' );

        case 'description':
           return esc_html__( 'Slides: description', 'wpml-string-translation' );

        case 'button_text':
           return esc_html__( 'Slides: button text', 'wpml-string-translation' );

        default:
           return '';
     }
  }

  /**
   * @param string $field
   *
   * @return string
   */
  protected function get_editor_type( $field ) {
     switch( $field ) {
        case 'heading':
        case 'button_text':
           return 'LINE';

        case 'description':
           return 'VISUAL';

        default:
           return '';
     }
  }

}

You can find more examples in the following folder of the WPML core plugin:

  • ..\wp-content\plugins\sitepress-multilingual-cms\vendor\wpml\page-builders-elementor\src\modules\

Registering Page Builder Widgets for Translation in Your Language Configuration File

As of WPML 4.4.4, you can also register custom page builder widgets as translatable within your wpml-config.xml file. Please see our documentation about registering page builder widgets for translation.