Translate is a package consisting of several classes, that already in WB 2.8.4 take care about all the handling of translations known as 'language files' up to now.
The days when adventurous constructs like the following had to be integrated in addons clearly belong to the past<PHP>
Load Language file
if(LANGUAGE_LOADED) {
if(!file_exists(WB_PATH.'/modules/droplets/languages/'.LANGUAGE.'.php')) {
require_once(WB_PATH.'/modules/droplets/languages/EN.php');
} else {
require_once(WB_PATH.'/modules/droplets/languages/'.LANGUAGE.'.php');
}
}
</PHP>From now on only a statement like: <php>$oTrans→enableAddon('modules\\droplets');</php>
is needed, and you are done.
If you now pose the legitimate question: 'is that all?', then simply read on.
===== General structure of the translation mechanism =====
==== General ====
For simplicity, I'm talking only about 'language files' here. However, in real case usage the translations no longer have to be defined necessarily as arrays in PHP files. Any conceivable suitable file format is possible now. The data don't not even have to be on the same server. The data could be provided by a web service, or stored in a database. For such use cases only a small, specialized driver is necessary, which can be loaded any time, even temporarily even for a single addon or template involved.
==== Translations before 2.10.0 ====
Let's start at the current level at the beginning of 2.10.0 and earlier. In the central language directory of the core, there are a large number of language files (DE.php | EN.php | etc.). Each of these files contains an overwhelmingly large number of language variables (specifically, currently about 600 !!). The used system requires that in each language file, each entry is present. Missing one often ends up in a runtime error. Once WebsiteBaker starts, one of these language files will be loaded with its full 600 entries forcibly. completely independent of whether even one of them is required! Of course, different addons then load their own language files still additionally. Having several different addons on one page even a very considerable number can also come together.
(From historical times, the translation of many ancient modules are included and a real care of the files, with a reasonable time / effort is virtually impossible. Whoever says otherwise, must be happy from now on take care of these fossil files. )
=== Aufbau der Sprachdateien (EN.php) ===
<PHP>
Modul Description
$module_description = 'Enter here a really short description of your module. About 200-250 characters should suffice.';
$MOD_MyModule['PRINT'] = 'Please print this page, if a copy is desired for your records.'; $MOD_MyModule['LOAD_LAYOUT'] = 'Load Default Layout'; $MOD_MyModule['TEXT_GUEST'] = 'Guest'; $MOD_MyModule['TEXT_UNKNOWN'] = 'unknown'; $MOD_MyModule['TEXT_PRINT_PAGE'] = 'Print page'; $MOD_MyModule['MESSAGE_ARCHIVE_DELETED'] = 'Zip(s) deleted successfully.'; $MOD_MyModule['MESSAGE_ARCHIVE_NOT_DELETED'] = 'Cannot delete the selected Zip(s).'; </PHP> somebody wrote this kind of entries: <PHP> $MOD_MyModule['PRINT'] = 'Please print this page, if a copy is desired for your records.'; $MOD_MyModule_TEXT['GUEST'] = 'Guest'; $MOD_MyModule_MESSAGE['ARCHIVE_DELETED'] = 'Zip(s) deleted successfully.'; </PHP> It does not look that good, but it works. Both syntax lead to the same Translate keys. <PHP> echo $oTrans→MOD_MyModule_PRINT; echo $oTrans→MOD_MyModule_LOAD_LAYOUT; echo $oTrans→MOD_MyModule_TEXT_GUEST; echo $oTrans→MOD_MyModule_TEXT_UNKNOWN; echo $oTrans→MOD_MyModule_TEXT_PRINT_PAGE; echo $oTrans→MOD_MyModule_MESSAGE_ARCHIVE_DELETED; echo $oTrans→MOD_MyModule_MESSAGE_ARCHIVE_NOT_DELETED; </PHP>
Translate is based on the premise that language files generally contain only the necessary items for each area. In return, a relatively large number of small language files is used. Each addon, each ACP extension must and even each individual template / theme can bring their own language files.
This division simplifies the work of a developer. He no longer has to find 'halfway matching' entries already there in the central file and to add any new entries, which must then be maintained / translated into ~ 25 different languages. As an absolute minimum requirement, it is completely sufficient, that an addon-specific file in the system language 'english' is shaped, that contains all the text of an addon, except for the central texts.
What are language files good for in templates ??
All language files are 'output Global'. This means that these texts are generally issued the same in all selected templates / themes. If a template for example has space for relatively short texts only, so that's no longer a problem. There are just the adapted texts taken with identical keys in the language file of the template - and the lyrics are especially adapted to this template. All other templates as usual get the global texts.
Translate works internally with several translation tables (TranslationTable). Each of these tables is made up of a maximum of 9!! different language files. That sounds at first a bit 'oversized', but it's not so bad, because first, the resulting translation table will be never greater than the largest file loaded due to the technology used, and secondly, by the built-in caching mechanism, the translation tables need to be rebuilt only after changes to the language files.
When you look at the table on the left (Extract from the Language support of Firefox), you can already see various Chinese, several German and English language in several dialects. The previously used, simple 2-letter codes purely following ISO 639-1 no longer satisfy at least the most languages with their major, regional to define variations. The use of IETF language tag according to RFC 5646 has therefore in the meantime become to an established standard. Translate supports at least the major part of the IETF tags. Not supported are currently the optional script subtags, extension subtags, and the private-use subtag.
Translate itself currently includes the following tags:
With this system, almost all languages and language variations occurring in the world can be mapped. In the full IETF tags still stood far more information, including the used character set (script). We have restricted ourselves here deliberately only to the actual language code plus the regional allocation. The Variant tag is used for the definition of slightly modified differences of language in the same country. For example, there is indeed Chinese in China and which in turn contains Mandarin or Cantonese, Singapore etc … This linguistic diversity is essentially more common than one can imagine at first glance.
The complete structure of Translate is based on complex translation tables which are each responsible for the core, a module or template. The basic structure is based on the 3 language settings and the fallback mechanism specified by WebsiteBaker:
Now, an auxiliary table is set up for each language setting, each in turn mixed together from up to 3 language files, which specifies the language code. This 3 auxiliary tables are then mapped together in the order System→Default→User to obtain the actual translation table (in fact it's a bit more complex to save time and memory), which is then also automatically cached. So the next call to the same language setting eliminates all the above-described procedure and just the final table is loaded from the cache.
Exactly as just described for the central translation table, it also happens the same way for each individual module and its template which ships with language files and actually loads and uses them.
For Addon developers Translate is very easy to use. The basic initialization is done automatically always from Core and therefore Addons don't have to care at all about this mechanism. In older addons that contain PHP files that need to be called directly from the outside, 2 to a maximum of 4 Translate methods need to be called (all commands are given in the form of standalone). Condition for the use of Translate is that the file framework/initialize.php
has been loaded (included) already:
Even simpler with add-on files that are called Core-controlled: Here the addon is already activated from the Core. Only the template and/or the theme must still be activated by the addon itself. The deactivation is performed automatically by the core.
Now basically the only thing left is actually to call the translated texts by Translate. The easiest way is:
<php> $sText = Translate::getInstance()→TEXT_CANCEL; </php> (corresponds to the former <php> $sText = $GLOBALS['TEXT']['CANCEL']; </php>)
Temporarily for older Addons a method exists that allows to pass all translation texts in one rushto the phplib Template Engine:
<php> $template→set_var(Translate::getInstance()→getLangArray()); </php> in the template the texts are inserted with {TEXT_CANCEL}
.
The problem with this method is that always a complete copy of the translation table is passed to the Template Engine.
Much easier and less space is used in conjunction with Twig, since only a memory-saving reference is passed to the Translate object:
<php> $aTwigData['Trans'] = Translate::getInstance(); </php> - in order to display it in the template use {{ Trans.TEXT_CANCEL }}