In My Language, Please! – Translating WordPress Themes and Plugins

Ivaylo Gerchev
Tweet

WordPress-powered sites are visited by millions of people all over the world. For many of them, English is not their native language, which makes using these sites harder. Fortunately this issue can easily be solved by offering users a translation.

WordPress itself is translated to many languages and people can use it in their preferred language. But this is not the case with themes, plugins, and other front-end customizations. Every theme or plugin developer is responsible for adding translation support for his work. And although adding translation to a theme or plugin is not required and requires some extra work, in the long run it can be a big advantage. Having your theme or plugin translated is a win-win situation in which both sides benefit. You benefit by having a larger audience of people using your theme or plugin, and users benefit by using the theme or plugin in their language.

The purpose of this article is to show you how to translate properly any theme or plugin by using internationalization and localization methods. In brief, internationalization (i18n) deals with making sure strings of text are wrapped in specific function calls. It is the practice of making text ready for localization, while the localization (L10n) itself is the process of translating text for a specific locale. WordPress handles the localization process by checking for specific translation files and then performing the translation. It certainly sounds easily, so let’s check it out.

Getting Started

The first thing you need to do is to decide where to store translations. Many themes and plugins put translation files in their root directory. Although translations will work when using this method, it can get a bit messy, especially if you have translation files for more than one language. For the most organized system, it’s better to create a subdirectory in your theme or plugin folder called languages. When you release your theme or plugin, you can store your default translation files in this directory, and when translators send you translation files you simply drop those files in that directory.

The translation process consists of three steps. The first step in making your theme or plugin translatable is to use a special function which tells WordPress to load a translation file if it exists for the user’s language. For theme translations, you can put this function call in your theme’s functions.php file:

<?php
$domain = "myplugin";
$path = "myplugin/languages/";
load_theme_textdomain($domain, $path);

$domain is a unique string that identifies text in your theme that has been prepared for translation. For organizational purposes, you should give this the same value as the name of your theme directory. $path is the path to your translation files within the theme.

Here is another example, this one sampled from the functions.php file of WordPress’ default twentyeleven theme:

<?php
load_theme_textdomain( 'twentyeleven', TEMPLATEPATH.'/languages' );
  
$locale = get_locale();
$locale_file = TEMPLATEPATH."/languages/$locale.php";
if ( is_readable( $locale_file ) )
require_once( $locale_file );

Here, “twentyeleven” is the domain which matches the theme directory’s name. You can use whatever you want, but this is considered best practice. In the second parameter, the TEMPLATEPATH constant is used in order to get the theme’s root directory and then concatenate to it the “/languages” string to give the correct path to your files. The remaining code tells WordPress to get the translation file from the languages folder.

In case of a plugin, the function used is similar but takes three parameters:

<?php
load_plugin_textdomain($domain, $abs_rel_path, $plugin_rel_path);

$abs_rel_path is actually a deprecated parameter that should no longer be used, so just set this to false or null. $plugin_rel_path is the relative path to your translation file. You should put this in your plugin file, not functions.php:

<?php
add_action("init", "pluginname_init");

function pluginname_init() {
   load_plugin_textdomain("myplugin", false, "myplugin/languages/");
}

Using the Localization Functions

Next you’ll need to define which text strings will be translated. This is done by wrapping your textual content with functions that identifies the type of localization you want. A lot of localization functions are available, but in fact there are only two which you’ll use most of the time.

The first function makes your text ready for translation and returns it for use in PHP. Here are two examples:

<?php
$text = "Hello World!";
$domain = "myplugin";
__($text, $domain); // begins with double underscore
<?php
edit_post_link(__("Edit", "twentyeleven"), '<span class="edit-link">', "</span>");

The __() Function takes a text string as a parameter, and looks for a translated version of $text within a provided translation file and returns the result, if any. It is used for controlling the display of text already contained within PHP tags. If no localization files other than English exist, then the text will remain the same. The value of $domain variable enables WordPress to recognize it as a part of your theme’s or plugin’s translation files.

The second function you’ll use makes your text ready for translation and prints it out directly to the browser. It takes the same parameters as you just saw:

<?php
_e($text, $domain);

_e() function looks for a translated version of $text and echoes the result to the screen. This should be used for titles and headings that will display on the screen and are not already contained within PHP tags.

In some instances you’ll want to use placeholders to insert dynamic information into a text string at runtime. Placeholders are useful because they enable you to translate strings without breaking them apart. The translation functions in WordPress cannot output placeholders on their own, though, so you’ll need to use an appropriate PHP function such as printf() or sprintf().

<?php
printf(__("About %s", "twentyeleven"), get_the_author());

Here, get_the_author() function returns the author which replaces the placeholder by printf().

