Advanced Translation Voodoo


This serves as another installment in the series about “Why We Do Things The Way We Do Them” in Underscores.

It is about a commit that we made almost a year ago. That commit dealt with a bug that a few themes have on, and which just recently came up again internally, on an old Trac ticket.

The commit message reads like this:

_s: Provide a context for the comments title strings.

There are languages that have more than one plural form. Sometimes these
languages need to add the %1$s placeholder in the original singular
version to help differentiate between these plural forms.

In case the original singular version (‘One thought on
“%2$s”’ in this case) is used elsewhere, the translation
with the faulty %1$s will be used, possibly ending up with the
placeholder not being replaced.

The context will prevent that from happening by seperating(sic) the strings.

Imagine we have a project (theme or plugin, it applies to both), that contains following function calls:

// Somewhere in the project:
printf( _n( 'One Comment', '%1$s Comments', $count, 'domain' ), $count );

// Somewhere else in the project:
__( 'One Comment', 'domain' );

The translation tool will load the same translation for the string 'One Comment', no matter where it is used. The tool doesn’t care if we just need it in a situation where it depends on how many comments there actually are, or if we just need it translated and returned. It will always load the same translation.

In a lot of languages this is not an issue, languages where we have one singular form and one plural form. But there are some languages that have multiple plural forms, depending on the actual amount referred to. Think of it as always having to add ‘rd‘ to a 3. 3rd, 23rd, 33rd, you get the idea.

As I mentioned in the commit message, sometimes these languages need to add the %1$s placeholder in the original singular version, to help differentiate between these plural forms. In these instances 'One Comment' might be translated to  '%1$s Comment'. And when we then use 'One Comment' somewhere else in our project, that placeholder will not be replaced there.

So how do we avoid having strings be falsely translated because they are used in different contexts? By providing context.

In the commit we changed the function call from _n() to _nx() and passed the context of 'comments title'. This tells the translation tool to treat the same string differently, because it is used in different contexts. Much like the term Search in a search form might be used as a label, a placeholder, or a button text — and might be translated differently because of that.

Yes, we try to get even these “little” things right.

Author: obenland

Release Lead (Ret.) at Automattic, WordPress Contributor. Can be found on Twitter (@obenland).