WordPress Development Stack Exchange is a question and answer site for WordPress developers and administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

What is the best way create a plugin that is translation ready?

It doesn't have to be translated from the beginning but it has to be easily translatable so fellow developers from different cultures can participate to the localization process of the plugin.

share|improve this question
Another simple tutorial - wordpress.stackexchange.com/questions/92560/… there you will see the instructions. It is a simple tutorial and you will be able to do your worn translation. – guests Mar 27 '13 at 18:23
up vote 26 down vote accepted

1. Write with localization in mind

Don't use echo or print() to produce text output, instead use the WordPress functions __() and _e():

/** Not localization friendly */
echo "Welcome to my plugin";    
// OR
print("Welcome to my plugin");

/** Localization friendly */
_e('Welcome to my plugin', 'my-plugin');
// OR
$my_text = __('Welcome to my plugin', 'my-plugin');
echo $my_text;

_e() and __() will provide the translation — in the current language — of the text provided as the first parameter. _e() will output the text whereas __() will return it.

The second parameter is the text domain, you will be using it to tell WordPress that the text provided as the first parameter belongs to this plugin, you can use any name you want but I prefer to use the same name as I used for the plugin file of directory, I find it more intuitive.

How to output dynamic text like: "Hello <username>"?

With __() and sprintf():

/** Get the username */
$username = 'Magictrick';

/** Not localization friendly */
echo "Hello $username";     

/** Localization friendly */
printf(__('Hello %s', 'my-plugin'), $username);
// OR 
$my_text = sprintf(__('Hello %s', 'my-plugin'), $username);
echo $my_text;

2. Prepare the .pot/.po/.mo files


  • The .pot file: is put at your disposal by the plugin developer and it's used as a starting point to create new translations, WordPress doesn't use it.
  • A .po file: is a translation file you or someone else started, and maybe completed, WordPress doesn't use it.
  • A.mo file: is automatically created by Poedit whenever you save a .po file, all you can do with these files is to upload or re-upload them whenever you create or update a .po file. WordPress gets translations from .mo files.

Open Poedit and create a new catalog (File › New Catallog...) with these settings:

  • Project info: Use your (or your team) information, the language and country should match your plugin default language
  • Paths:
    • Base path: .
    • Paths : remove all & add .., (we will store language file in a plugin subdirectory called languages)
  • Keywords : remove all & add __ and _e

Save the catalog as /my_wordpress_blog/wp-content/plugins/my-plugin/languages/my-plugin.pot and scan your plugin files for translatable text by pressing the update button. When the update is finished close that catalog, you won't need to update that file unless you add new translatable strings (i.e enclosed in __() or _e()) to your plugin.

Now let's create the first translation (I will use fr_FR):

Using Podeit, create a catalog from a POT file (File › New catalog from POT file...):

  • Project info: Use your (or your team) information, change the language and country, I will use French and France
  • Paths:Don't change
  • Keywords : Don't chage

Save the catalog as /my_wordpress_blog/wp-content/plugins/my-plugin/languages/my-plugin-fr_FR.po. Translate some or all the of the strings, save the .po file again, upload both the .po and .mo files.

Note that whenever you save a .po file a .mo file is generated with the same name, the filename of the .po file is crucial, it's composed of the concatenation of the plugin text domain (my-plugin) and the language locale (fr_FR), always name your .po files for plugins like this: [textdomain]-[locale].po, here are some examples:

  • Italian/Italy: wpcf7-it_IT.po
  • Portuguese/Brazil: wpcf7-pt_BR.po
  • Arabic: wpcf7-ar.po... Yes!

Whenever the plugin is updated with new text, update the po file, translate new strings and reupload the .po and .mo files

3. Instruct the plugin to load translated text for the current language

Somewhere in your plugin, you must tell WordPress to use your .mo file, you can do it by using this code in the beginning of your plugin file:

function my_plugin_init() {
  load_plugin_textdomain( 'my-plugin', false, 'my-plugin/languages' );
add_action('init', 'my_plugin_init');

Replace my-plugin with your plugin name in the 1st and 3rd parameter of the load_plugin_textdomain function.

4. Test and troubleshoot

Some reasons it may not work:

  • Strings are not imported into the .pot or .po file
    • → Wrong catalog settings (path or keywords or both)
  • Text is not translated on the WordPress site
    • → .mo file for that language missing or has a wrong file name
    • → Text domain not used (replace _e('my text') with _e('my text', 'my-plugin'))
    • → Text domain not loaded (use example above with the right parameters, WP will not warn you about mistakes)
share|improve this answer
+1 Nice write-up :) Take a look at this article: Loading WordPress language files the right way, "Practical guidelines for taking the pain out of loading language files in WordPress". :::::: Glotpress and the Polyglots group may be worth mentioning too. – brasofilo Jan 13 '13 at 0:27
Thank for for this nice instruction! It's worth mentioning that load_plugin_textdomain() needs to be called in every method, where you use _e() and __() – Andreas May 8 '13 at 5:40
Sir, thank you so much for your help. – jepser Jul 12 '13 at 19:05

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.