Skip Navigation
Updated
March 24, 2023

This guide provides you with all the information you need to make your WordPress theme WPML-ready.

Getting Started

Five Steps to Ensure that Your Theme is Compatible

Step 1: Make sure all strings are available for translation

This allows you to find every single string and translate it with the String Translation plugin or the .mo language files. You can use the WPML Multilingual Compatibility Testing Tool, which helps identify good theme strings that are ready for translation. It marks them by adding a prefix tag in front of the text. If any strings are still showing their original text, it means they were not recognized as translatable and need some fixing in your PHP theme file.

Step 2: Make sure all translated strings appear on front-end

Translations of all strings must appear on the site’s front-end. If they do not, you will want to troubleshoot String Translation.

Step 3: Confirm that all custom post types, custom taxonomies, custom fields, and admin texts are translatable

WPML can read a configuration file that tells it what needs to be translated. The file is named wpml-config.xml and it’s placed in the root folder of the plugin or theme. You should add custom post types and custom taxonomies that need translation there. You can read more about this in the language configuration files tutorial.

Step 4: Confirm that special features are translatable

Any special features such as sliders, widgets, galleries, etc. should be available for translation.

Step 5: Test the theme in different languages

The main goal is to make it work fine in different languages, including RTL languages.

Making Themes Compatible

How to make template strings translatable

Any texts that are hard-coded in PHP and not wrapped in gettext calls with a textdomain function will not be translated by WPML. If it’s a simple hard-coded string, you can translate it by wrapping the string in the gettext call.

When translations of template strings don’t appear on the front-end

This problem may come about if your gettext calls are missing the text domain. The text domain is a unique identifier, which makes sure WordPress can distinguish between all loaded translations. Using the text domain is always a good idea.

How to make strings from theme settings translatable

Text strings that are input by users in theme options need to be registered using a language configuration file. We have a thorough tutorial about language configuration files that you will want to have a look at.

How to make theme features translatable

Custom post types, custom taxonomies and custom fields can all be made translatable. You can achieve this by adding them to a language configuration file.

How to make theme sliders or any other custom features play nice in different languages

Use WordPress API functions that accept filters. Avoid using custom SQL queries to get the slide IDs from the database.

Troubleshooting two common issues

  1. The Slider is blank or it displays the default language slides regardless of the current language.
    Check to see whether your code hardcodes the slider post IDs. If it uses set IDs, then you will want to have a look at the Language dependent IDs tutorial.
  2. The Slider displays all slides regardless of language.
    Check to see whether your code really uses a query method that applies filters. For example get_posts would not be a good query method to use, since is suppresses filters by default.

Frequently Used WPML API Hooks

wpml_register_single_string – This hook will register a string for translation. It’s useful when you need to register a dynamic string that comes from the database.

wpml_translate_single_string – This hook will return the translation of the string if it exists.

wpml_object_id – This hook will return the ID of the translated post type (page, post, attachment, custom) or taxonomy term (category, post tag, custom).

wpml_post_language_details – This hook will return the post language information.

Browse through all the WPML hooks.

Common Problems – Solutions in Practice

Issue: Form labels can’t be translated because they are coming from the database

Solution:

$label = esc_html( apply_filters('wpml_translate_single_string', $this->checkout_item->name, 'wpsc', '$this->checkout_item->name .'_checkout_form_label'' ) );

Issue: wp_query($args) or get_posts($args) doesn’t filter out correct posts IDs for the current language

Solution:
If you use wp_query($args) or get_posts($args) you need to add “suppress_filters=0” to arguments.

Issue: All slides are shown in one language

Solution:

// Unset not translated slides
foreach( $slides as $k => $slide ) {
	$check = apply_filters( 'wpml_post_language_details', NULL, $slide->ID )
	$slide_language_code = substr( $check['locale'], 0, 2 );

	if( $check['different_language'] ) {
		unset( $slides[$k] );
	}
}

Issue: Slide ID is different in a second language

Solution:

// Loop posts
while (have_posts()): the_post();
$post = get_post( apply_filters( 'wpml_object_id', $post->ID, 'slide' ) );

Issue: Slider is using a custom admin page and we need to register custom fields values to translations

Solution:

// Adding a new slide code
$slide_id = $this->slide->ID;
$url = $fields['url'];

// Register slide URL to translations
do_action( 'wpml_register_single_string', 'Slider', 'Slide_ID_' . $this->slide->ID, $url);

$this->add_or_update_or_delete_meta($this->slide->ID, 'url', $url);

Issue: A custom taxonomy ID is different in a second language

Solution:

$taxonomy_id = apply_filters( 'wpml_object_id', $taxonomy_id, 'my_custom_taxonomy' );

Issue: Custom (non-standard WordPress) AJAX requests always return the default language content.

Solution:

When building custom AJAX URLs, use the wpml_current_language hook and add the current language as a parameter for the AJAX URLs.

$ajax_url = 'http://my-site.com/wp-content/plugins/my-plugin/handle-ajax.php';
$my_current_lang = apply_filters( 'wpml_current_language', NULL ); 
if ( $my_current_lang ) {
	$ajax_url = add_query_arg( 'wpml_lang', $my_current_lang, $ajax_url );
	// $ajax_url will be something like 'http://my-site.com/wp-content/plugins/my-plugin/handle-ajax.php?wpml_lang=es'
}

When handling AJAX requests at the handle-ajax.php file, before generating the content output, use the wpml_switch_language hook to switch the content language.

if ( isset( $_GET[ 'wpml_lang' ] ) ) {
    do_action( 'wpml_switch_language',  $_GET[ 'wpml_lang' ] ); // switch the content language
}

// Run other content queries. 

Issue: Usage of the wrong “id” value for the WP_Query $args[ ‘tax_query’ ][ ‘field’ ] argument(s)

Using the “id” argument for the “field” parameter works for the default language but it does not work for the second language. The following is an example of an incorrect query:

$args = array(
    'post_type' => 'post',
    'tax_query' => array(
        array(
            'taxonomy' => 'people',
            'field'    => 'id',
            'terms'    => 'bob',
        ),
    ),
);
$query = new WP_Query( $args );

Solution:

Developers should correct the “field” parameter.

'field'    => 'id',

to:

'field'    => 'term_id',

Reference: https://codex.wordpress.org/Class_Reference/WP_Query#Taxonomy_Parameters. There is no value “id” for the “field” parameter. Its default value is “term_id”.

Getting Help

  • Please search our support forum before contacting us. Many of our most frequently asked questions about compatibility issues are already answered there and you will be able to find your answer in minutes.
  • For technical questions, please use our support forum.