What’s with all the double-underscores everywhere?

If you’re new to creating  WordPress themes and have been digging into the PHP for the first time, you may wonder what’s up with all of the massively redundant __() functions.

WordPress uses the GNU gettext library to make translation easier. Any string that is hard-coded into a theme or plugin should be fed through one of the methods that marks the string for translation.

Arguments for the functions include the string to be translated, and a unique-to-your-theme “text domain” string, which is used to identify which component the string relates to.

The functions:

__( 'Your text string', 'yourthemetextdomain' )
returns the translated text string.

_e( 'Your text string', 'yourthemetextdomain' )
echos the text string (equivalent of placing an ‘echo’ before the previous string).

_x( 'Your text string', 'Additional context for the translator', 'yourthemetextdomain')
Sometimes, the string to translate does not have enough information on its own. This form of the function allows you to provide a translator with contextual information.

_ex( 'Your text string', 'Additional context for the translator', 'yourthemetextdomain');
Same as _x, but – you guessed it – it echos the result.

What if you know most of the string, but not all of it?

Such as “View all posts by _______”. You don’t want to translate just “View all posts by:” and then have the name follow, because depending on the language, the grammar may dictate that the name falls in a different location.


Hint: embedding $php_variables such as “View all posts by $author_name” will NOT work!

That’s where %s (string) and %d (number) come in handy:

__( 'All posts by: %s', 'yourthemetextdomain' );

You will then need to use sprintf or printf to place the variable in the string:

printf( __( 'All posts by: %s', 'yourthemetextdomain' ), $author_name );


$archive_title = sprintf( __( 'All posts by: %s'. 'yourthemetextdomain' ), $author_name);

What if you have more than one string or number?

Instead of %s, you can use %1$s, %2$s, %3$s, and so on. Likewise, instead of %d you can use %1$d, %2$d, and so on. Then include all relevant variables in your printf or sprintf string.

printf ( __( 'This is a string about %1$s and %2$s', 'yourthemetextdomain' ), $first_string, $second_string);

Speaking of numbers…

Sometimes a string needs to appear differently depending on whether or not a number is plural.

printf ( _n (‘%d comment so far’, ‘%d comments so far’, ‘yourthemetextdomain’), $num_comments );

Yes, the _n only allows for one singular, and one plural, even though some languages are more complicated than that. But there is a way for the translator to add more options, even though the PHP syntax at this end is limited to the English singular/plural system.

It won’t DRY out!

Now, if you care at all about DRY (Don’t Repeat Yourself) code, you’re going to be tempted to do something like:

function mytheme_translate( $the_string )<br />
{<br />
return __( $the_string, 'yourthemetextdomain' );<br />
//Don't do it!!!<br />

Don’t do it! It won’t work.

Well, technically, the __() function will still work to pull an already-translated stringA into your WordPress theme. But the script that runs on your PHP files to pull out all the strings for the translator? The translator will just receive the literal ‘$the_string’, and not any of your actual text. So unless you plan on translating your theme to every language known to humanity yourself, you’ll need to put up with the redundant ‘yourthemetextdomain’ everywhere

Doesn’t PHP reserve functions beginning with a double-underscore as ‘magic’ functions?

Yes, it does.
However, there are enough frameworks that use some variation or another of the __ translation methodology that it has become a fairly solid exception.

Additional gotchas to watch out for:

For reasons internal to how the gettext system works:
• If you need to insert line-breaks into translated strings, use ‘\n’, not ‘\r’.
• Don’t try to translate an empty string.

For more information:


Official documentation:

• http://codex.wordpress.org/Translating_WordPress
• http://codex.wordpress.org/Function_Reference/_2
• http://codex.wordpress.org/I18n_for_WordPress_Developers
• http://www.gnu.org/software/gettext/gettext.html
• http://www.php.net/manual/en/function.gettext.php

Helpful blog posts:

• http://www.eatmybusiness.com/food/2007/04/13/what-on-earth-does-a-double-underscore-then-parenthesis-mean-in-php-__/7/
• http://www.catswhocode.com/blog/how-to-make-a-translatable-wordpress-theme
• http://ottopress.com/2012/internationalization-youre-probably-doing-it-wrong/

Start a conversation!

This post looks bare without your input.

Leave a Reply

Your email address will not be published. Required fields are marked *

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