ILIAS  release_5-4 Revision v5.4.26-12-gabc799a52e6
Translate.php
Go to the documentation of this file.
1 <?php
2 
11 namespace SimpleSAML\Locale;
12 
13 class Translate
14 {
15 
21  private $configuration;
22 
23  private $langtext = array();
24 
28  private $dictionaries = array();
29 
33  private $defaultDictionary = null;
34 
40  private $language;
41 
42 
50  {
51  $this->configuration = $configuration;
52  $this->language = new Language($configuration);
53 
54  if ($defaultDictionary !== null && substr($defaultDictionary, -4) === '.php') {
55  // TODO: drop this entire if clause for 2.0
56  // for backwards compatibility - print warning
57  $backtrace = debug_backtrace();
58  $where = $backtrace[0]['file'].':'.$backtrace[0]['line'];
60  'Deprecated use of new SimpleSAML\Locale\Translate(...) at '.$where.
61  '. The last parameter is now a dictionary name, which should not end in ".php".'
62  );
63 
64  $this->defaultDictionary = substr($defaultDictionary, 0, -4);
65  } else {
66  $this->defaultDictionary = $defaultDictionary;
67  }
68  }
69 
70 
76  public function getLanguage()
77  {
78  return $this->language;
79  }
80 
81 
90  private function getDictionary($name)
91  {
92  assert(is_string($name));
93 
94  if (!array_key_exists($name, $this->dictionaries)) {
95  $sepPos = strpos($name, ':');
96  if ($sepPos !== false) {
97  $module = substr($name, 0, $sepPos);
98  $fileName = substr($name, $sepPos + 1);
99  $dictDir = \SimpleSAML\Module::getModuleDir($module).'/dictionaries/';
100  } else {
101  $dictDir = $this->configuration->getPathValue('dictionarydir', 'dictionaries/');
102  $fileName = $name;
103  }
104 
105  $this->dictionaries[$name] = $this->readDictionaryFile($dictDir.$fileName);
106  }
107 
108  return $this->dictionaries[$name];
109  }
110 
111 
120  public function getTag($tag)
121  {
122  assert(is_string($tag));
123 
124  // first check translations loaded by the includeInlineTranslation and includeLanguageFile methods
125  if (array_key_exists($tag, $this->langtext)) {
126  return $this->langtext[$tag];
127  }
128 
129  // check whether we should use the default dictionary or a dictionary specified in the tag
130  if (substr($tag, 0, 1) === '{' && preg_match('/^{((?:\w+:)?\w+?):(.*)}$/D', $tag, $matches)) {
131  $dictionary = $matches[1];
132  $tag = $matches[2];
133  } else {
134  $dictionary = $this->defaultDictionary;
135  if ($dictionary === null) {
136  // we don't have any dictionary to load the tag from
137  return null;
138  }
139  }
140 
141  $dictionary = $this->getDictionary($dictionary);
142  if (!array_key_exists($tag, $dictionary)) {
143  return null;
144  }
145 
146  return $dictionary[$tag];
147  }
148 
149 
159  public function getPreferredTranslation($translations)
160  {
161  assert(is_array($translations));
162 
163  // look up translation of tag in the selected language
164  $selected_language = $this->language->getLanguage();
165  if (array_key_exists($selected_language, $translations)) {
166  return $translations[$selected_language];
167  }
168 
169  // look up translation of tag in the default language
170  $default_language = $this->language->getDefaultLanguage();
171  if (array_key_exists($default_language, $translations)) {
172  return $translations[$default_language];
173  }
174 
175  // check for english translation
176  if (array_key_exists('en', $translations)) {
177  return $translations['en'];
178  }
179 
180  // pick the first translation available
181  if (count($translations) > 0) {
182  $languages = array_keys($translations);
183  return $translations[$languages[0]];
184  }
185 
186  // we don't have anything to return
187  throw new \Exception('Nothing to return from translation.');
188  }
189 
190 
199  {
200  // normalize attribute name
201  $normName = strtolower($name);
202  $normName = str_replace(":", "_", $normName);
203 
204  // check for an extra dictionary
205  $extraDict = $this->configuration->getString('attributes.extradictionary', null);
206  if ($extraDict !== null) {
207  $dict = $this->getDictionary($extraDict);
208  if (array_key_exists($normName, $dict)) {
209  return $this->getPreferredTranslation($dict[$normName]);
210  }
211  }
212 
213  // search the default attribute dictionary
214  $dict = $this->getDictionary('attributes');
215  if (array_key_exists('attribute_'.$normName, $dict)) {
216  return $this->getPreferredTranslation($dict['attribute_'.$normName]);
217  }
218 
219  // no translations found
220  return $name;
221  }
222 
223 
231  public static function noop($tag)
232  {
233  return $tag;
234  }
235 
236 
259  public function t(
260  $tag,
261  $replacements = array(),
262  // TODO: remove this for 2.0. Assume true
263  $fallbackdefault = true,
264  // TODO: remove this for 2.0
265  $oldreplacements = array(),
266  // TODO: remove this for 2.0
267  $striptags = false
268  ) {
269  $backtrace = debug_backtrace();
270  $where = $backtrace[0]['file'].':'.$backtrace[0]['line'];
271  if (!$fallbackdefault) {
273  'Deprecated use of new SimpleSAML\Locale\Translate::t(...) at '.$where.
274  '. This parameter will go away, the fallback will become' .
275  ' identical to the $tag in 2.0.'
276  );
277  }
278  if (!is_array($replacements)) {
279  // TODO: remove this entire if for 2.0
280 
281  // old style call to t(...). Print warning to log
283  'Deprecated use of SimpleSAML\Locale\Translate::t(...) at '.$where.
284  '. Please update the code to use the new style of parameters.'
285  );
286 
287  // for backwards compatibility
288  if (!$replacements && $this->getTag($tag) === null) {
290  'Code which uses $fallbackdefault === FALSE should be updated to use the getTag() method instead.'
291  );
292  return null;
293  }
294 
295  $replacements = $oldreplacements;
296  }
297 
298  if (is_array($tag)) {
299  $tagData = $tag;
301  'Deprecated use of new SimpleSAML\Locale\Translate::t(...) at '.$where.
302  '. The $tag-parameter can only be a string in 2.0.'
303  );
304  } else {
305  $tagData = $this->getTag($tag);
306  if ($tagData === null) {
307  // tag not found
308  \SimpleSAML\Logger::info('Template: Looking up ['.$tag.']: not translated at all.');
309  return $this->getStringNotTranslated($tag, $fallbackdefault);
310  }
311  }
312 
313  $translated = $this->getPreferredTranslation($tagData);
314 
315  foreach ($replacements as $k => $v) {
316  // try to translate if no replacement is given
317  if ($v == null) {
318  $v = $this->t($k);
319  }
320  $translated = str_replace($k, $v, $translated);
321  }
322  return $translated;
323  }
324 
325 
335  private function getStringNotTranslated($tag, $fallbacktag)
336  {
337  if ($fallbacktag) {
338  return 'not translated ('.$tag.')';
339  } else {
340  return $tag;
341  }
342  }
343 
344 
355  public function includeInlineTranslation($tag, $translation)
356  {
357  if (is_string($translation)) {
358  $translation = array('en' => $translation);
359  } elseif (!is_array($translation)) {
360  throw new \Exception("Inline translation should be string or array. Is ".gettype($translation)." now!");
361  }
362 
363  \SimpleSAML\Logger::debug('Template: Adding inline language translation for tag ['.$tag.']');
364  $this->langtext[$tag] = $translation;
365  }
366 
367 
377  public function includeLanguageFile($file, $otherConfig = null)
378  {
379  if (!empty($otherConfig)) {
380  $filebase = $otherConfig->getPathValue('dictionarydir', 'dictionaries/');
381  } else {
382  $filebase = $this->configuration->getPathValue('dictionarydir', 'dictionaries/');
383  }
384 
385  $lang = $this->readDictionaryFile($filebase.$file);
386  \SimpleSAML\Logger::debug('Template: Merging language array. Loading ['.$file.']');
387  $this->langtext = array_merge($this->langtext, $lang);
388  }
389 
390 
398  private function readDictionaryJSON($filename)
399  {
400  $definitionFile = $filename.'.definition.json';
401  assert(file_exists($definitionFile));
402 
403  $fileContent = file_get_contents($definitionFile);
404  $lang = json_decode($fileContent, true);
405 
406  if (empty($lang)) {
407  \SimpleSAML\Logger::error('Invalid dictionary definition file ['.$definitionFile.']');
408  return array();
409  }
410 
411  $translationFile = $filename.'.translation.json';
412  if (file_exists($translationFile)) {
413  $fileContent = file_get_contents($translationFile);
414  $moreTrans = json_decode($fileContent, true);
415  if (!empty($moreTrans)) {
416  $lang = array_merge_recursive($lang, $moreTrans);
417  }
418  }
419 
420  return $lang;
421  }
422 
423 
431  private function readDictionaryPHP($filename)
432  {
433  $phpFile = $filename.'.php';
434  assert(file_exists($phpFile));
435 
436  $lang = null;
437  include($phpFile);
438  if (isset($lang)) {
439  return $lang;
440  }
441 
442  return array();
443  }
444 
445 
453  private function readDictionaryFile($filename)
454  {
455  assert(is_string($filename));
456 
457  \SimpleSAML\Logger::debug('Template: Reading ['.$filename.']');
458 
459  $jsonFile = $filename.'.definition.json';
460  if (file_exists($jsonFile)) {
461  return $this->readDictionaryJSON($filename);
462  }
463 
464  $phpFile = $filename.'.php';
465  if (file_exists($phpFile)) {
466  return $this->readDictionaryPHP($filename);
467  }
468 
470  $_SERVER['PHP_SELF'].' - Template: Could not find dictionary file at ['.$filename.']'
471  );
472  return array();
473  }
474 
475 
476  public static function translateSingularGettext($original)
477  {
478  $text = \Gettext\BaseTranslator::$current->gettext($original);
479 
480  if (func_num_args() === 1) {
481  return $text;
482  }
483 
484  $args = array_slice(func_get_args(), 1);
485 
486  return strtr($text, is_array($args[0]) ? $args[0] : $args);
487  }
488 
489 
490  public static function translatePluralGettext($original, $plural, $value)
491  {
492  $text = \Gettext\BaseTranslator::$current->ngettext($original, $plural, $value);
493 
494  if (func_num_args() === 3) {
495  return $text;
496  }
497 
498  $args = array_slice(func_get_args(), 3);
499 
500  return strtr($text, is_array($args[0]) ? $args[0] : $args);
501  }
502 
503 
515  public static function translateFromArray($context, $translations)
516  {
517  if (!is_array($translations) || $translations === null) {
518  return null;
519  }
520 
521  if (!is_array($context) || !isset($context['currentLanguage'])) {
522  return null;
523  }
524 
525  if (isset($translations[$context['currentLanguage']])) {
526  return $translations[$context['currentLanguage']];
527  }
528 
529  // we don't have a translation for the current language, load alternative priorities
531  $langcfg = $sspcfg->getConfigItem('language', null);
532  $priorities = array();
533  if ($langcfg instanceof \SimpleSAML_Configuration) {
534  $priorities = $langcfg->getArray('priorities', array());
535  }
536 
537  foreach ($priorities[$context['currentLanguage']] as $lang) {
538  if (isset($translations[$lang])) {
539  return $translations[$lang];
540  }
541  }
542 
543  // nothing we can use, return null so that we can set a default
544  return null;
545  }
546 }
if((!isset($_SERVER['DOCUMENT_ROOT'])) OR(empty($_SERVER['DOCUMENT_ROOT']))) $_SERVER['DOCUMENT_ROOT']
$dictionaries
Associative array of dictionaries.
Definition: Translate.php:28
$context
Definition: webdav.php:25
static noop($tag)
Mark a string for translation without translating it.
Definition: Translate.php:231
static debug($string)
Definition: Logger.php:211
readDictionaryJSON($filename)
Read a dictionary file in JSON format.
Definition: Translate.php:398
static getModuleDir($module)
Retrieve the base directory for a module.
Definition: Module.php:39
$defaultDictionary
The default dictionary.
Definition: Translate.php:33
includeInlineTranslation($tag, $translation)
Include a translation inline instead of putting translations in dictionaries.
Definition: Translate.php:355
if($modEnd===false) $module
Definition: module.php:59
static translateSingularGettext($original)
Definition: Translate.php:476
getStringNotTranslated($tag, $fallbacktag)
Return the string that should be used when no translation was found.
Definition: Translate.php:335
readDictionaryPHP($filename)
Read a dictionary file in PHP format.
Definition: Translate.php:431
static translatePluralGettext($original, $plural, $value)
Definition: Translate.php:490
static info($string)
Definition: Logger.php:199
getPreferredTranslation($translations)
Retrieve the preferred translation of a given text.
Definition: Translate.php:159
includeLanguageFile($file, $otherConfig=null)
Include a language file from the dictionaries directory.
Definition: Translate.php:377
static warning($string)
Definition: Logger.php:177
__construct(\SimpleSAML_Configuration $configuration, $defaultDictionary=null)
Constructor.
Definition: Translate.php:49
$text
Definition: errorreport.php:18
t( $tag, $replacements=array(), $fallbackdefault=true, $oldreplacements=array(), $striptags=false)
Translate a tag into the current language, with a fallback to english.
Definition: Translate.php:259
getTag($tag)
This method retrieves a tag as an array with language => string mappings.
Definition: Translate.php:120
static error($string)
Definition: Logger.php:166
readDictionaryFile($filename)
Read a dictionary file.
Definition: Translate.php:453
$filename
Definition: buildRTE.php:89
getDictionary($name)
This method retrieves a dictionary with the name given.
Definition: Translate.php:90
for($i=1; $i<=count($kw_cases_sel); $i+=1) $lang
Definition: langwiz.php:349
$languages
Definition: cssgen2.php:34
if(function_exists('posix_getuid') &&posix_getuid()===0) if(!array_key_exists('t', $options)) $tag
Definition: cron.php:35
static getInstance($instancename='simplesaml')
Get a configuration file by its instance name.
getAttributeTranslation($name)
Translate the name of an attribute.
Definition: Translate.php:198
static translateFromArray($context, $translations)
Pick a translation from a given array of translations for the current language.
Definition: Translate.php:515
getLanguage()
Return the internal language object used by this translator.
Definition: Translate.php:76