WordPress localisation: the difference between x() and translator comments

There are two ways in WordPress to provide context for translatable text (”strings”): the _x() function (along with its related functions), and the /*translators:*/ comment. Their use is described in the Plugin Handbook, but here’s a quick definition of their key differences.

Translator comments

The /*translators:*/ comment describes something about about a string. To take a random, simplified example from WordPress core (string shortened for readability):

printf(
     /* translators: %s: Privacy Policy Guide URL. */
     __( 'Please <a href="%s">review the guide</a>…' ),
     esc_url( admin_url( 'privacy-policy-guide.php?tab=policyguide' ) )
 );

In GlotPress, WordPress.org’s own translation platform, this shows up as a comment on the translatable text:

Table entry with the original full string and a comment section underneath saying “%s: Privacy Policy Guide URL”
(Full original string this time)

That way, translators are informed about the meaning of the %s placeholder in the string. In this case, it’s pretty clear that it’s supposed to be a URL, but placeholders get used for all kind of things, so in other cases it might not be as clear.

The _x() function

The _x() function accepts three parameters:

_x( string $text, string $context, string $domain = 'default' )
  • The first parameter is the actual string, i.e. text to translate.
  • Developers can use the second parameter to indicate in which context within the software this particular instance of the string appears.

Similar to the /*translators:*/ comment above, that context is displayed by GlotPress in the form of a short description, but with one major difference:

It creates a separate instance of the string in the language file.

Here’s another example from WordPress core:

_x( 'Post', 'add new from admin bar' )

Note that the same string “Post” appears again in the same core file, but with a different contextual description:

_x( 'Post', 'post type singular name' )

And this is how it looks in the translation database:

Two table entries: “Post (add new from admin bar)”, “Post (post type singular name)”

So here, translators not only are informed of certain context for the string, but they actually get two separate instances of the string to add different translations for.

In the example above, German doesn’t require a different translation for “Post” in the Add New admin bar menu than it does for the general post type name, but other languages may have different grammatical requirements.

Generally speaking, the fact you can use the same source text in English within different contexts doesn’t mean it’ll work as smoothly in other languages. So that’s what x() is for.

(Apologies, I know I suck at picking examples here. You’ll just have to trust me if you don’t know already, languages can get super tricky.)

TL;DR

  • The /*translators:*/ comment just adds a description that appears alongside a string in translation software.
  • The _x() function and its related functions _ex(), esc_attr_x(), esc_html_x(), _nx(), and _nx_noop() create a separate instance of a string for each description used in their $context parameter, so translators get to translate one and same source string (English in WordPress) in multiple ways, according to its context and the grammatical requirements of their locale.

See the official WordPress Code Reference and the Plugin Handbook for details on how to best use these functions.

2 comments

Leave a Reply to Torsten Landsiedel Cancel reply

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