Excluding Specific Text Domains From Language Files (Or So)

|

Note: Content might be outdated!

When your plugin or theme supports WooCommerce, you might be using text strings from WooCommerce in your template files or hooked functions. Assigned to those strings is the woocommerce text domain, so translation will be handled by WooCommerce itself. Yay all the things, only one question remains: How can you get your translation tool to not include those strings in your language files?

Multiple Text Domains In Your Theme Or Plugin

We’re talking about something like this in a theme or plugin file:

It could be any text domain other than the one of your theme or plugin, of course. In our example, WooCommerce will translate the string, given the language file for your locale does exist.

Still, that string is going to be parsed by any gettext-based translation tool and be included into the language files of your theme or plugin.

Meh. Bloated language files, translation workflow messed up. Not so bad if it’s only one or two strings from another text domain; but often a theme supports multiple third-party plugins, so the number of non-domestic strings can increase quite easily into two-digit figures.

Why Filtering By Text Domain Won’t Work

In my own quest for a solution I learned that filtering strings by text domain and including only those from your own domain can be considered a “misuse” of the GNU gettext library:

Neither GNU gettext tools nor Poedit (which uses them) support this particular misuse of gettext.

In gettext, domain is roughly “a piece of software” — a program, a library, a plugin, a theme. As such, it typically resides in a single directory tree and is alone there — or at the very least, if you have multiple pieces=domains, you have them organized sanely into some subdirectories that you can limit the extraction to.

Mixing and matching domains within a single file as you do is not how gettext was intended to be used, and there’s no reasonable solution to handle it other than using your own helper function, e.g. by wrapping all woocommerce texts into __woo (which you must define, obviously) and not adding that to the list of keywords in Poedit.

Václav Slavík (PoEdit) @ stackoverflow.com

Or as a WordPress lead developer concisely put it:

GNU gettext is not a PHP parser.

Mark Jaquith, Translating WordPress Plugins and Themes: Don’t Get Clever

There. Filtering strings by text domain—not going to happen.

Workaround: Wrappers

Václav Slavík suggests the workaround of “wrapping all woocommerce texts” into custom functions. Those functions can act as wrappers for the default i18n functions in WordPress.

Tools like Poedit and plugins like Loco Translate will not know of these functions, thus they won’t parse any strings passed through them.

Somewhat ironically, this is WordPress i18n standards backwards. Developers are supposed to not replace text domain strings with variables or constants in order to keep them parseable by gettext tools. In our case, we don’t want certain strings to be parsed, so we replace entire functions.

Questions

I haven’t tested this with WPML yet, and I’ll be deeply in whosever depth who will take it on. Other than that, what do you think? Any potential pitfalls you’re seeing with thist approach?

At least for temporary workaround in a local environment this works pretty neatly. If you don’t feel safe deploying wrapped gettext functions into production, there’s always NPM to rename back and forth.

Update: If you’re working with GlotPress, there’s this Grunt package by Marko Heijnen.

3 reactions on “Excluding Specific Text Domains From Language Files (Or So)

  1. Ulrich says:

    Thank you for writing this. A few things that you may need to also take into account.

    – The theme review team only allows a maximum of two text domain in the theme as some time in the future WordPress.org will handle all of the translations and so all of the strings will be added into Glotpress.
    – The best practice that I learnt was that you should not use strings from WP Core in a plugin or theme as they may be removed or changed one day. The same could apply for WooCommerce strings in a theme.
    – If you are using a translation management tool like Transifex there is a database of translations so the strings should be able to be translated quickly.

    The code could be slightly improved. If the string is only for WooCommerce and your function is prefixed with wc there is no need to have the text domain as a variable and you could hardcode it in the function. Another possibility would be to prefix the function with the theme slug and use it for different plugins.

    1. Thanks, Ulrich, helpful advice!

  2. Jens says:

    Thanks for writing this all up.

    I left another answer at http://stackoverflow.com/a/35668590/1129950. Hope it helps. I would be interested if you found another solution in the meantime (please leave an answer at stackoverflow, so we have answer to this problem in one place).

Reactions are closed.