In order to run multilingual WordPress sites, all your content as well as your themes and plugin strings, need to be localized. This page explains how to turn the theme you created into a multilingual one.

The entire process for theme localization includes:

  1. Identifying and marking texts that need to be translated.
  2. Collecting all the texts for translation.
  3. Translating the texts.
  4. Adding your translation to your theme.

Why theme localization is important

Although it involves multiple steps, creating multilingual themes is really simple. It is also a good practice and a smart idea to create all your themes as translation-ready.  Not only it is a powerful feature to advertise, but it is a real time saver for your clients and a way to reach a bigger market. They will deeply appreciate it when they start translating their site’s contents.

You will also see how your premium theme value increases, not only if it is already translated to several languages, but also if it includes a .pot file. It would make it easier for your users to translate it to other languages and even share those .mo files with you.

Furthermore, most of the texts are shared between different themes, so it is just a little one-time investment which you can reuse later over and over.

Making the theme texts translatable

Usually, WordPress themes include some hardcoded texts. For example, let’s look at comments.php. The form for leaving new comments asks for the visitor’s name, email and website and includes a submit button.

Translation plus echo

Here is a very simplified version of the field requesting the first name:

<input type="text" name="author" id="author" value="<?php echo $comment_author; ?>" />
Name <?php if ($req) echo ('(required)'); ?>

The strings “Name” and “required” need to be translated. We need to wrap those texts – which we will continue calling strings from now on – into GetText functions. In our example, we will use a GetText echo call: _e().

<input type="text" name="author" id="author" value="<?php echo $comment_author; ?>" />
<?php _e('Name', 'wpml_theme'); ?> <?php if ($req) _e('(required)', 'wpml_theme'); ?>

Can you see the difference?

Translation without echo

When you do not need to echo the string (for example, when it is the argument of a function), you should use the __() call. It is similar to _e(), but does not echo the translation. For example, in the comment number display, we use:

<?php comments_number('No Responses', 'One Response', '% Responses');?>

After using the GetText call:

<?php comments_number(__( 'No Responses', 'wpml_theme'), __('One Response', 'wpml_theme'), __('% Responses', 'wpml_theme'));?>

The second argument, wpml_theme, in both these calls is the Text domain. This allows texts to be translated in their correct context. If any plugin, or even WordPress itself, includes the same strings used in a different context, the GetText() function will still provide the correct translation, because we have provided our own text domain (wpml_theme).

Translation with parameters

Sometimes, texts have parameters. For instance, the text that says who wrote a post:

by <?php get_the_author(); ?>

We cannot translate the word “by” on its own. It needs some context so the translator understands that it is “by SOMEONE” (we will fill in who that is a bit later). For that, we use a parameter:

<?php printf( __('by %s', 'wpml_theme' ), get_the_author() ); ?>

Now, the translator can translate “by %s” as an entire phrase. We use the __() function to translate the string and the PHP printf() instruction to insert the name of the author back to the string.

Collecting all the theme strings

Once all the texts in your theme are wrapped with GetText calls, it’s time to collect them into a single file, which we will translate later.

Allow us to introduce Poedit. It is a program that can create and translate .po (Portable Object) files and turn them into .mo (Machine Object) files. These are the files which WordPress uses to translate your theme.

Poedit is able to scan many different types of files, including C, CPP, PHP and others. But, instead of using this tool, we will do something a bit different – and a lot of easier.

In order to localize our own theme, we have used our own PHP to .po file converter. It is an online tool which allows you to upload a ZIP file containing your theme. The converter will instantly create a .po file for you to download.

And that’s it, we have the needed .po file to start translating our own theme.

Translating your theme strings

Now that you have a .po (or .pot – Portable Object Template) file, it’s time to translate it. Each .po file includes strings and their translation to a single language. This means that you need as many .po files as the languages you are translating the theme to.

If you are working with translators, just send them the .po files. Each translator would translate it and return it to you. Otherwise you have to translate them.

In our case, we have done the translations for all languages at once using our own translation service.

Here is how it works:

  1. Create an account at ICanLocalize (that’s free).
  2. Create a new text resource project (still free).
  3. Upload the .po file and select which languages to translate to.
  4. The system counts the words in the file and asks for payment. Payment is calculated as 0.09 USD * words * languages. For instance, translating our own theme to both Spanish and German cost us $30 (together).
  5. Translators do the translation.
  6. You download all the translated .po files (one .po file per language), ready to be used by WordPress.

Adding translations to WordPress

Now that you have the translated .po files, you need to create the corresponding .mo file. For this, open each of your .po files with Poedit and click on Save. Poedit will create the .mo file for every .po project that you have.

Keep in mind that your .mo files names are important. All of them go into your theme’s folder (/wp-content/languages/themes/) and their names indicate which language they correspond to. You can choose any name you like, but we strongly suggest you to follow the standard locale naming convention of language_COUNTRY, where every term should have two letters.

For example, to provide the German (Germany) translation, you would name it de_DE.mo. For French from France, it would be fr_FR.mo.

For reference, you can see the locale names used by WordPress in the WordPress i18n project.

Remember that some of the translations need to be provided directly by WordPress, so keeping to the same naming is crucial.

Adding your theme’s translations

It is highly probable that your theme will be translated in several languages, that is why we recommend you to create a languages folder inside your theme and place all your .mo files there.

Then, WordPress needs to load and associate them correctly with your theme’s Text Domain. In order to do so, you need to call them with a load_theme_textdomain function in your theme’s functions.php file,  like the following:

add_action( 'after_setup_theme', 'my_theme_setup' );
function my_theme_setup(){
  load_theme_textdomain( 'wpml_theme', get_template_directory() . '/languages' );
}

Finally,make sure you have defined your Text domain in your theme’s style.css file. It is always a good practice:

Text Domain: wpml_theme

Where to place your WordPress translations

To fully translate your WordPress admin and your theme, you need the following two sets of .mo files:

  • Your theme’s .mo files.
  • WordPress .mo files.

Until now, all we have discussed was related to your theme’s .mo files and how you should place them in your theme folder. But what about your WordPress Dashboard?

In previous versions of WPML, you needed to manually install your WordPress .mo files. Nowadays, this procedure is automatically done by WPML at the moment of your languages configuration.