Sometimes you need multiple placeholders in one text string. Luckily, both printf() and sprintf() handle this wonderfully. It’s best to use numbered placeholders because the order of words in one language may be different in another.

<?php
$site_name = get_bloginfo("name");
$comments_count = wp_count_comments();
$mod_comments = $comments_count->moderated
$appr_comments = $comments_count->approved
$all_comments = $comments_count->total_comments

printf(__('There are %3$s comments on %4$s. %2$s approved and %1$s in moderation.', $domain), $mod_comments, $appr_comments, $all_comments, $site_name);

Creating Translations Files

Now with your theme or plugin files correctly internationalized, you need to create translations files which WordPress will use to lookup the translation.

The first file you need to create is a POT (Portable Object Template) file. A POT file lists all of the translatable text strings that can be found in your application and serves as a template for individual PO files. The PO (Portable Object) file is the file that maps the text strings to the actual translation. Translators work with this file to provide a translation. The POT and PO files aren’t necessary to run a translation of your plugin, but it’s nice to package it with your plugin download for use by other users that may want to update the translations to suit their needs. Finally, the PO file is compiled into a MO (Machine Object) file which is the finished translation file which WordPress uses to translate internationalized text strings for your theme or plugin.

When translators create translations of your theme or plugin they use your POT file to create two files, $locale.po and $locale.mo for a theme, and pluginname-$locale.po and pluginname-$locale.mo for a plugin. $locale here represents a combination of both a language and a country code specified by the GNU gettext framework—you can see the language and country abbreviations in the gettext manual. For example, WordPress uses “en_US” as its default locale. “en” represents English, and US represents the country/dialect.

A variety of translation tools are available which are open source and free to download. However one of the most common tools is Poedit which is simple and easy to use. Here are the steps to create a POT file using Poedit:

Choose File > New Catalog. A Settings box appears with three tabs. In the Project info tab, fill in the input boxes that are relevant to your plugin, leaving the Charset box as UTF-8.

In the Paths tab, change the Base Path to ../ and add an extra path of . if you’re placing your translations in the languages folder of your plugin. If not, then leave this at the default.

In the Keywords tab, enter the functions you’ve learned above as keywords.

Click OK and save your file as themename.po or pluginname.po in your languages directory. Poedit will scan your PHP files searching for __() and _e() wrapped strings, and automatically output them in a dialog window.

Click OK. Now you will see a window with your strings.

Save the file again and close it. In your languages directory you will now see the PO and MO files generated by Poedit. Delete the MO file and rename the PO file with the .pot extension. That’s it. Now your theme or plugin is ready for translation.

If you have the required skills you can go further and make the actually translation of your files. To do, Choose File > New catalog from POT file. Locate the POT file, open it, and then click OK to the subsequent catalog settings (they are the exact same ones you set yourself). Poedit will ask you what you’d like to save your new PO file as – give it an appropriate name, for example es_ES.po or pluginname-es_ES.po and save it in the languages directory.

Now just click on the string you’d like to translate in Poedit, and type a translation into the box on the bottom of the Poedit window.

The last thing you need to do in order to see your theme or plugin translated is to set your locale in the wp-config.php file. This tells WordPress to look for any translations with that locale and load them. If you set your locale to es_ES (Spanish), WordPress would load a file called es_ES.mo a theme, or pluginname-es_ES.mo for a plugin.

<?php
define('WPLANG', ''); // this is default for a fresh WordPress installation
define('WPLANG', 'es_ES') // set the second parameter to your locale

Summary

As you can see the translation of WordPress themes and plugins is a pretty straightforward process. There is no need to be a PHP guru; it’s just a matter of following several simple steps in a logical sequence. And now when you have good understanding of these steps, I hope that you will apply this knowledge in your existing or future theme or plugin projects, thus giving WordPress users the ability to use their favorite publishing platform in a language which is natural for them.

Image via iQoncept / Shutterstock

Free book: Jump Start HTML5 Basics

Grab a free copy of one our latest ebooks! Packed with hints and tips on HTML5's most powerful new features.

  • http://jkudish.com Joachim Kudish

    The domain should not be set with a variable, it should always be a string, see: http://ottopress.com/2012/internationalization-youre-probably-doing-it-wrong/

  • http://goldhat.ca Joel Milne

    Useful guide here on translating WordPress. I’ve done translations in Drupal before and found the support pretty good because core modules are included that help in the process. Translating a site is still always a big project on most sites, so much to do, not just the programming but getting all the text organized!

  • Selena Henn

    You can also use this online tool to easily translate WordPress themes – https://poeditor.com/ There’s even a plug-in you can download to speed up the file management process, which integrates the POEditor API to your WordPress account – http://wordpress.org/extend/plugins/poeditor/ I highly recommend it.