The only use case for using wpml plugin for multi lingual wordpress sites is when you need control of the translation process

The CEO of OnTheGoSystems, the company behind the multilingual wordpress translation plugin WPML, gave a presentation in wordcamp jerusalem 2013.

The presentation started by showing leading Israeli site which have great content in hebrew but are much less impresive or even plain bad in english or russian.

For the english example he used the leading israeli news portal which has full content in hebrew and a simpler site in english. For the russian example he used the site of the airline arkia in hebrew and their russian site.

I wasn’t the only one that were underwhelemed by those examples for “poorly translated” sites. Ynet is mainly about israeli news so why would they even bother with an english site? tourists or buisnessman located in israel might want to know about the major political/buisness/cultural events but are they really interested in the israeli equivalent of “american idol”? Same goes for arkia, their main costumers are israeli and whatever service they give to russian speakers is related to israel  (the phone numbers in the site are local israeli numbers), and how many russian speaking israeli are there that can’t use the hebrew or the english site?

In ideal world all content would have been translated in to all languages, but in the real world translation cost money and there is no point in spending money for translating into languages from which you don’t make money. It is never enough to translate the site only when it is launched, and you always need to keep spending time and money for translating every new content.

And if the reason for not having full translation to all the languages is money related conscious decision, then why would you even start considering a solution which has the basic assumption that all content should be translated? Better to just set up a site per language and manage the translation according to the amount of effort you decided to dedicate to that language.

The presentation highlighted something that WPML seems to do well, it gives you an up to date status of the translation and makes it easy to see what parts of the site are translated and what are not. This is something you can’t automatically achieve when each language has its own site. For sites that have to have reasonable up to date content in several languages (even if not all of the content) it might be a valid solution.

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.


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() {

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

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')) {
// then you have in the code

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….

Localizing/Translating wordpress plugins and themes names and descriptions

Cool small localization feature that WordPress has is the ability to localize/translate the meta data of a plugins and theme. If plugin and theme authors will actually use it, it will enable localizers to provide a totally localized experience to the users even on the plugin and theme management pages.

This feature is very easy to activate, you should just add two lines into your plugin or theme header block

Text Domain: mytextdomain
Domain Path: lang_folder

where “Text domain” (mytextdomain in this example) is the text domain you used for your plugin/theme localization in the __e() and __() calls, and “Domain path” (here it is lang_folder) is the directory under your plugin/theme root directory in which the *.mo file resides.

For plugins, you can localize Name, PluginURI, Description, Author, AuthorURI, Version. For themes, you can localize Name, Description, Author, Version, ThemeURI, AuthorURI, Status.

While localizing Author info is probably not very moral, and localizing version probably not very smart, it is possible to localize the PluginURI and ThemeURI so they will point to a support/info URL relevant for that local. In other words, a plugin/theme developer can set up support page in english and another one in spanish, and use localization to point the spanish users to the spanish support page instead of the english one.

The only problem left is how to put those strings into your *.pot/*.po file.

For the plugin header below

Name: Plugin name
Description: Plugin description
Author: me
Version: 1.0
Text domain: mytextdomain
Domain Path: /lang

you can add the following code which enables the localization of only the name and description of the plugin. The location of this snippet in your code is not important as long as poedit can parse the file and conclude that ‘Plugin name’ and ‘Plugin description’ are translatable strings

_plagin_header_local = array(
__('Plugin name','mytextdomain'),
__('Plugin description','mytextdomain')

There are also other methods to achieve the same effect.

Relevant reading: Jacob Santos and Viper007Bond wrote on this feature.

How to expose dynamic translatable text to translation tools like poedit

The gettext translation framework is the best I ever used. All you have to do in order to find out which strings in your code require translation, and to create a skeleton translation file, is to have a function which performance the actual translation and just keep calling it for each translatable string. Then automated tool like poedit can be configured to parse your code, find all the strings that are used as parameter to the function and make a skeleton file containing them.
If our translation function is __() then when poedit parses our code and finds __(‘Somthing’) it generates a file in format similar to

Original "Something"
Translation ""

Now we just need to fill the translation (and you don’t need to be a coder to do that!) and tell our code to look for translations in this file.

Dynamic text breaks this nice system as almost by definition dynamic means that we don’t know the exact value at “compilation” time.When poedit scans the code below it doesn’t find any translatable strings.

a = get_response_from_remote_server(random-value);

But many times we know in advance that get_response_from_remote_server() can return only a limited set of strings, for example only “apple” and “orange”. Right now in order for them to be translated correctly we will need to add them manually to the translation file, which makes it much harder to maintain as you will need to add them again after the next time poedit will process your code.

Luckily there is a way to maintain the list of that kind of string as  part of the code in a way which enable poedit to detect them – just put them in the code.

dummy = __('Apple');
dummy = __('Orange');
a = get_response_from_remote_server(random-value);

Dummy here is never used, so there are no side affects. The problem with this approach is that we waste CPU time to call a function while we don’t need the value it returns.

Obvious improvement will be

if (false) {
  dummy = __('Apple');
  dummy = __('Orange');
a = get_response_from_remote_server(random-value);

Now we don’t execute the functions and a compiler might even simply discard that section of the code resulting with zero impact on performance while maintaning the ability to generate translation file automatically.

Which leads to the best option – add a source code file which include the strings but don’t add it to your compilation chain in your make file or don’t include it.

dummy = __('Apple');
dummy = __('Orange');