Internationalization, or “i18n” for short, is a way of allowing display strings to be changed depending on the language setting of the system. In WP, in the wp-config.php file, you will see something like:

define ('WPLANG', '');

Which indicates WP is running in the default language (English). If you change this setting to the following, then you would have WP set for Italian.

#define ('WPLANG', 'it_IT');

In this case, “it” is the Italian language, for “IT” which means Italy. That seems redundant, but it allows you to specify the same language but different varients associated with different countries. Portuguese from Portugal (pt_PT) is bit different from Portuguese from Brazil (pt_BR) for example.

In your WP plugin, you indicate which string are to be “internationalized” (see below). Then you just write your strings in English by convention. You don’t do any translation. What you do is automatically generate a create a file (.pot) that other users can use as a reference to create a translation files (.po & .mo) for a specific language/country (see below). All these files go in your plugin’s languages/ sub-directory.

Once the translation files are in the languages directory of a plugin where it is installed, and that matches the WPLANG setting, then all i18n strings in your plugin will automatically be replaced with what is in the translation file.

If the translator gives those files to you (the plugin writer), you can then include those files in your plugin so that everyone’s installation will have that translation available.

Read more at Translating WordPress.

How to I18n Strings in WP

To make a string be i18n, you simply wrap it in the WP double-underscore function “__” and you need a Text Domain configured.

$i18nTrue = __('true', 'my-text-domain');

If you plan to echo the string, you can use the “_e” function:

// This echos a translated string
echo  __('true', 'my-text-domain');
// This does the same thing
_e('true', 'my-text-domain');

You should also be aware of how to handle i18n in display string for plugin options. See Handling Options.

Setting Up a Text Domain

The template coded sets up a text domain for you automatically. You just need to know what it is.

By default in the template code, it is the same as the name of your plugin directory. Something like “my-awesome-plugin”. It is officially defined in your main plugin file, also named the same as the directory + .php (like “my-awesome-plugin.php”). At the top of that file is a comment section with metadata that WP reads. The Text Domain line is there

   Text Domain: my-awesome-plugin

This should already be set up for you. In addition there is some code in the your XXX_main.php file that initialization your text domain. Have a look if you are curious.

The point of the Text Domain is to have a unique label so that when WP goes to i18n a string, it knows what translations files to use. The translation files in your plugin’s languages/ sub-directory get associated with your Text Domain label.

Creating a POT File

Once you have diligently use the “__” and “_e” function to i18n all your display strings, then all you have to do is generate a POT file and include it in your languages sub-directory.

Assuming you have your plugin registered on (see Registering Your Plugin on all you need to do is go to the Administration tab of your plugin’s page on and it gives you a button to generate a POT file from the code you have checked into SVN. The POT file name will be the same as your text domain + .pot (like “my-awesome-plugin.pot”).

Generating a POT file is something to do just before a release. There are more details about generating a POT at Version and Releases.

Creating and Sharing Translation Files

In case you want to create translation files yourself, you use the Poedit application to open the POT file. You enter in a translation for each string and save a .po (text) file and a .mo (binary) file. You need to append the language and country abbreviations to the file (same as what would appear in WPLANG).

For example, if you have a “my-awesome-plugin.pot” file and you wanted to translate to Brazilian Portuguese, you would name your files:

  • my-awesome-plugin-pt_BR.po
All three files go into the languages/ sub-directory.

Sneaking Translation Files into Your Version

If a translator shares his translation files with you, you will want to include them in the released version of your software. You can create a new release (new version) with the files included. See  Version and Releases.

But sometimes this seems like something you just want to slip into the current version. You can add the file to the SVN trunk code and to the copy of the code under the current release tag. Anyone who installs/updates to that version after you slipped in the translation files will get them. Those who did it before will not. You can decide for yourself if you think this is an OK practice.


  2 Responses to “Internationalization”

  1. Hi Michael,

    thanks a lot for this great work.
    I believe I found an issue in the registration of the plugin.

    It should be:

    But for some reason, the template of the plugin reports

    and this makes the language files to not be loaded properly

    • Hi Gerardo,
      I just had the same issue and found this hint – and I can confirm your remarks,
      problem soved 🙂

      apart from that, this project is a BIG help for new WP Plugin developers,
      thanks alot, Michael !

 Leave a Reply

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>