How to localize WordPress themes and plugins with GetText

If your blog is run in a number of languages, the theme and texts in plugins should be localized, as well as the post contents. We’ll show you how to do this with the GetText package.

GetText and WordPress

GetText is a a text translation utility. It’s free and comes built on any web server. WordPress makes comprehensive use of it and all WordPress localization is based on GetText.

There are a few steps to localization with GetText:

  • Wrap each text in a GetText call
  • Create a list of texts
  • Translate that list to different languages
  • Tell WordPress to use the translation

Once these are done, the same page can be displayed in different languages. The PHP code will display the strings in the selected language, while the formating of the page remains the same.

A single PHP file can now render contents if multiple language, without any need to edit the code. And, when you want to support new languages, you just add a new string translation file.

Wrapping strings in GetText calls

Any text that would appear on the page needs to be translated. There are two kinds of strings you need to look out for:

  1. Strings in HTML text. For example <h3>Leave a Reply</h3>
  2. Strings in PHP code: For example: <?php comments_number(‘No Responses’, ‘One Response’, ‘% Responses’ );?>

Any string that isn’t inside a PHP call will have to change. Just wrap it as:

<h3><?php _e('Leave a Reply',my_theme_name); ?></h3>

What this does is just tell PHP to display this string. We’ve wrapped it in the GetText echo call _e(), so GetText will be able to return the translation for this string.

If the string already appears inside PHP code, we’ll just wrap it in the GetText call:

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

Notice, that here we used a different GetText call (__). This one returns the same translation, but doesn’t echo the output.

Text domains

Have you noticed the 2nd argument in the GetText calls? It’s an optional argument that tells GetText what the scope (domain) of the texts is. If supplied, this GetText will return the translations only from the dictionary that you supply with that domain name. Although optional, specifying the translation domain is highly recommended. Without it, GetText might return a different translation, if the same string also appears in a different plugin, or in WordPress.

Creating a list of texts to be translated

Once all texts have been wrapped in GetText calls, it’s time to compile them into a list, which will be translated. You will need to create a .po (Portable Object) file. This is a text file which contains all the strings to translate, along with comments. Once this file is translated, it will also include the translation.
GNU GetText package comes with a utility that extracts strings from source files. Unfortunately, this tool was not built especially for PHP. It is limited in the type of inputs it can process and does not support many things that are typically used in PHP.

As a result, many programmers and theme designers resort to compiling .po files manually. You can use a free online PHP to .po extractor. This tool will parse a single PHP file, or multiple files inside a ZIP archive and will create a .po file from them.

When you’re updating the translation (new version of the theme or plugin), you can supply the old .po file with exiting translations. The utility will then maintain all translations for unmodified texts.

Translating the strings with Poedit

To translate .po files, you can use the free Poedit program. It’s free and is available for Windows, Mac and Linux. Poedit is a simple, but powerful program. One of its nicest features is that it lets the translators (and you) see the context of the strings to translate.

Steps to translate a .po file

  1. Create a copy of the .po file per language. Use the locale’s name. For example, to translate to Swiss German (German, as spoken in Switzerland), name it de_CH.po.
  2. Send that .po file to your translator. Optionally, you can also send the ZIP file that contains your theme or plugin, so that the translator can see where the strings are used.
  3. When you get back the .po files, use Poedit to create the corresponding .mo files.

The .po file is all that the translator needs to have in order to translate. If you also include the source files, from which the strings were extracted, the translator will be able to better understand where these strings are used in the website.

For example, if your theme name is ‘solar_attack’, and you create a ZIP file called solar_attack.zip, send that to the translator along with the .po file. The translator will extract that ZIP in the same folder where the .po file is.

Then, when translators edit the .po file (in Poedit), they’ll be able to click on ‘reference’, for each string and see the location in the PHP files where it appears.

When Poedit saves the .po file, it automatically generates a .mo (Machine Object) file. This file has the same contents as the .po file, but is designed to be read by a computer. This is the file that needs to be included in the theme or plugin directory in order for GetText to provide the translated strings.

Tell WordPress to use the translation

After you’ve placed the .mo files in the theme or plugin directory, you need to tell WordPress to use this translation. For themes, include the statement:

<?php load_theme_textdomain(my_theme_name);?>

This statement should appear for any page in the website, so you can just place it in the header.php file.

For plugins, you can include the following function:

$my_translator_domain   = MY_TEXT_DOMAIN;
$my_translator_is_setup = 0;
function fabfunc_setup(){
  global $my_translator_domain, $my_translator_is_setup;
  if($my_translator_is_setup) {
    return;
  }
  load_plugin_textdomain($my_translator_domain,
       PLUGINDIR.'/'.dirname(plugin_basename(__FILE__)),
       dirname(plugin_basename(__FILE__)));
}

What this function will do is load and set the translation domain for the plugin just once.

Resources

Share and Enjoy:
  • Digg
  • Facebook
  • Mixx
  • StumbleUpon
  • TwitThis
This page is also available in French