The purpose of this article is to provide a quick and easy to follow step-by-step guide to extracting text strings from a WordPress plugin for translation from the command line. Although this is documented in the codex: I18N for WordPress Developers and Translating WordPress, those articles are somewhat lengthy and the first time I was asked to internationalize a plugin it took me some time to find the actual steps to generate my POT file. The codex article might be better if you’re translating a plugin that you have listed on wordpress.org, but since the majority of my plugins are either custom for a client or myself, or listed in the WooCommerce shop, I have to do my translation on the command line.
Extracting Strings for Translation
Although I won’t delve deeply into all aspects of WordPress internationalization (i18n), it is important to note that it’s built on the excellent GNU gettext localization framework. The basic process for translating a plugin or theme is as follows:
- Code the plugin/theme using the translation functions
_e('message'), etc. Include a call to
load_plugin_textdomain()as I describe in my article Writing a Plugin That Can Be Localized by WPML.
- Extract all translatable strings into a POT file
- Provide the POT file to a translator who returns one or more PO files with the text translated
- Convert the PO file into an MO file
- Place the MO file into the directory within your plugin that you specify in your call to
load_plugin_textdomain(), ie “languages”
Step 1 – Coding
While coding a plugin or theme it’s always good practice to use the special (and odd looking) localization functions whenever displaying text, with the two most common being:
_e('message'). Some additional useful functions to know include
_x('message', 'context') which allows you to provide some context information for translators to provide them with additional comments needed to distinguish between the same word used in different contexts, for instance. Another one is
_n('message', 'plural', $number) which is used to retrieve the singular or plural form of a string, based on the amount
$number. There are a number of variations of these functions, as well as ones specialized for use with HTML attribute values for instance.
You should also use an appropriate text domain string based on your plugin name. If your plugin is called My-Plugin, your text domain might be ‘my-plugin’ for instance.
Step 2 – Extraction
If you have not already done so, start by exporting the WordPress translation tools:[bash]$ svn export http://i18n.svn.wordpress.org/tools/trunk/[/bash]
Update 2013.03.01: It looks like the current head (revision 21405) of the WordPress translation tools has a broken
makepot.php. When I tried to use it today the POT file it generated only contained strings from the main plugin file and none from the other plugin source files. The previous revision does not have this bug, so until the issue is fixed I’d recommend exporting the tools like so:
One of those scripts is
makepot.php which is used like the following:
/path/to/my/plugin/ is the path to the plugin you wish to localize and will generate a POT file named like:
my-plugin.pot. Rename it to match your text domain, and add the language suffix you want (or let your translator do this): ie
Step 3 – Translate POT to PO
Send your POT file to the translator, or translate it yourself if you have the knowledge. If you need to edit the PO file you’ll probably want to do so with a tool with UTF-8 support, depending on your target language. I had good luck with Poedit for this.
Step 4 – Convert PO to MO
Convert your PO file to the MO required by gettext by using the
Step 5 – Using the MO File
Finally, drop your
my-plugin-de_DE.mo into the directory within your plugin specified by your call to
load_plugin_textdomain(). So for instance, if you use the following:
load_plugin_textdomain( 'my-plugin', false, dirname( plugin_basename( __FILE__ ) ) . '/languages' );
.mo file would go in
Once you put your
mo translation file into the plugin directory that you supplied in your call to
load_plugin_textdomain() (as described in Step 5 above), you can test that your language file is being picked up by editing your sites
wp-config.php. There you should find a line like:
Just change this to the language abbreviation, for instance:
And visit your site to verify the translation is being picked up.
One possible stumbling point for developers: your translation files may not be picked up if you symlink your plugin into your webroot as I do.
Working with WPML, so that the site language isn’t hardcoded in your
wp-config.php file and can for instance be selected by your site visitors, is a simple matter of making the
load_plugin_textdomain() call in the correct place. See my related article Writing a Plugin That Can Be Localized by WPML for details.
Updating Your Translation
If you change text in your plugin and want to update your translation without re-translating everything, Poedit makes this a snap. Simply:
- Follow the steps above to generate a new POT file with the current strings
- Open your out of date PO file with Poedit
- Go to Catalog > Update from POT file… and choose your new POT file
- Poedit will show you the obsolete and new strings. You can choose to delete the obsolete strings, or leave them (they’ll be commented-out in your new PO file) and translate the new strings.
- Save to generate the new PO/MO files
For a tip on supporting WPML see my article on Writing a Plugin That Can Be Localized by WPML.
If you create new database tables for your plugin, ensure that the default charset is UTF8, otherwise accented and other special characters that get inserted into them will not render properly:
CREATE TABLE blah ( ... ) ENGINE=InnoDB DEFAULT CHARSET=utf8;