Elgg  Version 1.11
Translator.php
Go to the documentation of this file.
1 <?php
2 namespace Elgg\I18n;
3 
11 class Translator {
12 
18  private $CONFIG;
19 
23  public function __construct() {
24  global $CONFIG;
25  $this->CONFIG = $CONFIG;
26  $this->defaultPath = dirname(dirname(dirname(dirname(__DIR__)))) . "/languages/";
27  }
28 
40  function translate($message_key, $args = array(), $language = "") {
41 
42 
43  static $CURRENT_LANGUAGE;
44 
45  // old param order is deprecated
46  if (!is_array($args)) {
48  'As of Elgg 1.8, the 2nd arg to elgg_echo() is an array of string replacements and the 3rd arg is the language.',
49  1.8
50  );
51 
52  $language = $args;
53  $args = array();
54  }
55 
56  if (!isset($this->CONFIG->translations)) {
57  // this means we probably had an exception before translations were initialized
58  $this->registerTranslations($this->defaultPath);
59  }
60 
61  if (!$CURRENT_LANGUAGE) {
62  $CURRENT_LANGUAGE = $this->getLanguage();
63  }
64  if (!$language) {
65  $language = $CURRENT_LANGUAGE;
66  }
67 
68  if (!isset($this->CONFIG->translations[$language])) {
69  // The language being requested is not the same as the language of the
70  // logged in user, so we will have to load it separately. (Most likely
71  // we're sending a notification and the recipient is using a different
72  // language than the logged in user.)
74  }
75 
76  if (isset($this->CONFIG->translations[$language][$message_key])) {
77  $string = $this->CONFIG->translations[$language][$message_key];
78  } else if (isset($this->CONFIG->translations["en"][$message_key])) {
79  $string = $this->CONFIG->translations["en"][$message_key];
80  _elgg_services()->logger->notice(sprintf('Missing %s translation for "%s" language key', $language, $message_key));
81  } else {
82  $string = $message_key;
83  _elgg_services()->logger->notice(sprintf('Missing English translation for "%s" language key', $message_key));
84  }
85 
86  // only pass through if we have arguments to allow backward compatibility
87  // with manual sprintf() calls.
88  if ($args) {
89  $string = vsprintf($string, $args);
90  }
91 
92  return $string;
93  }
94 
108  function addTranslation($country_code, $language_array) {
109 
110  if (!isset($this->CONFIG->translations)) {
111  $this->CONFIG->translations = array();
112  }
113 
114  $country_code = strtolower($country_code);
115  $country_code = trim($country_code);
116  if (is_array($language_array) && $country_code != "") {
117  if (sizeof($language_array) > 0) {
118  if (!isset($this->CONFIG->translations[$country_code])) {
119  $this->CONFIG->translations[$country_code] = $language_array;
120  } else {
121  $this->CONFIG->translations[$country_code] = $language_array + $this->CONFIG->translations[$country_code];
122  }
123  }
124  return true;
125  }
126  return false;
127  }
128 
134  function getCurrentLanguage() {
135  $language = $this->getLanguage();
136 
137  if (!$language) {
138  $language = 'en';
139  }
140 
141  return $language;
142  }
143 
149  function getLanguage() {
150  $url_lang = _elgg_services()->input->get('hl');
151  if ($url_lang) {
152  return $url_lang;
153  }
154 
155  $user = _elgg_services()->session->getLoggedInUser();
156  $language = false;
157 
158  if (($user) && ($user->language)) {
159  $language = $user->language;
160  }
161 
162  if ((!$language) && (isset($this->CONFIG->language)) && ($this->CONFIG->language)) {
163  $language = $this->CONFIG->language;
164  }
165 
166  if ($language) {
167  return $language;
168  }
169 
170  return false;
171  }
172 
176  function loadTranslations() {
177 
178 
179  if ($this->CONFIG->system_cache_enabled) {
180  $loaded = true;
181  $languages = array_unique(array('en', $this->getCurrentLanguage()));
182  foreach ($languages as $language) {
183  $data = elgg_load_system_cache("$language.lang");
184  if ($data) {
185  $this->addTranslation($language, unserialize($data));
186  } else {
187  $loaded = false;
188  }
189  }
190 
191  if ($loaded) {
192  $this->CONFIG->i18n_loaded_from_cache = true;
193  // this is here to force
194  $this->CONFIG->language_paths[$this->defaultPath] = true;
195  return;
196  }
197  }
198 
199  // load core translations from languages directory
200  $this->registerTranslations($this->defaultPath);
201  }
202 
203 
204 
214  function registerTranslations($path, $load_all = false) {
216 
217  // Make a note of this path just incase we need to register this language later
218  if (!isset($this->CONFIG->language_paths)) {
219  $this->CONFIG->language_paths = array();
220  }
221  $this->CONFIG->language_paths[$path] = true;
222 
223  // Get the current language based on site defaults and user preference
224  $current_language = $this->getCurrentLanguage();
225  _elgg_services()->logger->info("Translations loaded from: $path");
226 
227  // only load these files unless $load_all is true.
228  $load_language_files = array(
229  'en.php',
230  "$current_language.php"
231  );
232 
233  $load_language_files = array_unique($load_language_files);
234 
235  $handle = opendir($path);
236  if (!$handle) {
237  _elgg_services()->logger->error("Could not open language path: $path");
238  return false;
239  }
240 
241  $return = true;
242  while (false !== ($language = readdir($handle))) {
243  // ignore bad files
244  if (substr($language, 0, 1) == '.' || substr($language, -4) !== '.php') {
245  continue;
246  }
247 
248  if (in_array($language, $load_language_files) || $load_all) {
249  $result = include_once($path . $language);
250  if ($result === false) {
251  $return = false;
252  continue;
253  } elseif (is_array($result)) {
254  $this->addTranslation(basename($language, '.php'), $result);
255  }
256  }
257  }
258 
259  return $return;
260  }
261 
272 
273 
274  static $LANG_RELOAD_ALL_RUN;
275  if ($LANG_RELOAD_ALL_RUN) {
276  return;
277  }
278 
279  if ($this->CONFIG->i18n_loaded_from_cache) {
280  $cache = elgg_get_system_cache();
281  $cache_dir = $cache->getVariable("cache_path");
282  $filenames = elgg_get_file_list($cache_dir, array(), array(), array(".lang"));
283  foreach ($filenames as $filename) {
284  // Look for files matching for example 'en.lang', 'cmn.lang' or 'pt_br.lang'.
285  // Note that this regex is just for the system cache. The original language
286  // files are allowed to have uppercase letters (e.g. pt_BR.php).
287  if (preg_match('/(([a-z]{2,3})(_[a-z]{2})?)\.lang$/', $filename, $matches)) {
288  $language = $matches[1];
289  $data = elgg_load_system_cache("$language.lang");
290  if ($data) {
291  $this->addTranslation($language, unserialize($data));
292  }
293  }
294  }
295  } else {
296  foreach ($this->CONFIG->language_paths as $path => $dummy) {
297  $this->registerTranslations($path, true);
298  }
299  }
300 
301  $LANG_RELOAD_ALL_RUN = true;
302  }
303 
311 
312 
313  // Ensure that all possible translations are loaded
314  $this->reloadAllTranslations();
315 
316  $installed = array();
317 
318  $admin_logged_in = _elgg_services()->session->isAdminLoggedIn();
319 
320  foreach ($this->CONFIG->translations as $k => $v) {
321  $installed[$k] = $this->translate($k, array(), $k);
322  if ($admin_logged_in && ($k != 'en')) {
323  $completeness = $this->getLanguageCompleteness($k);
324  if ($completeness < 100) {
325  $installed[$k] .= " (" . $completeness . "% " . $this->translate('complete') . ")";
326  }
327  }
328  }
329 
330  return $installed;
331  }
332 
341 
342 
343  // Ensure that all possible translations are loaded
344  $this->reloadAllTranslations();
345 
347 
348  $en = count($this->CONFIG->translations['en']);
349 
350  $missing = $this->getMissingLanguageKeys($language);
351  if ($missing) {
352  $missing = count($missing);
353  } else {
354  $missing = 0;
355  }
356 
357  //$lang = count($this->CONFIG->translations[$language]);
358  $lang = $en - $missing;
359 
360  return round(($lang / $en) * 100, 2);
361  }
362 
372 
373 
374  // Ensure that all possible translations are loaded
375  $this->reloadAllTranslations();
376 
377  $missing = array();
378 
379  foreach ($this->CONFIG->translations['en'] as $k => $v) {
380  if ((!isset($this->CONFIG->translations[$language][$k]))
381  || ($this->CONFIG->translations[$language][$k] == $this->CONFIG->translations['en'][$k])) {
382  $missing[] = $k;
383  }
384  }
385 
386  if (count($missing)) {
387  return $missing;
388  }
389 
390  return false;
391  }
392 
402  function languageKeyExists($key, $language = 'en') {
403  if (empty($key)) {
404  return false;
405  }
406 
407  if (($language !== 'en') && !array_key_exists($language, $this->CONFIG->translations)) {
408  // Ensure that all possible translations are loaded
409  $this->reloadAllTranslations();
410  }
411 
412  if (!array_key_exists($language, $this->CONFIG->translations)) {
413  return false;
414  }
415 
416  return array_key_exists($key, $this->CONFIG->translations[$language]);
417  }
418 
424  function getAllLanguageCodes() {
425  return array(
426  "aa", // "Afar"
427  "ab", // "Abkhazian"
428  "af", // "Afrikaans"
429  "am", // "Amharic"
430  "ar", // "Arabic"
431  "as", // "Assamese"
432  "ay", // "Aymara"
433  "az", // "Azerbaijani"
434  "ba", // "Bashkir"
435  "be", // "Byelorussian"
436  "bg", // "Bulgarian"
437  "bh", // "Bihari"
438  "bi", // "Bislama"
439  "bn", // "Bengali; Bangla"
440  "bo", // "Tibetan"
441  "br", // "Breton"
442  "ca", // "Catalan"
443  "cmn", // "Mandarin Chinese" // ISO 639-3
444  "co", // "Corsican"
445  "cs", // "Czech"
446  "cy", // "Welsh"
447  "da", // "Danish"
448  "de", // "German"
449  "dz", // "Bhutani"
450  "el", // "Greek"
451  "en", // "English"
452  "eo", // "Esperanto"
453  "es", // "Spanish"
454  "et", // "Estonian"
455  "eu", // "Basque"
456  "fa", // "Persian"
457  "fi", // "Finnish"
458  "fj", // "Fiji"
459  "fo", // "Faeroese"
460  "fr", // "French"
461  "fy", // "Frisian"
462  "ga", // "Irish"
463  "gd", // "Scots / Gaelic"
464  "gl", // "Galician"
465  "gn", // "Guarani"
466  "gu", // "Gujarati"
467  "he", // "Hebrew"
468  "ha", // "Hausa"
469  "hi", // "Hindi"
470  "hr", // "Croatian"
471  "hu", // "Hungarian"
472  "hy", // "Armenian"
473  "ia", // "Interlingua"
474  "id", // "Indonesian"
475  "ie", // "Interlingue"
476  "ik", // "Inupiak"
477  "is", // "Icelandic"
478  "it", // "Italian"
479  "iu", // "Inuktitut"
480  "iw", // "Hebrew (obsolete)"
481  "ja", // "Japanese"
482  "ji", // "Yiddish (obsolete)"
483  "jw", // "Javanese"
484  "ka", // "Georgian"
485  "kk", // "Kazakh"
486  "kl", // "Greenlandic"
487  "km", // "Cambodian"
488  "kn", // "Kannada"
489  "ko", // "Korean"
490  "ks", // "Kashmiri"
491  "ku", // "Kurdish"
492  "ky", // "Kirghiz"
493  "la", // "Latin"
494  "ln", // "Lingala"
495  "lo", // "Laothian"
496  "lt", // "Lithuanian"
497  "lv", // "Latvian/Lettish"
498  "mg", // "Malagasy"
499  "mi", // "Maori"
500  "mk", // "Macedonian"
501  "ml", // "Malayalam"
502  "mn", // "Mongolian"
503  "mo", // "Moldavian"
504  "mr", // "Marathi"
505  "ms", // "Malay"
506  "mt", // "Maltese"
507  "my", // "Burmese"
508  "na", // "Nauru"
509  "ne", // "Nepali"
510  "nl", // "Dutch"
511  "no", // "Norwegian"
512  "oc", // "Occitan"
513  "om", // "(Afan) Oromo"
514  "or", // "Oriya"
515  "pa", // "Punjabi"
516  "pl", // "Polish"
517  "ps", // "Pashto / Pushto"
518  "pt", // "Portuguese"
519  "pt_br", // 'Brazilian Portuguese'
520  "qu", // "Quechua"
521  "rm", // "Rhaeto-Romance"
522  "rn", // "Kirundi"
523  "ro", // "Romanian"
524  "ru", // "Russian"
525  "rw", // "Kinyarwanda"
526  "sa", // "Sanskrit"
527  "sd", // "Sindhi"
528  "sg", // "Sangro"
529  "sh", // "Serbo-Croatian"
530  "si", // "Singhalese"
531  "sk", // "Slovak"
532  "sl", // "Slovenian"
533  "sm", // "Samoan"
534  "sn", // "Shona"
535  "so", // "Somali"
536  "sq", // "Albanian"
537  "sr", // "Serbian"
538  "ss", // "Siswati"
539  "st", // "Sesotho"
540  "su", // "Sundanese"
541  "sv", // "Swedish"
542  "sw", // "Swahili"
543  "ta", // "Tamil"
544  "te", // "Tegulu"
545  "tg", // "Tajik"
546  "th", // "Thai"
547  "ti", // "Tigrinya"
548  "tk", // "Turkmen"
549  "tl", // "Tagalog"
550  "tn", // "Setswana"
551  "to", // "Tonga"
552  "tr", // "Turkish"
553  "ts", // "Tsonga"
554  "tt", // "Tatar"
555  "tw", // "Twi"
556  "ug", // "Uigur"
557  "uk", // "Ukrainian"
558  "ur", // "Urdu"
559  "uz", // "Uzbek"
560  "vi", // "Vietnamese"
561  "vo", // "Volapuk"
562  "wo", // "Wolof"
563  "xh", // "Xhosa"
564  "yi", // "Yiddish"
565  "yo", // "Yoruba"
566  "za", // "Zuang"
567  "zh", // "Chinese"
568  "zu", // "Zulu"
569  );
570  }
571 
572 }
getInstalledTranslations()
Return an array of installed translations as an associative array "two letter code" => "native langua...
Definition: Translator.php:310
_elgg_load_translations_for_language($language)
Load both core and plugin translations for a specific language.
Definition: languages.php:74
$lang
Definition: html.php:12
sanitise_filepath($path, $append_slash=true)
Sanitise file paths ensuring that they begin and end with slashes etc.
Definition: elgglib.php:368
elgg_get_system_cache()
Returns an object suitable for caching system information.
Definition: cache.php:20
$data
Definition: opendd.php:13
$return
Definition: opendd.php:15
$args
Some servers don&#39;t allow PHP to check the rewrite, so try via AJAX.
$string
getMissingLanguageKeys($language)
Return the translation keys missing from a given language, or those that are identical to the english...
Definition: Translator.php:371
getAllLanguageCodes()
Returns an array of language codes.
Definition: Translator.php:424
WARNING: API IN FLUX.
Definition: Translator.php:11
addTranslation($country_code, $language_array)
Add a translation.
Definition: Translator.php:108
elgg_get_file_list($directory, $exceptions=array(), $list=array(), $extensions=null)
Returns a list of files in $directory.
Definition: elgglib.php:336
reloadAllTranslations()
Reload all translations from all registered paths.
Definition: Translator.php:271
$key
Definition: summary.php:34
registerTranslations($path, $load_all=false)
When given a full path, finds translation files and loads them.
Definition: Translator.php:214
_elgg_services()
Definition: autoloader.php:14
loadTranslations()
private
Definition: Translator.php:176
sanitise_string($string)
Wrapper function for alternate English spelling (.
Definition: database.php:150
$user
Definition: ban.php:13
elgg_deprecated_notice($msg, $dep_version, $backtrace_level=1)
Log a notice about deprecated use of a function, view, etc.
Definition: elgglib.php:1006
elgg global
Pointer to the global context.
Definition: elgglib.js:12
getCurrentLanguage()
Detect the current language being used by the current site or logged in user.
Definition: Translator.php:134
getLanguageCompleteness($language)
Return the level of completeness for a given language code (compared to english)
Definition: Translator.php:340
elgg_load_system_cache($type)
Retrieve the contents of a system cache.
Definition: cache.php:50
translate($message_key, $args=array(), $language="")
Given a message key, returns an appropriately translated full-text string.
Definition: Translator.php:40
languageKeyExists($key, $language= 'en')
Check if a give language key exists.
Definition: Translator.php:402
__construct()
Initializes new translator.
Definition: Translator.php:23
$filename
Definition: crop.php:23
$language
$vars[&#39;language&#39;]
Definition: languages.php:6
getLanguage()
Gets the current language in use by the system or user.
Definition: Translator.php:149
$path
Definition: invalid.php:17
foreach(array('sitename','sitedescription', 'siteemail', 'default_limit') as $field) $languages