Translating WordPress Plugins & Themes

This guide is another in the Inside WordPress series and attempts to show how to produce a translation for an already-prepared theme, plugin, or WordPress itself. Even if you have little PHP or HTML skills you can still contribute to making WordPress a truly international experience by providing localizations for existing themes and plugins.


The guide will be written from a beginners perspective and will not assume any knowledge of PHP or HTML (although some will be helpful). Detailed explanations will be given at every stage and you are invited to provide feedback or pose questions.

If you are a plugin or theme writer then please take a look at Preparing A Theme Or Plugin for Localization, another in the Inside WordPress series that is specifically targeted at the steps involved before a translation can occur.

An Overview of localization

WordPress uses a standard localization framework called GNU gettext. This framework provides the programmer the ability to mark text inside code as being suitable for localization. The role of the translator is to take these marked pieces of text and produce a language-specific localization. No code needs to change and you do not need to understand how the program works.

Text is marked by wrapping it with special PHP functions. It is not important to know how these functions work, but it will be helpful to recognize them:

  • __($text) – Looks for a translated version of $text and returns the result
  • _e($text) – Looks for a translated version of $text and echo the result to the screen (i.e. effectively it is echo __($text))
  • __ngettext($single,$plural,$number) – If $number is 1 then looks for a translated version of $single. If number is more than 1 then looks for a translated version of $plural.

With a suitably localized theme, plugin, or WordPress, the steps involved in translating it are:

  1. Run a tool over the code to produce a POT file (Portable Object Template), simply a list of all localizable text. Some themes and plugins may already provide you with this
  2. Use a plain text editor or a special localization tool to generate a translation for each piece of text. This produces a PO file (Portable Object). The only difference between a POT and PO file is that the PO file contains translations
  3. Compile the PO file to produce a MO file (Machine Object), which can then be used in the theme or plugin

Tools Of The Trade

Special software tools are needed in the translation process. There are many available options here and this guide will show you how to use two Open Source tools:

  • poEdit – A cross-platform graphical tool that is available for Windows, Linux, and Mac OS X
  • GNU gettext – The framework has its own set of command-line tools to produce the POT file and to compile the MO file. Use of these tools is considered advanced, and is more appropriate to people who want to automate the translation process

Before you continue you should ensure you have one of the above tools installed.

Installing poEdit

poEdit is a localization tool with a graphical interface. Windows and Mac OS X users can download a self-installing file from the poEdit download page, while Linux users will need to install it via their package administration system.

After installation you should take a few moments to configure poEdit. This is very simple and just requires your name and email address, which will be embedded in any files you produce. From the poEdit menu select Preferences to bring up the settings. Enter your details:

Configure Poedit

Installing gettext

GNU gettext can be installed easily enough on Linux using a package management tool appropriate to your installation. Windows users can download a self-installing file from Gettext For Windows which will take care of any complexities. Mac OS X users have the choice of downloading gettext and compiling it themselves, or using a pre-built copy from a package management such as Fink or DarwinPorts. Details of any of these methods is beyond the scope of this guide and any problems should be directed at the appropriate website forums.

Note that this guide will assume that the gettext utilities are located somewhere in your path.

Naming conventions

The naming of your PO and MO files is very important and must match the desired locale. The naming convention is:


Or, for non-standard encoded localizations:


That is, the file name must be the language code followed by an underscore, followed by a code for the country (in uppercase). If the encoding of the file is not UTF-8 then the encoding must be specified. For example:

  • en_US – US English
  • en_UK – UK English
  • fr_FR – French
  • zh_CN – Simplified Chinese
  • – Japanese in EUC-JP encoding

A list of language codes can be found here, and country codes can be found here. A full list of encoding names can also be found at IANA.

