Introduction

You want to translate a WordPress plugin, but you don’t know how to do? You have come to the right place, this guide is here for you!

WordPress uses gettext as its translation system. You will often find a .po and a .mo file in WordPress plugins. What are those files? Basically, the translated strings are all contained in a .mo file which is a machine (binary) optimized version of  the corresponding .po file. This file is a text file containing pairs of string IDs and strings to be translated. We will explain how to produce those files.

This guide is composed of three chapters:

  1. Creating your translation
  2. Updating an existing translation
  3. FAQ

Ready ?

Translate an existing plugin

1 – Grabbing the sources

First you will have  to grab the latest plugin sources, usually at the WordPress plugin homepage. We will often take the example of our plugin Counterize. Go to http://wordpress.org/extend/plugins/counterize/ and click on the orange “Download” button to get it. Once you downloaded the file, just extract it in any directory. Let’s say you extracted it in “/home/yourname/web/counterize/“: this directory should now contain all the plugin source files. You can see that there are already some translations contributed by other people. If your locale is not included, then this is your chance to be part of the contributor list!

2 – Determining the “text domain” of the plugin

Each plugin to be translated must use a unique text domain. This is an identifier. It should not be too generic to avoid conflicts. There are good chances that the plugin author already defined a text domain for his plugin. Just look at the sources and search for the strings “__(” or “_e(“. For example you will find the following string in the Counterize plugin:

__('Keywords', 'counterize')
_e('Referers', 'counterize')
//String like these help you to find the text-domain

This shows that the text domain is “counterize”. Of course it will be different for each plugin.

3 – The .pot file

You will need a .pot file to begin your translation. The .pot file is a model that will be used later to create your own translation. If the plugin provides a .pot file in its source, then you can use it and go directly to the next part of this chapter. Otherwise, we explain how to get such a file below. There are two ways to create a .pot file:

A – Using the xgettext command-line tool

Most Linux distributions come with gettext installed. Among the files installed by the gettext package, you will find a command-line tool named “xgettext”. This little tool will let us generate a .pot file. So open a terminal and cd to the directory where you extracted the sources (such as /home/yourname/web/counterize/). Consider the following command line  I used for Counterize:

xgettext --default-domain=counterize --language=PHP --keyword=__ --keyword=_e --sort-by-file --copyright-holder="Hautclocq Gabriel" --package-name=counterize --package-version=3.0.18 --msgid-bugs-address="" *.php

This command grabs all the strings to be translated and save them in a file named “counterize.pot”.

I will now explain a little  what each part of the command line is:

xgettext is the tool itself

−−default-domain=counterize sets the text domain to “counterize”

−−language=PHP because the plugin is written in PHP

−−keyword=__ and −−keyword=_e define how to find the strings to be translated. Every string contained inside __(), _e() and gettext() blocks will be fetched.

−−sort-by-file will sort the strings to be translated by file when possible. Not mandatory.

−−copyright-holder=”Hautclocq Gabriel” defines the translation copyright holder to “Hautclocq Gabriel”. You must change it to your name.

−−package-name=counterize defines the package name (the plugin name). I recommend to use the same word used for the –default-domain argument.

−−package-version=3.0.18 defines the version of the plugin that can work with your translation.

−−msgid-bugs-address=”<myemail@mycompany.com>” defines an email used to contact the translation author for updates and translation errors. Not mandatory but recommended.

*.php to search in all the .php files for strings to be translated.

If you now got a .pot file, go ahead to the next point in this chapter. Otherwise, please try the next method.

B – Using Poedit (recommended and easy)

Poedit (http://www.poedit.net/) is a graphical and multi-platform translation tool that is designed to work with gettext translations. You can get Poedit at the previous link and install it. Once installed, follow these instructions:

  1. Open Poedit
  2. Click on the “File>New catalog” menu item
  3. A new window with three tabs appears:
    Poedit project configuration, Tab 1

    Poedit project configuration, Tab 1

    Let’s fill in the first tab. Please note that I am a user of the French version of Poedit, therefore my English translation of the fields and menu names may not reflect exactly the real labels. In the “Project name and version” field, type in the plugin text domain followed by its current version (example: “counterize 3.0.21“). In the Translation team field, type in the name of your team. Can be anything. Next, the team email. You are advised to write a valid email so that users and the plugin developers can contact you if they find a problem with your translation. Do not choose the language and the country of your translation now. Then select the charset (for Character Set) of your translation (utf-8 is recommended) and the charset used in the source code (usually utf-8, but could be iso-8859-1 for example…). Now go to the second tab which defines the paths where to look for the sources:

    Poedit project configuration, Tab 2

    Poedit project configuration, Tab 2

    Type in the directory where you extracted the source for the “Base path” field. Then double click on the top of the big blank area. Type in a dot (“.”) without the quotes, as in the following screen-shot. Now click on the last tab.

    Poedit project configuration, Tab 3

    Poedit project configuration, Tab 3

    We have to define how to find the strings to be translated. We have to tell Poedit which keywords to look for to detect the strings. WordPress provides two shortcut functions: “__()” and “_e()”. So lets type “__” and “_e” in two separate lines, as seen in the screen-shot.

  4. Click on the “Validate” button. Save the file as {the plugin text domain}.po (for example: counterize.po).
  5. You will get the following window:

    Poedit "what's new" window

    Poedit "what's new" window

  6. Click on “Validate“.
  7. Click on the “File > Save” menu item or the “Save” button in the toolbar.
  8. Close Poedit and go to where you saved your .po file.
  9. Rename it from .po to .pot (for example: from “counterize.po” to “counterize.pot”) and delete the corresponding .mo file if present.

That’s it! You now have your .pot file, ready to be translated.

4 – The .po file

If a .pot file is a model, the .po file is the file you will use to actually put your translated strings. We will use Poedit to edit the .po file.

Do not edit it manually! The reason is this .po file cannot be used directly by gettext, it must be compiled to a .mo file before, and Poedit do that automatically.

Let’s prepare our translation:

  1. Copy your .pot file to a new .po file. You have to append the locale before the .po extension. For example if we have “counterize.pot”, we will copy it under the name “counterize-FR_fr.po”.
  2. Open this file (“counterize-FR_fr.po” for example) in Poedit
  3. Click on the “Catalog > Settings” menu item.
  4. In the first tab, just select the target language of your translation, and the target country. Those two fields must be set to a valid entry! Otherwise you will not be able to use your translation. See the screen-shot for French language as an example:

    Poedit project configuration

    Poedit project configuration

  5. Click on the “Validate” button
  6. You are now ready to translate! Click on one sentence in the list to select it for translation. On the bottom of Poedit, there are two fields: the source field and the target field. You must write your translation in the target field (the empty one).
  7. Select another sentence and translate it. Repeat the process until you translated all the sentences.

5 – The .mo file

The .mo file is the machine-optimized version of the .po file. It is not human readable, so don’t try to edit it manually. Always generate your .mo files using Poedit or whatever other tool you use to translate.

  1. When you translated all the sentences, in the Poedit toolbar click on the “Save” button (or “File>Save” in the menu). You should now have a .mo file. For example “counterize-FR_fr.mo“. This file is the one that will be used for translating the plugin.
  2. Test the translation! Copy and paste both the .po and .mo files into the plugin directory (or whichever directory the plugin other .mo files are located) into your WordPress installation. If your blog is already using the desired locale (for example FR_fr), the plugin should now use the translated strings!

Some tips to translate with Poedit and gettext:

  • In Poedit, take extra care about escaping the double quotes (“) if present in the translation source by adding an anti-slash before each double quote (\” ). Otherwise your translation could be truncated. Poedit will always adds some double quotes around your translated sentence, except if it find a non escaped double quote in your translation. Just be careful with double quotes.
  • You will most probably find some things such as “%s, “%d” or “%1\$s” in the sentences to be translated. These are placeholders for some data to insert at that specific place. For example, you may find the sentence “Hello, %s” where %s will be replaced by your name in the plugin. Take it as a rule that you MUST include any placeholder in your translation when you see them.
  • Do not give “Google Translate” translations to the plugin author. These are usually bad translations. Please…
  • Respect the punctuation rules of the source and the target languages. The more care you take to offer a good translation, the more people will use it. For example you should avoid breakable spaces between a word and a “!” sign in French, and insert an unbreakable space instead (&nbsp; in HTML and XHTML).
  • If your language is read from Left to Right, you can ignore any “&#x202A;” and “&#x202C;” control characters that you may find in the source sentences.
  • Check your spelling! Do not send translations full of misspelled words…
  • Always test your translation before you send it to the plugin author.
  • Send both the .mo and the .po files to the plugin author so that he can open your translation and make it available to other people for translating the plugin.
  • Save often.

Updating an existing translation

If you are not satisfied of your translation, or a newer version of the plugin has been released, or you want to correct someone else’s translation, read this chapter. We assume that you already completed all the steps of the first chapter.

Updating an existing translation is quite strait-forward:

  1. Open the .po file in Poedit.
  2. Go to the “Catalog > Settings” menu. In the first tab, “Project name and version”, update the version if it is not set to the latest.
  3. In the second tab, make sure that the referenced path is the one where you extracted the plugin sources. If it is not, update this path.
  4. Click on the “Validate” button
  5. Click on the “Catalog > Update from sources” menu item.
  6. A window will pop-up to show what changed since the last time. Some strings may have been updated, some other may have been deleted, and probably some new untranslated strings will appear. Accept the changes.
  7. Proceed to translate the new strings first. They are usually colorized in dark blue.
  8. Double-check the strings in orange color. These are fuzzy matches. It means that Poedit proposed a translation for a string it thinks it recognizes, or sometimes it is just because a string was slightly modified. Correct the invalid orange translations or approve them by clicking on the cloud button.
  9. Click on the “Save” button or “File > Save”.

Congratulations, you just updated your translation! If you are satisfied of the results, you can now send your updated translation to the author of the plugin.

Frequently Asked Questions

  • Q: Why do my strings appear truncated?
  • A: It may be because you forgot to escape some double quotes. Check everywhere in your translation and make sure any double quote is escaped with an antislash (\) before the double quote.
  • Q: Why do I have errors during the importation of the strings from source?
  • A: Most probably this is an encoding error. Check in which encoding the plugin sources are saved, and set the Catalog Settings accordingly. For example if the plugin sources are saved in ISO-8859-1 and you specified “UTF-8″ as the source encoding in your .po file, then you are very likely to get some errors.
  • Q: Why my translation doesn’t work?
  • A: It’s most probably a locale problem. Check that your WordPress installation is set to the desired locale. This is usually done in the “wp-config.php” file in the root directory of WordPress. Check that the “define(‘WPLANG’, ”);” line is set to the locale of your translation (for example, if you translated a plugin to the “FR_fr” locale, then you have to set the line to “define(‘WPLANG’, ‘FR_fr’);”).
  • Q: My locale is set correctly, but the plugin is still not translated!
  • A: It may be that you didn’t put the .mo file in the correct place. You should ask the plugin author for the correct location where to put the .mo files.
  • Q: I found errors in your guide!
  • A: That’s a good thing, because you can tell us about the error and we will update the guide!

This is the end of this tutorial, we hope that this guide helped you to translate the plugin of your choice!