ILIAS  release_5-3 Revision v5.3.23-19-g915713cf615
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  $fallbackdefault = true, // TODO: remove this for 2.0. Assume true
263  $oldreplacements = array(), // TODO: remove this for 2.0
264  $striptags = false // TODO: remove this for 2.0
265  ) {
266  $backtrace = debug_backtrace();
267  $where = $backtrace[0]['file'].':'.$backtrace[0]['line'];
268  if (!$fallbackdefault) {
270  'Deprecated use of new SimpleSAML\Locale\Translate::t(...) at '.$where.
271  '. This parameter will go away, the fallback will become' .
272  ' identical to the $tag in 2.0.'
273  );
274  }
275  if (!is_array($replacements)) {
276  // TODO: remove this entire if for 2.0
277 
278  // old style call to t(...). Print warning to log
280  'Deprecated use of SimpleSAML\Locale\Translate::t(...) at '.$where.
281  '. Please update the code to use the new style of parameters.'
282  );
283 
284  // for backwards compatibility
285  if (!$replacements && $this->getTag($tag) === null) {
287  'Code which uses $fallbackdefault === FALSE should be updated to use the getTag() method instead.'
288  );
289  return null;
290  }
291 
292  $replacements = $oldreplacements;
293  }
294 
295  if (is_array($tag)) {
296  $tagData = $tag;
298  'Deprecated use of new SimpleSAML\Locale\Translate::t(...) at '.$where.
299  '. The $tag-parameter can only be a string in 2.0.'
300  );
301  } else {
302  $tagData = $this->getTag($tag);
303  if ($tagData === null) {
304  // tag not found
305  \SimpleSAML\Logger::info('Template: Looking up ['.$tag.']: not translated at all.');
306  return $this->getStringNotTranslated($tag, $fallbackdefault);
307  }
308  }
309 
310  $translated = $this->getPreferredTranslation($tagData);
311 
312  foreach ($replacements as $k => $v) {
313  // try to translate if no replacement is given
314  if ($v == null) {
315  $v = $this->t($k);
316  }
317  $translated = str_replace($k, $v, $translated);
318  }
319  return $translated;
320  }
321 
322 
332  private function getStringNotTranslated($tag, $fallbacktag)
333  {
334  if ($fallbacktag) {
335  return 'not translated ('.$tag.')';
336  } else {
337  return $tag;
338  }
339  }
340 
341 
352  public function includeInlineTranslation($tag, $translation)
353  {
354  if (is_string($translation)) {
355  $translation = array('en' => $translation);
356  } elseif (!is_array($translation)) {
357  throw new \Exception("Inline translation should be string or array. Is ".gettype($translation)." now!");
358  }
359 
360  \SimpleSAML\Logger::debug('Template: Adding inline language translation for tag ['.$tag.']');
361  $this->langtext[$tag] = $translation;
362  }
363 
364 
374  public function includeLanguageFile($file, $otherConfig = null)
375  {
376  if (!empty($otherConfig)) {
377  $filebase = $otherConfig->getPathValue('dictionarydir', 'dictionaries/');
378  } else {
379  $filebase = $this->configuration->getPathValue('dictionarydir', 'dictionaries/');
380  }
381 
382  $lang = $this->readDictionaryFile($filebase.$file);
383  \SimpleSAML\Logger::debug('Template: Merging language array. Loading ['.$file.']');
384  $this->langtext = array_merge($this->langtext, $lang);
385  }
386 
387 
395  private function readDictionaryJSON($filename)
396  {
397  $definitionFile = $filename.'.definition.json';
398  assert('file_exists($definitionFile)');
399 
400  $fileContent = file_get_contents($definitionFile);
401  $lang = json_decode($fileContent, true);
402 
403  if (empty($lang)) {
404  \SimpleSAML\Logger::error('Invalid dictionary definition file ['.$definitionFile.']');
405  return array();
406  }
407 
408  $translationFile = $filename.'.translation.json';
409  if (file_exists($translationFile)) {
410  $fileContent = file_get_contents($translationFile);
411  $moreTrans = json_decode($fileContent, true);
412  if (!empty($moreTrans)) {
413  $lang = array_merge_recursive($lang, $moreTrans);
414  }
415  }
416 
417  return $lang;
418  }
419 
420 
428  private function readDictionaryPHP($filename)
429  {
430  $phpFile = $filename.'.php';
431  assert('file_exists($phpFile)');
432 
433  $lang = null;
434  include($phpFile);
435  if (isset($lang)) {
436  return $lang;
437  }
438 
439  return array();
440  }
441 
442 
450  private function readDictionaryFile($filename)
451  {
452  assert('is_string($filename)');
453 
454  \SimpleSAML\Logger::debug('Template: Reading ['.$filename.']');
455 
456  $jsonFile = $filename.'.definition.json';
457  if (file_exists($jsonFile)) {
458  return $this->readDictionaryJSON($filename);
459  }
460 
461  $phpFile = $filename.'.php';
462  if (file_exists($phpFile)) {
463  return $this->readDictionaryPHP($filename);
464  }
465 
467  $_SERVER['PHP_SELF'].' - Template: Could not find dictionary file at ['.$filename.']'
468  );
469  return array();
470  }
471 
472 
473  public static function translateSingularGettext($original)
474  {
475  $text = \Gettext\BaseTranslator::$current->gettext($original);
476 
477  if (func_num_args() === 1) {
478  return $text;
479  }
480 
481  $args = array_slice(func_get_args(), 1);
482 
483  return strtr($text, is_array($args[0]) ? $args[0] : $args);
484  }
485 
486 
487  public static function translatePluralGettext($original, $plural, $value)
488  {
489  $text = \Gettext\BaseTranslator::$current->ngettext($original, $plural, $value);
490 
491  if (func_num_args() === 3) {
492  return $text;
493  }
494 
495  $args = array_slice(func_get_args(), 3);
496 
497  return strtr($text, is_array($args[0]) ? $args[0] : $args);
498  }
499 }
if((!isset($_SERVER['DOCUMENT_ROOT'])) OR(empty($_SERVER['DOCUMENT_ROOT']))) $_SERVER['DOCUMENT_ROOT']
$dictionaries
Associative array of dictionaries.
Definition: Translate.php:28
static noop($tag)
Mark a string for translation without translating it.
Definition: Translate.php:231
static debug($string)
Definition: Logger.php:213
readDictionaryJSON($filename)
Read a dictionary file in JSON format.
Definition: Translate.php:395
static getModuleDir($module)
Retrieve the base directory for a module.
Definition: Module.php:122
$defaultDictionary
The default dictionary.
Definition: Translate.php:33
includeInlineTranslation($tag, $translation)
Include a translation inline instead of putting translations in dictionaries.
Definition: Translate.php:352
if($modEnd===false) $module
Definition: module.php:59
static translateSingularGettext($original)
Definition: Translate.php:473
getStringNotTranslated($tag, $fallbacktag)
Return the string that should be used when no translation was found.
Definition: Translate.php:332
readDictionaryPHP($filename)
Read a dictionary file in PHP format.
Definition: Translate.php:428
static translatePluralGettext($original, $plural, $value)
Definition: Translate.php:487
if($format !==null) $name
Definition: metadata.php:146
static info($string)
Definition: Logger.php:201
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:374
static warning($string)
Definition: Logger.php:179
__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:168
readDictionaryFile($filename)
Read a dictionary file.
Definition: Translate.php:450
Create styles array
The data for the language used.
getDictionary($name)
This method retrieves a dictionary with the name given.
Definition: Translate.php:90
if(!file_exists("$old.txt")) if($old===$new) if(file_exists("$new.txt")) $file
if(function_exists('posix_getuid') &&posix_getuid()===0) if(!array_key_exists('t', $options)) $tag
Definition: cron.php:35
getAttributeTranslation($name)
Translate the name of an attribute.
Definition: Translate.php:198
getLanguage()
Return the internal language object used by this translator.
Definition: Translate.php:76