15 var $headers = array(); |
15 var $headers = array(); |
16 |
16 |
17 /** |
17 /** |
18 * Add entry to the PO structure |
18 * Add entry to the PO structure |
19 * |
19 * |
20 * @param object &$entry |
20 * @param array|Translation_Entry &$entry |
21 * @return bool true on success, false if the entry doesn't have a key |
21 * @return bool true on success, false if the entry doesn't have a key |
22 */ |
22 */ |
23 function add_entry($entry) { |
23 function add_entry($entry) { |
24 if (is_array($entry)) { |
24 if (is_array($entry)) { |
25 $entry = new Translation_Entry($entry); |
25 $entry = new Translation_Entry($entry); |
28 if (false === $key) return false; |
28 if (false === $key) return false; |
29 $this->entries[$key] = &$entry; |
29 $this->entries[$key] = &$entry; |
30 return true; |
30 return true; |
31 } |
31 } |
32 |
32 |
|
33 /** |
|
34 * @param array|Translation_Entry $entry |
|
35 * @return bool |
|
36 */ |
33 function add_entry_or_merge($entry) { |
37 function add_entry_or_merge($entry) { |
34 if (is_array($entry)) { |
38 if (is_array($entry)) { |
35 $entry = new Translation_Entry($entry); |
39 $entry = new Translation_Entry($entry); |
36 } |
40 } |
37 $key = $entry->key(); |
41 $key = $entry->key(); |
55 */ |
59 */ |
56 function set_header($header, $value) { |
60 function set_header($header, $value) { |
57 $this->headers[$header] = $value; |
61 $this->headers[$header] = $value; |
58 } |
62 } |
59 |
63 |
|
64 /** |
|
65 * @param array $headers |
|
66 */ |
60 function set_headers($headers) { |
67 function set_headers($headers) { |
61 foreach($headers as $header => $value) { |
68 foreach($headers as $header => $value) { |
62 $this->set_header($header, $value); |
69 $this->set_header($header, $value); |
63 } |
70 } |
64 } |
71 } |
65 |
72 |
|
73 /** |
|
74 * @param string $header |
|
75 */ |
66 function get_header($header) { |
76 function get_header($header) { |
67 return isset($this->headers[$header])? $this->headers[$header] : false; |
77 return isset($this->headers[$header])? $this->headers[$header] : false; |
68 } |
78 } |
69 |
79 |
|
80 /** |
|
81 * @param Translation_Entry $entry |
|
82 */ |
70 function translate_entry(&$entry) { |
83 function translate_entry(&$entry) { |
71 $key = $entry->key(); |
84 $key = $entry->key(); |
72 return isset($this->entries[$key])? $this->entries[$key] : false; |
85 return isset($this->entries[$key])? $this->entries[$key] : false; |
73 } |
86 } |
74 |
87 |
|
88 /** |
|
89 * @param string $singular |
|
90 * @param string $context |
|
91 * @return string |
|
92 */ |
75 function translate($singular, $context=null) { |
93 function translate($singular, $context=null) { |
76 $entry = new Translation_Entry(array('singular' => $singular, 'context' => $context)); |
94 $entry = new Translation_Entry(array('singular' => $singular, 'context' => $context)); |
77 $translated = $this->translate_entry($entry); |
95 $translated = $this->translate_entry($entry); |
78 return ($translated && !empty($translated->translations))? $translated->translations[0] : $singular; |
96 return ($translated && !empty($translated->translations))? $translated->translations[0] : $singular; |
79 } |
97 } |
95 |
113 |
96 function get_plural_forms_count() { |
114 function get_plural_forms_count() { |
97 return 2; |
115 return 2; |
98 } |
116 } |
99 |
117 |
|
118 /** |
|
119 * @param string $singular |
|
120 * @param string $plural |
|
121 * @param int $count |
|
122 * @param string $context |
|
123 */ |
100 function translate_plural($singular, $plural, $count, $context = null) { |
124 function translate_plural($singular, $plural, $count, $context = null) { |
101 $entry = new Translation_Entry(array('singular' => $singular, 'plural' => $plural, 'context' => $context)); |
125 $entry = new Translation_Entry(array('singular' => $singular, 'plural' => $plural, 'context' => $context)); |
102 $translated = $this->translate_entry($entry); |
126 $translated = $this->translate_entry($entry); |
103 $index = $this->select_plural_form($count); |
127 $index = $this->select_plural_form($count); |
104 $total_plural_forms = $this->get_plural_forms_count(); |
128 $total_plural_forms = $this->get_plural_forms_count(); |
137 * The gettext implementation of select_plural_form. |
161 * The gettext implementation of select_plural_form. |
138 * |
162 * |
139 * It lives in this class, because there are more than one descendand, which will use it and |
163 * It lives in this class, because there are more than one descendand, which will use it and |
140 * they can't share it effectively. |
164 * they can't share it effectively. |
141 * |
165 * |
|
166 * @param int $count |
142 */ |
167 */ |
143 function gettext_select_plural_form($count) { |
168 function gettext_select_plural_form($count) { |
144 if (!isset($this->_gettext_select_plural_form) || is_null($this->_gettext_select_plural_form)) { |
169 if (!isset($this->_gettext_select_plural_form) || is_null($this->_gettext_select_plural_form)) { |
145 list( $nplurals, $expression ) = $this->nplurals_and_expression_from_header($this->get_header('Plural-Forms')); |
170 list( $nplurals, $expression ) = $this->nplurals_and_expression_from_header($this->get_header('Plural-Forms')); |
146 $this->_nplurals = $nplurals; |
171 $this->_nplurals = $nplurals; |
147 $this->_gettext_select_plural_form = $this->make_plural_form_function($nplurals, $expression); |
172 $this->_gettext_select_plural_form = $this->make_plural_form_function($nplurals, $expression); |
148 } |
173 } |
149 return call_user_func($this->_gettext_select_plural_form, $count); |
174 return call_user_func($this->_gettext_select_plural_form, $count); |
150 } |
175 } |
151 |
176 |
|
177 /** |
|
178 * @param string $header |
|
179 * @return array |
|
180 */ |
152 function nplurals_and_expression_from_header($header) { |
181 function nplurals_and_expression_from_header($header) { |
153 if (preg_match('/^\s*nplurals\s*=\s*(\d+)\s*;\s+plural\s*=\s*(.+)$/', $header, $matches)) { |
182 if (preg_match('/^\s*nplurals\s*=\s*(\d+)\s*;\s+plural\s*=\s*(.+)$/', $header, $matches)) { |
154 $nplurals = (int)$matches[1]; |
183 $nplurals = (int)$matches[1]; |
155 $expression = trim($this->parenthesize_plural_exression($matches[2])); |
184 $expression = trim($this->parenthesize_plural_exression($matches[2])); |
156 return array($nplurals, $expression); |
185 return array($nplurals, $expression); |
160 } |
189 } |
161 |
190 |
162 /** |
191 /** |
163 * Makes a function, which will return the right translation index, according to the |
192 * Makes a function, which will return the right translation index, according to the |
164 * plural forms header |
193 * plural forms header |
|
194 * @param int $nplurals |
|
195 * @param string $expression |
165 */ |
196 */ |
166 function make_plural_form_function($nplurals, $expression) { |
197 function make_plural_form_function($nplurals, $expression) { |
167 $expression = str_replace('n', '$n', $expression); |
198 $expression = str_replace('n', '$n', $expression); |
168 $func_body = " |
199 $func_body = " |
169 \$index = (int)($expression); |
200 \$index = (int)($expression); |
170 return (\$index < $nplurals)? \$index : $nplurals - 1;"; |
201 return (\$index < $nplurals)? \$index : $nplurals - 1;"; |
171 return create_function('$n', $func_body); |
202 return create_function('$n', $func_body); |
172 } |
203 } |
173 |
204 |
174 /** |
205 /** |
175 * Adds parantheses to the inner parts of ternary operators in |
206 * Adds parentheses to the inner parts of ternary operators in |
176 * plural expressions, because PHP evaluates ternary oerators from left to right |
207 * plural expressions, because PHP evaluates ternary oerators from left to right |
177 * |
208 * |
178 * @param string $expression the expression without parentheses |
209 * @param string $expression the expression without parentheses |
179 * @return string the expression with parentheses added |
210 * @return string the expression with parentheses added |
180 */ |
211 */ |
201 } |
232 } |
202 } |
233 } |
203 return rtrim($res, ';'); |
234 return rtrim($res, ';'); |
204 } |
235 } |
205 |
236 |
|
237 /** |
|
238 * @param string $translation |
|
239 * @return array |
|
240 */ |
206 function make_headers($translation) { |
241 function make_headers($translation) { |
207 $headers = array(); |
242 $headers = array(); |
208 // sometimes \ns are used instead of real new lines |
243 // sometimes \ns are used instead of real new lines |
209 $translation = str_replace('\n', "\n", $translation); |
244 $translation = str_replace('\n', "\n", $translation); |
210 $lines = explode("\n", $translation); |
245 $lines = explode("\n", $translation); |
214 $headers[trim($parts[0])] = trim($parts[1]); |
249 $headers[trim($parts[0])] = trim($parts[1]); |
215 } |
250 } |
216 return $headers; |
251 return $headers; |
217 } |
252 } |
218 |
253 |
|
254 /** |
|
255 * @param string $header |
|
256 * @param string $value |
|
257 */ |
219 function set_header($header, $value) { |
258 function set_header($header, $value) { |
220 parent::set_header($header, $value); |
259 parent::set_header($header, $value); |
221 if ('Plural-Forms' == $header) { |
260 if ('Plural-Forms' == $header) { |
222 list( $nplurals, $expression ) = $this->nplurals_and_expression_from_header($this->get_header('Plural-Forms')); |
261 list( $nplurals, $expression ) = $this->nplurals_and_expression_from_header($this->get_header('Plural-Forms')); |
223 $this->_nplurals = $nplurals; |
262 $this->_nplurals = $nplurals; |
263 |
306 |
264 function get_plural_forms_count() { |
307 function get_plural_forms_count() { |
265 return 2; |
308 return 2; |
266 } |
309 } |
267 |
310 |
|
311 /** |
|
312 * @param string $singular |
|
313 * @param string $plural |
|
314 * @param int $count |
|
315 * @param string $context |
|
316 */ |
268 function translate_plural($singular, $plural, $count, $context = null) { |
317 function translate_plural($singular, $plural, $count, $context = null) { |
269 return 1 == $count? $singular : $plural; |
318 return 1 == $count? $singular : $plural; |
270 } |
319 } |
271 |
320 |
272 function merge_with(&$other) { |
321 function merge_with(&$other) { |