Skip Navigation
Originally written
May 2, 2018
Updated
January 11, 2021

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 or plugin you created into a multilingual one.

The entire process for theme and plugin 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 or plugin.

Why localization is important

Although it involves multiple steps, creating multilingual themes and plugins is really simple. It is also a good practice and a smart idea to create all your themes and plugins 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 or plugin value increases, not only if it is already translated to several languages, but also if it includes a POT file. This makes 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 and plugins, so it is just a little one-time investment which you can reuse later over and over.

Making the theme and plugin texts translatable

Usually, WordPress themes and plugins 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 or plugin strings

Once all the texts in your theme or plugin are wrapped with GetText calls, it’s time to collect them into a single file, which we will translate later. You can generate PO files in just a few clicks using WPML.

Translating your theme and plugin strings

Once 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 or plugin to.

If you are working with translators, you can just send them the PO files. Each translator will translate it and return it to you along with the corresponding MO (Machine Object) file. These are the files that WordPress uses to translate your theme or plugin. In our case, we have done the translations for all languages at once using our own translation service, ICanLocalize.

If you are translating your strings manually, you can use a program like Poedit to convert your translated PO files to MO files.

Adding translations to WordPress

Keep in mind that your MO files names are important. All of them go into your theme’s folder (/wp-content/languages/themes/) or plugin’s folder (/wp-content/languages/plugins/) 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 Translating WordPress 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 or plugin’s translations

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

Then, WordPress needs to load and associate them correctly with your theme or plugin’s Text Domain. In order to do so, you need to call them with a load_theme_textdomain or load_plugin_textdomain function in your theme or plugin’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 or plugin’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 or plugin, you need the following two sets of MO files:

  • Your theme/plugin’s MO files.
  • WordPress MO files.

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

In the past, you needed to manually install your WordPress MO files. Nowadays, this procedure is automatically done by WPML at the moment of configuring your languages.