Translations of messages in different languages
Located in /program/lib/language.class.php (line 33)
constructor
Set up the instance of this class. If no default domain is specified, 'was' is used. We always read the current list of all languages into core, for future reference.
return an array with active languages and language names
this returns an array with language_key => language_name pairs, one entry per active language, ordered by language name. This array can be used in language picklists or to translate a language key to readable form. Note that we use the name of a language expressed in the language itself.
determine the default language to use for translation of phrases
This routine determines which language to use for prompts and messages if not specified explicitly in calls to $this->get_phrase(). There are various ways in which a language can be determined. Here's the list, in order of significance:
calculate an ordered list of filenames to try for translation of phrases
WAS uses a separate language file for every text domain; basically the name of the text domain is the name of the file without the .php-extension. However, in order to prevent name clashes, modules and themes and addons have their own prefix: 'm_' for modules and 't_' for themes and 'a_' for addons.
The language translations for the installer are based on more or less the same trick: the prefix 'i_' identifies files in the directory /program/install/languages.
This trick with prefixing leads to the following search orders for generic phrases and module-, theme- and addon-specific phrases.
Example 1: phrases with $domain='login': {$CFG->progdir}/languages/{$language_key}/login.php {$CFG->datadir}/languages/{$language_key}/login.php
Example 2: phrases with $domain='m_guestbook': {$CFG->progdir}/modules/guestbook/languages/{$language_key}/guestbook.php {$CFG->progdir}/languages/{$language_key}/m_guestbook.php {$CFG->datadir}/languages/{$language_key}/m_guestbook.php
Example 3: phrases with $domain='login' and a hint in $location_hint: {$location_hint}/{$language_key}/login.php {$CFG->datadir}/languages/{$language_key}/login.php
Example 4: phrases with $domain='m_guestbook' and a hint in $location_hint: {$location_hint}/{$language_key}/guestbook.php {$location_hint}/{$language_key}/m_guestbook.php {$CFG->datadir}/languages/{$language_key}/m_guestbook.php
Example 5: phrases with $domain='i_demodata': {$CFG->progdir}/install/languages/{$language_key}/demodata.php {$CFG->datadir}/languages/{$language_key}/i_demodata.php
calculate a list of possible languages and parent-languages to try for translations
This constructs an array with all ancestors (=parent languages) of $language_key and English if that language was not yet added.
translation of phrases via a phrase key
This routine looks up the text associated with the phrase key. If no domain is specified, the domain 'was' is tried. If no valid language is specified, the current language is used. If a location hint is specified, we trust the caller knows best where to look and we try locating a translations file in that directory location first.
Note that phrases in a particular language which are found later in the search overwrite the phrases found earlier. These additional phrases (dubbed 'dialect' or 'userdefined translations') can be used to overwrite or correct existing standard ('official') translations. These dialect phrases can be stored in a file in the languages subdirectory of the data directory (writable for the web server but hopefully outside the document root) and/or in the table 'phrases' in the database.
Whether these dialect phrases are actually fetched from disk or database depends on the configuration of the language, via the boolean fields 'dialect_in_database' and 'dialect_in_file'; if the corresponding switch is not TRUE, we don't even bother to go and look, which saves time.
Finally, if a particular phrase is not found in the requested language, we recursively try the parent language(s) of the requested language until there are no more parents. After that, we go for the 'en' translation. If that fails too, we return the phrase_key itself, sandwiched between the strings '(lang) ' and ' (/lang)', where 'lang' is the requested language code. Of course this should not happen if all translations are correct. (Famous last words...)
If a translation is found, we replace all occurences of the keys in the array 'replace' in the translation with the corresponding values. This is done via a simple search and replace rather than a printf()-like way or (shudder) with complicated regex'es.
Note that we store search results in the array $this->phrases so we can re-use those phrases in a next call. We cache the results on a per-domain basis, based on the assumption that after the first phrase in a particular domain is requested, it is likely that more phrases in the same domain will be requested.
Note that the resulting phrases are cached using the original language as the key (in $this->phrases). This means that if a phrase in say 'de' or 'fr' was not found and 'en' was used instead, the English phrases are cached in the 'de' or 'fr' branch of the static array. This saves us time on the next call because we then use the phrases in the substitute language right away instead of going to look everywhere everytime.
Translations are fetched in such a way that the user-defined translations ('dialect') prevail over the system-defined ('official') translations. However, attempts to look for a phrase in a parent language (or 'en') only add the missing translations, preserving the translations in this full_domain that were already found. Quick illustration with Dutch (nl) and English (en): search order is: $nl_database, $nl_userfile, $nl_system, $en_database, $en_userfile, $en_system. The 'en' translations are only used if no corresponding Dutch translation is found. However, the English 'dialect' prevails over the English 'system' translation.
Examples of typical use of this routine:
retrieve phrases from the database for specified domain and language
return the $string array after including a file
This includes the specified language file $filename (if it exists) and returns the array $string. This assumes that filename actually consists of lines like this:
Because the file is included within the context of this function, the contents are added to the local array $string rather than some global array. This is a feature.
Note that the included file MUST name the array '$string' because otherwise this function will return an empty array. This means that any 'old' Site@School language files must be manipulated before they can be re-used. I'd consider this a feature too.
remove selected entries (per language+domain, per language, or all) from cache
retrieve an array with all active languages from the database
This reads all languages from the database. If there's nothing there, we still return an array with a single element for the English language 'en', because 'en' is the native language of this program. If the language 'en' was not found, we still add it to the array. The resulting array is usually sorted by language name.
Documentation generated on Tue, 28 Jun 2016 19:10:04 +0200 by phpDocumentor 1.4.0