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