Getting started

Five steps to ensure that your theme is compatible

Step 1: All strings are available for translation

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

Step 2: 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: All multilingual-needed custom post types, custom taxonomies, custom fields, admin texts are translatable

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

Step 4: Special features are translatable

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

Step 5: Tested 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, 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 so GetText will be able to return the translation for the string.

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 choice.

How to make strings from theme settings translatable

Text strings that the user inputs 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 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 a custom SQL queries to get the slides 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 filter 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.

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 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

Need help?

String Translation Support

Language configuration file support topics

Help on using icl_register_string and icl_t functions