Skip Navigation
May 2, 2022

The String Package Translation is a module integrated in the WPML String Translation plugin. It provides functionality that allows to translate complex constructs with WPML. It’s ideal for forms, visual editors, events and other elements that don’t quite fit into posts and fields.

WPML String Package Translation interface is intended for developers, who are building themes and plugins that produce their own elements. This interface allows to register “text groups” that require translation, bundle them in the same “context” and make it easier for end-users to translate.

If you are already finding yourself asking: “What is a ‘text group’ or a ‘context’?” just think of forms. Forms are made up of input and select fields; perhaps a textarea, a select drop-down, etc. Each form field is an individual element in itself but grouped together they make up a form. The grouped form fields are the ‘text group’. The ‘context’ is the form. Form fields are best kept together as a group for translation purposes. This helps translators see the context they belong in, which in turn makes translation easier and faster.

What We Want to Translate

Layouts allows to design page layouts using a drag and drop interface. Layouts include rows and rows contain cells. Some of these cells include texts and some include content that comes from the database.

Fortunately, everything that comes from the database doesn’t require any effort to be multilingual-ready. As long as the ‘other plugin’ uses the WordPress API to load its content, it will arrive in the correct language.

However, the text cells require translation. If a layout includes some text, you probably want to see it in the right language.

Our Layouts plugin, like many other plugins and themes, doesn’t have the concept of language. It just lets you create layouts without giving them a language. We don’t want to create different layouts for every language. This will be redundant work. Most of the elements in a layout don’t require translation. We want to use the same layouts for all languages and translate the texts in them. If it helps, think of it like using Gettext for PHP-templates, only with dynamic texts.

This is an example layout:

Layout with texts that need translation
Layout with texts that need translation

The text cells that require translation are the logo and the footer. All other content comes from the database.

Registering Strings for Translation

WPML defines the wpml_register_string action, which lets you register strings for translation.

To use it, add the following to your code, when texts are created or updated:

do_action( 'wpml_register_string', string $string_value, string $string_name, array $package, string $string_title, string string_type );


  • $string_value
    • (string) (Required)  The string to be translated.
  • $string_name
    • (string) (Required)  The name/slug of the string. This value needs to be unique among the strings in this ‘package’.
  • $package
    • (array) (Required)  See context description below
$package = array(
 'kind' => 'Layout',
 'name' => 'homepage-layout',
 'title' => 'Homepage Layout',
 'edit_link' => 'LINK TO EDIT THE FORM',
 'view_link' => 'LINK TO VIEW THE FORM'

$package contents:

$kind – what kind of object this is. For example ‘Gravity Form’ or ‘Layout’. This is used in the Translation Dashboard to filter objects by kind.

$name – the ‘machine name’, which should not change. For posts, like in Layouts, the best would be to use the ID.

$title – the human name. We need it to display the object in the Translation Dashboard.

$edit_link – link to edit the object. This is displayed in Translation Management dashboard. You can omit this or set to an empty string.

$view_link – link to view the object. This is displayed in Translation Management dashboard. You can omit this or set to an empty string.

  • $string_title
    • (string) (Required) The Title of the string to be displayed while editing the translation.
  • $string_type
    • (string) (Required) Specifies the type of control to use to edit the string. ‘LINE’, ‘AREA’, ‘VISUAL’

First, you need to choose the name of the Type that you are going to register. This Type should be the same for all the strings and objects that you will register. It’s just a string, so make sure that it’s unique and allows users to identify your items.

Next, decide how to organize strings into objects. This should come natural if you are translating strings that belong to ‘something’. In our example, strings belong to our layouts.

Finally, choose when to register strings. The best time to do this is when your code creates or updates strings.

Now that you’re ready, you can start using the string registration filter from WPML.

The $package array will be the same for all texts you send to translation for an object. In our case it’s a layout. So, you can set up that package once at the beginning of the code that updates or creates your objects.

Then, use it every time you register a string that needs translation. The other values in the wpml_register_string action depend on the string that you’re registering.

Meta code:

$package = array(
           'kind' => 'Layout',
           'name' => 'homepage-layout',
           'title' => 'Homepage Layout',
           'edit_link' => 'LINK TO EDIT THE FORM');

do_action('wpml_register_string', $layoutname, 'name', $package, 'Layout name', 'LINE');

do_action('wpml_register_string', $cell1txt, 'cell1-txt', $package, 'Cell 1', 'AREA');

do_action('wpml_register_string', $cell2txt, 'cell2-txt', $package, 'Cell 2', 'AREA');

Applying Translations Before Output

Registering the texts with WPML allows them to get translated. Before rendering, you want to apply another filter, which will replace the texts in the original language with the translations.

For this, we use the wpml_translate_string filter:

$translated_string = apply_filters( 'wpml_translate_string', string $string_value, string $string_name, string $package )

It receives the same arguments as the registration filer, just without the title and string type These are not needed to look up translations.

Just as you would use GetText calls for static texts, use the wpml_translate_string filter before outputting texts that you previously registered. If translation exists, the translation will be returned. Otherwise, you’ll get back the original text.

How it Looks to Users When Translating

Because you’ve provided full context when registering texts for translation, WPML can make it easy for users to find your objects and translate them.

Go to WPML->Translation Management. After you register your first texts, you will see the ‘kind’ that you selected in WPML’s ‘Content type’ filter.

Your registered type in the Translation Dashboard
Your registered type in the Translation Dashboard

Once people select your content type, they will see the items that you’ve registered.

Your items in the Translation Dashboard
Your items in the Translation Dashboard

Then, translators see each of the objects you’ve registered with the fields that they include.

Adding a Language and Translation Control Box to Your GUI

WPML automatically adds translation controls to standard WordPress content (posts, pages, taxonomy, menus, etc.). You can manually add similar language controls to your custom GUI. With these controls, users can choose the language of elements they are editing and translate to other languages.

The wpml_show_package_language_ui filter lets you easily display the language information box to your admin screens.

Here is an example taken from our Layouts plugin:

$package = array(
        'kind' => 'Layout',
        'name' => 'contact-us');

do_action('wpml_show_package_language_ui', $package);

This code produces the language configuration box at the bottom of our Layouts editor.

Translation controls, added by wpml_show_package_language_ui
Translation controls, added by wpml_show_package_language_ui

Since you’ve provided the context of the box, WPML knows for what object it’s used and will display the correct language information and translation controls.

Deleting a Package

When you delete a Layout, you also need to delete the packages bound to it; as well as all strings, string translations and jobs related to them.

To do so, you should hook to the most appropriate action (for Layouts and anything that use custom post types it’s ‘before_delete_post’) and execute the ‘wpml_delete_package’ action.

This action expects two arguments in this order:

  • $name: the unique name of the package
  • $kind:  the package kind

This is an example of how it can be implemented in Layouts:

add_action( 'before_delete_post', 'my_deleted_post' );
function my_deleted_post( $post_id ) {
    $is_a_layout_delete_action = isset( $_POST[ 'action' ] ) && $_POST[ 'action' ] == 'delete_layout_record';
    $layout_ids_to_delete = isset( $_POST[ 'layout_id' ] ) ? (array)$_POST[ 'layout_id' ] : array();

    if ( $is_a_layout_delete_action && in_array($post_id, $layout_ids_to_delete) ) {
        $package_name = $post_id;
        $package_kind = 'layout';
        do_action( 'wpml_delete_package', $package_name, $package_kind );


The String Package Translation is part of String Translation, starting from WPML 3.2.