WordPress Internationalization Part One – General Overview and Text Domains

InternationalizationDo you feel like you don’t need to provide translation in your plugin or are you a proud merican that feels everything should be in English?   I was right there with you for a long time not because I think everyone should speak English, but I didn’t see the need and I didn’t take the time to learn the proper methods to allow my plugins to be translated.

I don’t think this way anymore and what change was my increase need to understand WordPress and to be a part of a WordPress community that is truly global.  And if you are going to release your plugin on the WordPress Plugin Repository or even sell it, the plugin should Internationalized or be ready for translation.

Internationalization VS Localization

We need to know the general terms for translation in plugins.  First there is internationalization, which is the process of making your plugin ready for translation.  This is the main purpose of this post.  Localization is the process of translating a plugin already internationalized.

Also the common for these terms are I18N for internationalization where the 18 represents the number of letters between the “I” and “N” in the word internationalization.  Localization follows the same idea becoming L10N.

How Does WordPress Handle Translation

WordPress actually doesn’t do translation.  Translation files are loaded by WordPress and then there are a set of PHP functions that takes the strings ready for translation and replaces them with the translated strings.  Here is a general overview of how your code could be translated.

This begins with developers making their code translation ready by using WordPress translation functions.  The code is then parsed using different tools to create a Portable Translate Template (POT file).  This contains all the strings needing translation.

Next, the POT file is feed to a translation service such as Glotpress.  This is a whole community of people providing translation.  When your code is translated this then creates a Portable Object (PO file).  This is a set of strings and their completed translation.

Lastly, the PO file is then used to create a Machine Object (MO file).  This is a computer ready form of the POT file.  It is easy and quick for a computer to read.  This is used in the next step loading the text domain.

Text Domains Are the Key

Your plugin needs to some how signify the its strings ready for translation and this is done by the use of a text domain.  This is a unique string that denotes the string belongs to this plugin.  The string should not contain special characters except for underscores and dashes.  This is typically the name of the plugin or an abbreviation of the plugin.  Keep that in mind because the text domain will be typed everywhere where you use a translation function.

For example if you are creating a plugin named WP calendar your text domain could be WP-calendar, simple and it is easy to go through code and figure out what text is related to what plugin.

Properly Loading Text Domains

Loading text domains is  simple if you know the rules.  First you need to provide the text domain in the header of your plugin.  This is used by WordPress even if your plugin is not loaded.  Here is an example of loading in the plugin header:

The next step is to load the text domain in our plugin.

There are three pieces of information WordPress needs to properly load the text domain. First is the string you signify as the text doamin. Second, is the path to the folder containing the translation files, which is usually a folder in the plugin base directory called “languages”. Lastly is the locale constant set in the wp-config.php of the WordPress install. You can find this under the WP_LANG constant. And for purpose of this example we will use Brazilian Portuguese as the language. It would in the config file as:

The text domain and WP_LANG are combine using a naming convention to load the MO files providing the translation. For example, the translation file loaded would be wp-calander-pt_BR.mo and wp-calander-pt_BR.po.

To now load the file we need to use the following function:

The $domain is the text domain string covered above. $deprecated is set to false and is not needed. $plugin_rel_path is the path to the directory containing the MO files.

To properly call this function we need to wrap in a user defined function that will call using an action hook when plugins are loaded. For example:

Common Mistakes When Loading Text Domains

Don’t use a variable to store your text domain

This was a mistake I made for the longest time because I didn’t understand how WordPress actually handles translation. The reasoning you might make is that you need to type this every time your plugin has a string that needs to be translated and storing the value in a variable makes sense. But as we learned earlier translation of the plugin begins with the parsing of the code to pull out all the strings that need to be translated. This means the code will not be executed and there is no way for the parser to figure out what strings needs to included in the PO file. You have essentially hidden the text domain in a variable.

Don’t load the text domain in your singleton plugin constructor function

This was another mistake I have made. I like creating plugins using the singleton design pattern, by calling load text domain in your constructor function your are loading the domain before any other theme or plugin. This can lead to potential conflicts which can be avoided if you load using the init or plugins loaded hook.  And then having a method within your class that is dedicated to loading the text domain.