Writing a translatable library/framework that is used by wordpress plugins and themes

I got burned in the wordpress stack exchange while answering a question about variables in translatable text, which was really more about adhering to (IMO wrong) theme repository conventions while using third party code which doesn’t use them. My mistake came from misinterpretation of the translation strategy the third party code being used (the TGM plugin activation library) was using.

There are twp possible translation strategies for such libraries, self contained and integrated.

In the self contained strategy the library is distributed with the translations of its strings, using a specific text domain for them. The theme/plugin author using the library just needs to include it and initialize it.

require_once(dirname(__FILE__).'/useful_lib/useful_lib.php');
useful_lib_init();

Assuming the library expects its translation file to be in the “lang” sub directory of its root it only has to do

function useful_lib_init() {
load_textdomain('useful_lib',dirname(__FILE__).'/lang');
}

and use “useful_lib” as its text domain whenever the translation functions ( __(), _e()…) are called.

The advantage of this approach is that whoever uses the library don’t need to worry about the translation of the strings used in the library, and once a translation is updated he can simply include the new version of the library and push an update.

The disadvantage is that you don’t have full control over the translation of your theme/plugin (you can claim it works in language X only if  the library supports the language as well) and you have to communicate to translators that the files residing in the “useful_lib” directory should not be translated as it will have no impact on the result (maybe suggest to the translator to contribute the translation to the library).

In the integrated strategy you let the theme/plugin determine which text domain to use. The easiest way is by forcing them to DEFINE it.

if (!defined('USEFUL_LIB_TEXTDOMAIN')) {
  error('USEFUL_LIB_TEXTDOMAIN had to be defined');
}
.....
// then you have in the code
_e('Welcome',USEFUL_LIB_TEXTDOMAIN);

This way there is some duplicated translation effort between different users of the library, but the end result is totally under the contrul of the theme/plugin author.

And…. there can be an hybrid approach. If no explicit text domain is specified use our own, just need to remember to load the text domain

if (!defined('USEFUL_LIB_TEXTDOMAIN')) {
  define('USEFUL_LIB_TEXTDOMAIN,'useful_lib');
  load_textdomain('useful_lib',dirname(__FILE__).'/lang');
}
.....
// then you have in the code
_e('Welcome',USEFUL_LIB_TEXTDOMAIN);

In my opinion, libraries should follow the “integrated” strategy unless they have non trivial amount of translatable strings, and the maintainers are willing to maintain the translations as part of the library.

As for the hybrid approach, I don’t see any real life use case for it. If library can be used as “self contained” it is probably better to use it that way, and get automatic translation updates whenever there are, instead of asking your theme/plugin translators to retranslate just because there was a change in the library.

BTW, my failing was due to the library in that question using the hybrid strategy while I thought it is a “self contained” because I failed to notice the text domain initialization variants, and this calls for an article about how wordpress theme and plugin writers misuse the OOP paradigm….

__return_false and its siblings are great way to provide callbacks that do nothing in wordpress

Some of the wordpress API functions like add_settings_section require that one of their parameters will be a valid callback function. If your callback does not suppose to do a thing then you can simply use __return_false that immidiatly returns false as the callback instead of declaring a dummy callback by yourself.