Theme developers, please…..start your “translation mindset” as early as you can on your development. Why? It’s like make a new class, populate it with several functions and then say “I’ll do the code documentation later…” No you won’t. Use __() and _e() as early as you can.
You are going to create 3 files and changing 1:
The general idea is mark which code is translatable in your theme, create translation files and tell wordpress where they are.
Let’s start by telling wordpress where are our translation files. Open functions.php:
load_theme_textdomain( 'my_theme', get_template_directory() . '/languages' );
The first parameter of
load_theme_textdomain is the identifier, it must be unique. Generally, you should name it as your theme name or this prefixed by some letters (if your theme name is common).
Now we can make our code translatable by using wordpress built in functions. All of them have a last parameter named
domain which is that you defined earlier on load_theme_textdomain. The main ones are:
__( $text, $domain ): get $text and return its translated version relative to $domain.The function name is two underscores. –docs.
_e( $text, $domain ): same as __(), but it echoes the result. –docs.
_x( $text, $context, $domain ): get $text and return its translated version according to $context and relative to $domain. This is used with homonyms. Take “date” as an example, it can mean “relationship” or “time”. –docs.
_n( $single, $plural, $number, $domain ): return $single or $plural based on $number and relative to $domain.–docs.
_ex( $text, $context, $domain ): same as _x(), but it echoes the result. –docs.
_nx( $single, $plural, $number, $context, $domain ): it’s a hybrid of _n() and _x(). –docs.
esc_attr__( $text, $domain ): it’s a hybrid of __() and esc_attr(). –docs.
esc_attr_e( $text, $domain ): it’s a hybrid of _e() and esc_attr(). –docs.
Some considerations about these functions
_e() are basically the same, the difference is the echo. I know you are incredibly smart and noticed that the
e at their names indicate the echo. So, check the following statements:
// __ and _e() are equal below
echo __('Homer Simpson is GREAT', 'my_theme');
_e('Homer Simpson is Great', 'my_theme');
// _x() and _ex() are equal below
echo _x('date', 'relationship', 'my_theme');
_ex('date', 'relationship', 'my_theme');
_n() it’s used when you need to use a sentence that is based on a number. Let’s say you have a script that show how much you worth based on your value. “Peter worth 1 dollar” will have a different translation than “Peter worth 10000 dollars”. In this case the translator must change both sentences because of the word dollar. So the code should look like this:
$value = '1000';
$text = sprintf( _n( 'Peter worth 1 dollar', 'Peter worth %d dollars', $value, 'my_theme' ), $value );
In the code above, why did I use sprintf and not embedded a “Peter worth $value dollars” ? The answer only God knows…kidding. The answer lies on the pot tool, in this case, POEdit, the program we are going to use to create our translation files (I’ll explain that later). The pot tool will parse our code looking for references about “what the hell do I need to translate”. The parser will get “Peter worth $value dollars” but at execution time, the wordpress function will look for “Peter worth 1000 dollars” and the translation will fail. Using
printf save us from that problem.
Ok, after some work looking and marking your translatable code with the functions above, it’s time to know about .pot .po .mo files and pot tool.
POT, PO, MO Files
.po files are based on gettext, a system used for writing multilingual programs. gettext was originally created at Sun Microsystems, BUT I’m not here to tell history.
Let’s be familiar with them:
- POT ( Portable Object Template ): one word for you: blueprint. This file is the blueprint about your code. It contains all the sentences that needs to be translated, but it not contains any translation. This file will be used by translators.
- PO ( Portable Object ): This is the result file from translators. It’s created after a .pot file. Human readable.
- MO ( Machine Object ): This file has the same content as the .po file, but it differ in the format. Programs use the .mo files. Machine readable.
To create your .pot file, you need a program capable of that. There are many of them: Launchpad, Pootle, Poedit, GlotPress and others. Particularly I like Poedit (because this is the only one I tested, but let’s forget that).
Download Poedit and open it. Go to File > New Catalogue, then you have 3 tabs to fill with.
Project name and properties: my_theme
Team's email address: [email protected]
Language: English (or your native language)
Source code charset: UTF-8
Plural Forms: nplurals=2; plural=n != 1;
note: plural forms are relative on how english words (single and plural) will be translate to other languages. For a better understanding, –docs.
This depends about “where are your files to be parsed”. Let’s say that we put our .po files in root/languages folder, and the code to be parsed is on root. One dot
. means: the code to be parsed started at the same place as .po files. Two dots
.. means: the code to be parsed starts one folder above .po files. If you’re a programmer this is like to teach you 1 + 1 = 2. I put the .po files in root/languages, so I use
Here you list the wordpress localization functions defined above:
These numbers 1,2 means that the keyword have two parts. By default the second argument is plural, but the
c means that the second is a comment.
Press Ok and save it at the folder you defined earlier in “source paths”. By default, at least for me, the program tries to save the file as .po and not .pot. Just rename it to
my_theme.pot and delete the other file created with it ( .po file ) and stay with the .pot
That’s it. Your theme is translate ready. Now the translator just need your .pot file and create their .po .mo files, which in fact are translations.
Localization of your theme
Now you can shout to the world “My theme is translate ready!”. Ok ok. Let’s do another thing. Anyone here who speaks english realized that english isn’t my native language. I’m brazilian and by that I want to create .po and .mo files for my country.
Open POedit > Open > All Files (*) and then open your .pot file, probably my_theme.pot. Now Catalogue > Update from Sources. This will search the sources defined in .pot file.
This is self explanatory, click on the sentences at Source text and translate it, move to another line and go on. After all this process, Go to File > Save as > name it according to your language (in my case pt_BR) and save it as .po. My final file is pt_BR.po. The .mo file is created automatically when you save your .po. If for some reason the .mo file did not appear, go to File > Preferences > Editor > and check Automatically compile .mo file on save. These files ( .po and .mo ) must stay at the same folder on which .pot file is.
Remember, everytime you save your .po, a .mo is generated accordingly.
When .pot .po and .mo are ok and in place, just edit the wp-config.php located in wordpress’ root folder. Look for
define('WPLANG','') and change the second argument to your language. In my case it’s
That’s it. Any errors or complements put them at the comments below and I will update this ‘how to article’ as soon as possible.