Language.php 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. <?php
  2. /**
  3. * Represents a language and defines localizable string formatting and
  4. * other functions, as well as the localized messages for HTML Purifier.
  5. */
  6. class HTMLPurifier_Language
  7. {
  8. /**
  9. * ISO 639 language code of language. Prefers shortest possible version
  10. */
  11. public $code = 'en';
  12. /**
  13. * Fallback language code
  14. */
  15. public $fallback = false;
  16. /**
  17. * Array of localizable messages
  18. */
  19. public $messages = array();
  20. /**
  21. * Array of localizable error codes
  22. */
  23. public $errorNames = array();
  24. /**
  25. * True if no message file was found for this language, so English
  26. * is being used instead. Check this if you'd like to notify the
  27. * user that they've used a non-supported language.
  28. */
  29. public $error = false;
  30. /**
  31. * Has the language object been loaded yet?
  32. * @todo Make it private, fix usage in HTMLPurifier_LanguageTest
  33. */
  34. public $_loaded = false;
  35. /**
  36. * Instances of HTMLPurifier_Config and HTMLPurifier_Context
  37. */
  38. protected $config, $context;
  39. public function __construct($config, $context) {
  40. $this->config = $config;
  41. $this->context = $context;
  42. }
  43. /**
  44. * Loads language object with necessary info from factory cache
  45. * @note This is a lazy loader
  46. */
  47. public function load() {
  48. if ($this->_loaded) return;
  49. $factory = HTMLPurifier_LanguageFactory::instance();
  50. $factory->loadLanguage($this->code);
  51. foreach ($factory->keys as $key) {
  52. $this->$key = $factory->cache[$this->code][$key];
  53. }
  54. $this->_loaded = true;
  55. }
  56. /**
  57. * Retrieves a localised message.
  58. * @param $key string identifier of message
  59. * @return string localised message
  60. */
  61. public function getMessage($key) {
  62. if (!$this->_loaded) $this->load();
  63. if (!isset($this->messages[$key])) return "[$key]";
  64. return $this->messages[$key];
  65. }
  66. /**
  67. * Retrieves a localised error name.
  68. * @param $int integer error number, corresponding to PHP's error
  69. * reporting
  70. * @return string localised message
  71. */
  72. public function getErrorName($int) {
  73. if (!$this->_loaded) $this->load();
  74. if (!isset($this->errorNames[$int])) return "[Error: $int]";
  75. return $this->errorNames[$int];
  76. }
  77. /**
  78. * Converts an array list into a string readable representation
  79. */
  80. public function listify($array) {
  81. $sep = $this->getMessage('Item separator');
  82. $sep_last = $this->getMessage('Item separator last');
  83. $ret = '';
  84. for ($i = 0, $c = count($array); $i < $c; $i++) {
  85. if ($i == 0) {
  86. } elseif ($i + 1 < $c) {
  87. $ret .= $sep;
  88. } else {
  89. $ret .= $sep_last;
  90. }
  91. $ret .= $array[$i];
  92. }
  93. return $ret;
  94. }
  95. /**
  96. * Formats a localised message with passed parameters
  97. * @param $key string identifier of message
  98. * @param $args Parameters to substitute in
  99. * @return string localised message
  100. * @todo Implement conditionals? Right now, some messages make
  101. * reference to line numbers, but those aren't always available
  102. */
  103. public function formatMessage($key, $args = array()) {
  104. if (!$this->_loaded) $this->load();
  105. if (!isset($this->messages[$key])) return "[$key]";
  106. $raw = $this->messages[$key];
  107. $subst = array();
  108. $generator = false;
  109. foreach ($args as $i => $value) {
  110. if (is_object($value)) {
  111. if ($value instanceof HTMLPurifier_Token) {
  112. // factor this out some time
  113. if (!$generator) $generator = $this->context->get('Generator');
  114. if (isset($value->name)) $subst['$'.$i.'.Name'] = $value->name;
  115. if (isset($value->data)) $subst['$'.$i.'.Data'] = $value->data;
  116. $subst['$'.$i.'.Compact'] =
  117. $subst['$'.$i.'.Serialized'] = $generator->generateFromToken($value);
  118. // a more complex algorithm for compact representation
  119. // could be introduced for all types of tokens. This
  120. // may need to be factored out into a dedicated class
  121. if (!empty($value->attr)) {
  122. $stripped_token = clone $value;
  123. $stripped_token->attr = array();
  124. $subst['$'.$i.'.Compact'] = $generator->generateFromToken($stripped_token);
  125. }
  126. $subst['$'.$i.'.Line'] = $value->line ? $value->line : 'unknown';
  127. }
  128. continue;
  129. } elseif (is_array($value)) {
  130. $keys = array_keys($value);
  131. if (array_keys($keys) === $keys) {
  132. // list
  133. $subst['$'.$i] = $this->listify($value);
  134. } else {
  135. // associative array
  136. // no $i implementation yet, sorry
  137. $subst['$'.$i.'.Keys'] = $this->listify($keys);
  138. $subst['$'.$i.'.Values'] = $this->listify(array_values($value));
  139. }
  140. continue;
  141. }
  142. $subst['$' . $i] = $value;
  143. }
  144. return strtr($raw, $subst);
  145. }
  146. }
  147. // vim: et sw=4 sts=4