Note that WordPress plugins have an additional naming convention whereby the plugin name is added to the filename:



  1. WordPress汉化手册…


  2. i used your redirect plugin, to translate it to Arabic, Saudi Arabia, utf-8, i added the path of the extracted plugin, i put the keyword(–,-e,-ngettext:1,2), then i pressed ok, it did some scan put nothing appeared in the list & no .pot file was created. thanks for your time in advance.

  3. Very helpful article. I have a question about the catalog path settings. The poEdit help states that the path information is relative to the location of the .po file. This is a little different than what you’ve said here. If I follow the help and the .po file is in c:/thisplace/lang then the path for the source files are relative. (This is what the help file states). In practice, however, this doesn’t seem to work. Setting additional paths to “../src” with a basepath of c:/thisplace.lang” yields ‘no source files found in ../src”. Setting a complete path to a plugin directory under say under “c:/mypath/wp-contents/plugins/myplugin” will allow it to locate source files if the additional path “src” is added. The ‘#:’ statement contains “src/somefile.php:” – this seems ‘non-portable’ to me somehow. The ‘src’ file is relative to the base path but not relative to the location of the .po file – as a result translations don’t appear to work. I say ‘non-portable’ because not everyone is going to have the same path as the developer. Most .pot files I’ve looked at have a base path of ‘.’ – this makes more sense to me because the basepath is the ‘current directory’.

    I’m not understanding this and the help file isn’t much help. Maybe you could shed some light on this.

    – thanks –

  4. Hi…its very ice post!
    In way translating my WordPress, I have big problem. PLS help me.
    I translating English vertion to Uighur language version(Arabic). Uighur later writing from right side to left( likes Arabic). How can I make it from left to right side?

  5. Hello,

    I have translated the theme I’m using for my site into two languages; Danish and Arabic.
    My Danish site shows the translation, but the Arabic one doesn’t, it uses the Danish translation.

    I can’t see what the problem is.. Any idea?

  6. No, I mean to configure WP to use a localization – putting the files in the directory is not enough, you need to tell it to use the files too

  7. Hello again,
    I added the following code to wp-config.php:
    define (‘WPLANG’, ‘ar_BH’);

    That means I have these to lines now:
    define (‘WPLANG’, ‘da_DK’);
    define (‘WPLANG’, ‘ar_BH’);

    But nothing happened..

  8. Great post, I have been using Global translator plugin for WP as I did not think that I was up to writing something of my own, but it has led to being banned from Google translation I suppose due to not having the /en /fr /de etc folders nofollowed or blocked in my robots.txt file. I am now left with a whole bunch of links in google in different languages that now cannot be reached. Since our blog does not change that frequently other than the items in our nextgen gallery I will definately explore the options you have outlined above. Thanks very much for these options.

  9. Great article! It looks to take a bit of time to setup WordPress for other languages but when I have the time I am definitely going to move forward using this article.

    Thanks for the research,

  10. And it would be very very nice to have a tag for themes on which just says “localizable” or “i18n”! Otherwise you always have first to download a nice looking theme to find out if it is using the __ or _e functions so that you could easily tranlate it into german or turkish for a customer. If not you only have a nice looking theme and nothing else. (Maybe english theme editors are too lazy to care for l10n or i18n…)

  11. Great Tutorial! Unfortunately you didn’t mention anything about using: load_theme_textdomain() for including the theme file. Took me some time, a break and then another 5 minutes 😉 Thanks anyway for this introduction to gettext.

  12. Great post and very useful but I have a problem and it’s killing me , I have my plugin in this path
    I wrote in the Base path :
    and in the paths
    well it give me an error that there is no files in this path , my question is : what kind of files does it searches for ??
    because I only have mine.php inside it .
    Could you please help ?

    Feras Allaou

    1. Feras, instead of full Windows paths, use relative paths in Poedit, defined via “.” (the dot character) in your Catalog Settings. I’ve found the following path settings work for me, when translating John’s plugins on Windows.

      – Base path: .
      – Paths: ..

      As far as I can tell, single dot means “this folder” and 2 dots mean “one level up”. Since John has the language files always under the sub folder ‘locale’, Poedit needs instructions to look one level up in the folder structure for source code files, thus the “..” path.

      I suggest you use Poedit’s Catalogs Manager for all your translation projects. There, when staring a new project, you get to choose the project’s folder via convenient ‘Browse’ button. Poedit scans this folder for language files and presents you with a list. Open the desired language file (catalog), go to ‘Catalog’ > ‘Settings’ and define the paths with dots. As a final thing, make sure that on the ‘Catalog’ > ‘Settings’ ‘Keywords’ tab, the PHP gettext language variables “_e” and “__” are defined.

      If you get the ‘Paths’ and ‘Keywords’ right you can do a catalog update every time the plugin source code has been updated to let Poedit find the changed strings for you. It’s very, very convenient.

      Hope this helped.

  13. I have generatet two .po files from Icanlocalize.
    One for wp-admin, which is allready localized. And one for wp-content.

    My question is, how can I integrate my second .po file from wp-content, in the first one?
    And afterwards convert this to a new .mo file.

    Or is this the right way to do this?

  14. Finally found an in-depth explanation for localization. Thanks for the detailed how to on name conventions.

  15. there is something missing here. where to put this pluginname-fr_FR.po file? in the directory of plugin or a sub-directory called langues or smilar?

  16. Hi, I am trying to translate wordpress network site into icelandic and translations are not showing. Does anyone have a clue if there is some solution to translation of wordpress network sites?

Comments are closed.