Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
67.32% |
103 / 153 |
|
41.18% |
7 / 17 |
CRAP | |
0.00% |
0 / 1 |
language | |
67.32% |
103 / 153 |
|
41.18% |
7 / 17 |
781.53 | |
0.00% |
0 / 1 |
__construct | |
93.33% |
14 / 15 |
|
0.00% |
0 / 1 |
2.00 | |||
set_user_language | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
set_default_language | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
2 | |||
get_lang_array | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
2 | |||
add_lang | |
87.50% |
7 / 8 |
|
0.00% |
0 / 1 |
5.05 | |||
is_set | |
100.00% |
8 / 8 |
|
100.00% |
1 / 1 |
4 | |||
lang | |
100.00% |
3 / 3 |
|
100.00% |
1 / 1 |
1 | |||
lang_raw | |
100.00% |
10 / 10 |
|
100.00% |
1 / 1 |
7 | |||
lang_array | |
89.29% |
25 / 28 |
|
0.00% |
0 / 1 |
14.24 | |||
load_common_language_files | |
100.00% |
5 / 5 |
|
100.00% |
1 / 1 |
3 | |||
inject_default_variables | |
100.00% |
6 / 6 |
|
100.00% |
1 / 1 |
1 | |||
get_plural_form | |
51.43% |
18 / 35 |
|
0.00% |
0 / 1 |
852.50 | |||
get_used_language | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
set_fallback_array | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
20 | |||
load_core_file | |
100.00% |
4 / 4 |
|
100.00% |
1 / 1 |
2 | |||
load_extension | |
0.00% |
0 / 4 |
|
0.00% |
0 / 1 |
6 | |||
reload_language_files | |
0.00% |
0 / 10 |
|
0.00% |
0 / 1 |
20 |
1 | <?php |
2 | /** |
3 | * |
4 | * This file is part of the phpBB Forum Software package. |
5 | * |
6 | * @copyright (c) phpBB Limited <https://www.phpbb.com> |
7 | * @license GNU General Public License, version 2 (GPL-2.0) |
8 | * |
9 | * For full copyright and license information, please see |
10 | * the docs/CREDITS.txt file. |
11 | * |
12 | */ |
13 | |
14 | namespace phpbb\language; |
15 | |
16 | use phpbb\language\exception\invalid_plural_rule_exception; |
17 | |
18 | /** |
19 | * Wrapper class for loading translations |
20 | */ |
21 | class language |
22 | { |
23 | /** |
24 | * Global fallback language |
25 | * |
26 | * ISO code of the language to fallback to when the specified language entries |
27 | * cannot be found. |
28 | * |
29 | * @var string |
30 | */ |
31 | const FALLBACK_LANGUAGE = 'en'; |
32 | |
33 | /** |
34 | * @var array List of common language files |
35 | */ |
36 | protected $common_language_files; |
37 | |
38 | /** |
39 | * @var bool |
40 | */ |
41 | protected $common_language_files_loaded; |
42 | |
43 | /** |
44 | * @var string|null ISO code of the default board language |
45 | */ |
46 | protected $default_language; |
47 | |
48 | /** |
49 | * @var string|null ISO code of the User's language |
50 | */ |
51 | protected $user_language; |
52 | |
53 | /** |
54 | * @var array Language fallback array (the order is important) |
55 | */ |
56 | protected $language_fallback; |
57 | |
58 | /** |
59 | * @var array Array of language variables |
60 | */ |
61 | protected $lang; |
62 | |
63 | /** |
64 | * @var array Loaded language sets |
65 | */ |
66 | protected $loaded_language_sets; |
67 | |
68 | /** |
69 | * @var \phpbb\language\language_file_loader Language file loader |
70 | */ |
71 | protected $loader; |
72 | |
73 | /** |
74 | * Constructor |
75 | * |
76 | * @param \phpbb\language\language_file_loader $loader Language file loader |
77 | * @param array|null $common_modules Array of common language modules to load (optional) |
78 | */ |
79 | public function __construct(language_file_loader $loader, $common_modules = null) |
80 | { |
81 | $this->loader = $loader; |
82 | |
83 | // Set up default information |
84 | $this->user_language = null; |
85 | $this->default_language = null; |
86 | $this->lang = array(); |
87 | $this->loaded_language_sets = array( |
88 | 'core' => array(), |
89 | 'ext' => array(), |
90 | ); |
91 | |
92 | // Common language files |
93 | if (is_array($common_modules)) |
94 | { |
95 | $this->common_language_files = $common_modules; |
96 | } |
97 | else |
98 | { |
99 | $this->common_language_files = array( |
100 | 'common', |
101 | ); |
102 | } |
103 | |
104 | $this->common_language_files_loaded = false; |
105 | |
106 | $this->language_fallback = array(self::FALLBACK_LANGUAGE); |
107 | } |
108 | |
109 | /** |
110 | * Function to set user's language to display. |
111 | * |
112 | * @param string $user_lang_iso ISO code of the User's language |
113 | * @param bool $reload Whether or not to reload language files |
114 | */ |
115 | public function set_user_language(string $user_lang_iso, $reload = false) |
116 | { |
117 | $this->user_language = $user_lang_iso; |
118 | |
119 | $this->set_fallback_array($reload); |
120 | } |
121 | |
122 | /** |
123 | * Function to set the board's default language to display. |
124 | * |
125 | * @param string $default_lang_iso ISO code of the board's default language |
126 | * @param bool $reload Whether or not to reload language files |
127 | */ |
128 | public function set_default_language(string $default_lang_iso, $reload = false) |
129 | { |
130 | $this->default_language = $default_lang_iso; |
131 | |
132 | $this->set_fallback_array($reload); |
133 | } |
134 | |
135 | /** |
136 | * Returns language array |
137 | * |
138 | * Note: This function is needed for the BC purposes, until \phpbb\user::lang[] is |
139 | * not removed. |
140 | * |
141 | * @return array Array of loaded language strings |
142 | */ |
143 | public function get_lang_array() |
144 | { |
145 | // Load common language files if they not loaded yet |
146 | if (!$this->common_language_files_loaded) |
147 | { |
148 | $this->load_common_language_files(); |
149 | } |
150 | |
151 | return $this->lang; |
152 | } |
153 | |
154 | /** |
155 | * Add Language Items |
156 | * |
157 | * Examples: |
158 | * <code> |
159 | * $component = array('posting'); |
160 | * $component = array('posting', 'viewtopic') |
161 | * $component = 'posting' |
162 | * </code> |
163 | * |
164 | * @param string|array $component The name of the language component to load |
165 | * @param string|null $extension_name Name of the extension to load component from, or null for core file |
166 | */ |
167 | public function add_lang($component, $extension_name = null) |
168 | { |
169 | // Load common language files if they not loaded yet |
170 | // This needs to be here to correctly merge language arrays |
171 | if (!$this->common_language_files_loaded) |
172 | { |
173 | $this->load_common_language_files(); |
174 | } |
175 | |
176 | if (!is_array($component)) |
177 | { |
178 | if (!is_null($extension_name)) |
179 | { |
180 | $this->load_extension($extension_name, $component); |
181 | } |
182 | else |
183 | { |
184 | $this->load_core_file($component); |
185 | } |
186 | } |
187 | else |
188 | { |
189 | foreach ($component as $lang_file) |
190 | { |
191 | $this->add_lang($lang_file, $extension_name); |
192 | } |
193 | } |
194 | } |
195 | |
196 | /** |
197 | * @param array|string $key The language key we want to know more about. Can be string or array. |
198 | * |
199 | * @return bool Returns whether the language key is set. |
200 | */ |
201 | public function is_set($key) |
202 | { |
203 | // Load common language files if they not loaded yet |
204 | if (!$this->common_language_files_loaded) |
205 | { |
206 | $this->load_common_language_files(); |
207 | } |
208 | |
209 | if (is_array($key)) |
210 | { |
211 | $lang = &$this->lang[array_shift($key)]; |
212 | |
213 | foreach ($key as $_key) |
214 | { |
215 | $lang = &$lang[$_key]; |
216 | } |
217 | } |
218 | else |
219 | { |
220 | $lang = &$this->lang[$key]; |
221 | } |
222 | |
223 | return isset($lang); |
224 | } |
225 | |
226 | /** |
227 | * Advanced language substitution |
228 | * |
229 | * Function to mimic sprintf() with the possibility of using phpBB's language system to substitute nullar/singular/plural forms. |
230 | * Params are the language key and the parameters to be substituted. |
231 | * This function/functionality is inspired by SHS` and Ashe. |
232 | * |
233 | * Example call: <samp>$user->lang('NUM_POSTS_IN_QUEUE', 1);</samp> |
234 | * |
235 | * If the first parameter is an array, the elements are used as keys and subkeys to get the language entry: |
236 | * Example: <samp>$user->lang(array('datetime', 'AGO'), 1)</samp> uses $user->lang['datetime']['AGO'] as language entry. |
237 | * |
238 | * @return string Return localized string or the language key if the translation is not available |
239 | */ |
240 | public function lang() |
241 | { |
242 | $args = func_get_args(); |
243 | $key = array_shift($args); |
244 | |
245 | return $this->lang_array($key, $args); |
246 | } |
247 | |
248 | /** |
249 | * Returns the raw value associated to a language key or the language key no translation is available. |
250 | * No parameter substitution is performed, can be a string or an array. |
251 | * |
252 | * @param string|array $key Language key |
253 | * |
254 | * @return array|string |
255 | */ |
256 | public function lang_raw($key) |
257 | { |
258 | // Load common language files if they not loaded yet |
259 | if (!$this->common_language_files_loaded) |
260 | { |
261 | $this->load_common_language_files(); |
262 | } |
263 | |
264 | if (is_array($key)) |
265 | { |
266 | $lang = &$this->lang[array_shift($key)]; |
267 | |
268 | foreach ($key as $_key) |
269 | { |
270 | $lang = &$lang[$_key]; |
271 | } |
272 | } |
273 | else |
274 | { |
275 | $lang = &$this->lang[$key]; |
276 | } |
277 | |
278 | // Return if language string does not exist |
279 | if (!isset($lang) || (!is_string($lang) && !is_array($lang))) |
280 | { |
281 | return $key; |
282 | } |
283 | |
284 | return $lang; |
285 | } |
286 | |
287 | /** |
288 | * Act like lang() but takes a key and an array of parameters instead of using variadic |
289 | * |
290 | * @param string|array $key Language key |
291 | * @param array $args Parameters |
292 | * |
293 | * @return string |
294 | */ |
295 | public function lang_array($key, array $args = []) |
296 | { |
297 | $lang = $this->lang_raw($key); |
298 | |
299 | if ($lang === $key) |
300 | { |
301 | return (string) $key; |
302 | } |
303 | |
304 | // If the language entry is a string, we simply mimic sprintf() behaviour |
305 | if (is_string($lang)) |
306 | { |
307 | if (count($args) === 0) |
308 | { |
309 | return $lang; |
310 | } |
311 | |
312 | // Replace key with language entry and simply pass along... |
313 | return vsprintf($lang, $args); |
314 | } |
315 | else if (count($lang) == 0) |
316 | { |
317 | // If the language entry is an empty array, we just return the language key |
318 | return (string) $key; |
319 | } |
320 | |
321 | // It is an array... now handle different nullar/singular/plural forms |
322 | $key_found = false; |
323 | |
324 | // We now get the first number passed and will select the key based upon this number |
325 | for ($i = 0, $num_args = count($args); $i < $num_args; $i++) |
326 | { |
327 | if (is_int($args[$i]) || is_float($args[$i])) |
328 | { |
329 | if ($args[$i] == 0 && isset($lang[0])) |
330 | { |
331 | // We allow each translation using plural forms to specify a version for the case of 0 things, |
332 | // so that "0 users" may be displayed as "No users". |
333 | $key_found = 0; |
334 | break; |
335 | } |
336 | else |
337 | { |
338 | $use_plural_form = $this->get_plural_form($args[$i]); |
339 | if (isset($lang[$use_plural_form])) |
340 | { |
341 | // The key we should use exists, so we use it. |
342 | $key_found = $use_plural_form; |
343 | } |
344 | else |
345 | { |
346 | // If the key we need to use does not exist, we fall back to the previous one. |
347 | $numbers = array_keys($lang); |
348 | |
349 | foreach ($numbers as $num) |
350 | { |
351 | if ($num > $use_plural_form) |
352 | { |
353 | break; |
354 | } |
355 | |
356 | $key_found = $num; |
357 | } |
358 | } |
359 | break; |
360 | } |
361 | } |
362 | } |
363 | |
364 | // Ok, let's check if the key was found, else use the last entry (because it is mostly the plural form) |
365 | if ($key_found === false) |
366 | { |
367 | $numbers = array_keys($lang); |
368 | $key_found = end($numbers); |
369 | } |
370 | |
371 | // Use the language string we determined and pass it to sprintf() |
372 | return vsprintf($lang[$key_found], $args); |
373 | } |
374 | |
375 | /** |
376 | * Loads common language files |
377 | */ |
378 | protected function load_common_language_files() |
379 | { |
380 | if (!$this->common_language_files_loaded) |
381 | { |
382 | foreach ($this->common_language_files as $lang_file) |
383 | { |
384 | $this->load_core_file($lang_file); |
385 | } |
386 | |
387 | $this->inject_default_variables(); |
388 | |
389 | $this->common_language_files_loaded = true; |
390 | } |
391 | } |
392 | |
393 | /** |
394 | * Inject default values based on composer.json |
395 | * |
396 | * @return void |
397 | */ |
398 | protected function inject_default_variables(): void |
399 | { |
400 | $lang_values = $this->loader->get_composer_lang_values($this->language_fallback); |
401 | |
402 | $this->lang['DIRECTION'] = $lang_values['direction'] ?? 'ltr'; |
403 | $this->lang['USER_LANG'] = $lang_values['user_lang'] ?? 'en-gb'; |
404 | $this->lang['PLURAL_RULE'] = $lang_values['plural_rule'] ?? 1; |
405 | $this->lang['RECAPTCHA_LANG'] = $lang_values['recaptcha_lang'] ?? 'en-GB'; |
406 | $this->lang['TURNSTILE_LANG'] = $lang_values['turnstile_lang'] ?? 'auto'; // default to auto mode |
407 | } |
408 | |
409 | /** |
410 | * Determine which plural form we should use. |
411 | * |
412 | * For some languages this is not as simple as for English. |
413 | * |
414 | * @param int|float $number The number we want to get the plural case for. Float numbers are floored. |
415 | * @param int|bool $force_rule False to use the plural rule of the language package |
416 | * or an integer to force a certain plural rule |
417 | * |
418 | * @return int The plural-case we need to use for the number plural-rule combination |
419 | * |
420 | * @throws invalid_plural_rule_exception When $force_rule has an invalid value |
421 | */ |
422 | public function get_plural_form($number, $force_rule = false) |
423 | { |
424 | $number = (int) $number; |
425 | $plural_rule = ($force_rule !== false) ? $force_rule : ((isset($this->lang['PLURAL_RULE'])) ? $this->lang['PLURAL_RULE'] : 1); |
426 | |
427 | /** |
428 | * The following plural rules are based on a list published by the Mozilla Developer Network |
429 | * https://developer.mozilla.org/en/Localization_and_Plurals |
430 | */ |
431 | switch ($plural_rule) |
432 | { |
433 | case 0: |
434 | /** |
435 | * Families: Asian (Chinese, Japanese, Korean, Vietnamese), Persian, Turkic/Altaic (Turkish), Thai, Lao |
436 | * 1 - everything: 0, 1, 2, ... |
437 | */ |
438 | return 1; |
439 | |
440 | case 1: |
441 | /** |
442 | * Families: Germanic (Danish, Dutch, English, Faroese, Frisian, German, Norwegian, Swedish), Finno-Ugric (Estonian, Finnish, Hungarian), Language isolate (Basque), Latin/Greek (Greek), Semitic (Hebrew), Romanic (Italian, Portuguese, Spanish, Catalan) |
443 | * 1 - 1 |
444 | * 2 - everything else: 0, 2, 3, ... |
445 | */ |
446 | return ($number === 1) ? 1 : 2; |
447 | |
448 | case 2: |
449 | /** |
450 | * Families: Romanic (French, Brazilian Portuguese) |
451 | * 1 - 0, 1 |
452 | * 2 - everything else: 2, 3, ... |
453 | */ |
454 | return (($number === 0) || ($number === 1)) ? 1 : 2; |
455 | |
456 | case 3: |
457 | /** |
458 | * Families: Baltic (Latvian) |
459 | * 1 - 0 |
460 | * 2 - ends in 1, not 11: 1, 21, ... 101, 121, ... |
461 | * 3 - everything else: 2, 3, ... 10, 11, 12, ... 20, 22, ... |
462 | */ |
463 | return ($number === 0) ? 1 : ((($number % 10 === 1) && ($number % 100 != 11)) ? 2 : 3); |
464 | |
465 | case 4: |
466 | /** |
467 | * Families: Celtic (Scottish Gaelic) |
468 | * 1 - is 1 or 11: 1, 11 |
469 | * 2 - is 2 or 12: 2, 12 |
470 | * 3 - others between 3 and 19: 3, 4, ... 10, 13, ... 18, 19 |
471 | * 4 - everything else: 0, 20, 21, ... |
472 | */ |
473 | return ($number === 1 || $number === 11) ? 1 : (($number === 2 || $number === 12) ? 2 : (($number >= 3 && $number <= 19) ? 3 : 4)); |
474 | |
475 | case 5: |
476 | /** |
477 | * Families: Romanic (Romanian) |
478 | * 1 - 1 |
479 | * 2 - is 0 or ends in 01-19: 0, 2, 3, ... 19, 101, 102, ... 119, 201, ... |
480 | * 3 - everything else: 20, 21, ... |
481 | */ |
482 | return ($number === 1) ? 1 : ((($number === 0) || (($number % 100 > 0) && ($number % 100 < 20))) ? 2 : 3); |
483 | |
484 | case 6: |
485 | /** |
486 | * Families: Baltic (Lithuanian) |
487 | * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, ... |
488 | * 2 - ends in 0 or ends in 10-20: 0, 10, 11, 12, ... 19, 20, 30, 40, ... |
489 | * 3 - everything else: 2, 3, ... 8, 9, 22, 23, ... 29, 32, 33, ... |
490 | */ |
491 | return (($number % 10 === 1) && ($number % 100 != 11)) ? 1 : ((($number % 10 < 2) || (($number % 100 >= 10) && ($number % 100 < 20))) ? 2 : 3); |
492 | |
493 | case 7: |
494 | /** |
495 | * Families: Slavic (Croatian, Serbian, Russian, Ukrainian) |
496 | * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, ... |
497 | * 2 - ends in 2-4, not 12-14: 2, 3, 4, 22, 23, 24, 32, ... |
498 | * 3 - everything else: 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 26, ... |
499 | */ |
500 | return (($number % 10 === 1) && ($number % 100 != 11)) ? 1 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 2 : 3); |
501 | |
502 | case 8: |
503 | /** |
504 | * Families: Slavic (Slovak, Czech) |
505 | * 1 - 1 |
506 | * 2 - 2, 3, 4 |
507 | * 3 - everything else: 0, 5, 6, 7, ... |
508 | */ |
509 | return ($number === 1) ? 1 : ((($number >= 2) && ($number <= 4)) ? 2 : 3); |
510 | |
511 | case 9: |
512 | /** |
513 | * Families: Slavic (Polish) |
514 | * 1 - 1 |
515 | * 2 - ends in 2-4, not 12-14: 2, 3, 4, 22, 23, 24, 32, ... 104, 122, ... |
516 | * 3 - everything else: 0, 5, 6, ... 11, 12, 13, 14, 15, ... 20, 21, 25, ... |
517 | */ |
518 | return ($number === 1) ? 1 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 2 : 3); |
519 | |
520 | case 10: |
521 | /** |
522 | * Families: Slavic (Slovenian, Sorbian) |
523 | * 1 - ends in 01: 1, 101, 201, ... |
524 | * 2 - ends in 02: 2, 102, 202, ... |
525 | * 3 - ends in 03-04: 3, 4, 103, 104, 203, 204, ... |
526 | * 4 - everything else: 0, 5, 6, 7, 8, 9, 10, 11, ... |
527 | */ |
528 | return ($number % 100 === 1) ? 1 : (($number % 100 === 2) ? 2 : ((($number % 100 === 3) || ($number % 100 === 4)) ? 3 : 4)); |
529 | |
530 | case 11: |
531 | /** |
532 | * Families: Celtic (Irish Gaeilge) |
533 | * 1 - 1 |
534 | * 2 - 2 |
535 | * 3 - is 3-6: 3, 4, 5, 6 |
536 | * 4 - is 7-10: 7, 8, 9, 10 |
537 | * 5 - everything else: 0, 11, 12, ... |
538 | */ |
539 | return ($number === 1) ? 1 : (($number === 2) ? 2 : (($number >= 3 && $number <= 6) ? 3 : (($number >= 7 && $number <= 10) ? 4 : 5))); |
540 | |
541 | case 12: |
542 | /** |
543 | * Families: Semitic (Arabic) |
544 | * 1 - 1 |
545 | * 2 - 2 |
546 | * 3 - ends in 03-10: 3, 4, ... 10, 103, 104, ... 110, 203, 204, ... |
547 | * 4 - ends in 11-99: 11, ... 99, 111, 112, ... |
548 | * 5 - everything else: 100, 101, 102, 200, 201, 202, ... |
549 | * 6 - 0 |
550 | */ |
551 | return ($number === 1) ? 1 : (($number === 2) ? 2 : ((($number % 100 >= 3) && ($number % 100 <= 10)) ? 3 : ((($number % 100 >= 11) && ($number % 100 <= 99)) ? 4 : (($number != 0) ? 5 : 6)))); |
552 | |
553 | case 13: |
554 | /** |
555 | * Families: Semitic (Maltese) |
556 | * 1 - 1 |
557 | * 2 - is 0 or ends in 01-10: 0, 2, 3, ... 9, 10, 101, 102, ... |
558 | * 3 - ends in 11-19: 11, 12, ... 18, 19, 111, 112, ... |
559 | * 4 - everything else: 20, 21, ... |
560 | */ |
561 | return ($number === 1) ? 1 : ((($number === 0) || (($number % 100 > 1) && ($number % 100 < 11))) ? 2 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 3 : 4)); |
562 | |
563 | case 14: |
564 | /** |
565 | * Families: Slavic (Macedonian) |
566 | * 1 - ends in 1: 1, 11, 21, ... |
567 | * 2 - ends in 2: 2, 12, 22, ... |
568 | * 3 - everything else: 0, 3, 4, ... 10, 13, 14, ... 20, 23, ... |
569 | */ |
570 | return ($number % 10 === 1) ? 1 : (($number % 10 === 2) ? 2 : 3); |
571 | |
572 | case 15: |
573 | /** |
574 | * Families: Icelandic |
575 | * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, 131, ... |
576 | * 2 - everything else: 0, 2, 3, ... 10, 11, 12, ... 20, 22, ... |
577 | */ |
578 | return (($number % 10 === 1) && ($number % 100 != 11)) ? 1 : 2; |
579 | |
580 | default: |
581 | throw new invalid_plural_rule_exception('INVALID_PLURAL_RULE', ['plural_rule' => $plural_rule]); |
582 | } |
583 | } |
584 | |
585 | /** |
586 | * Returns the ISO code of the used language |
587 | * |
588 | * @return string The ISO code of the currently used language |
589 | */ |
590 | public function get_used_language() |
591 | { |
592 | return $this->language_fallback[0]; |
593 | } |
594 | |
595 | /** |
596 | * Returns language fallback data |
597 | * |
598 | * @param bool $reload Whether or not to reload language files |
599 | */ |
600 | protected function set_fallback_array($reload = false) |
601 | { |
602 | $fallback_array = array(); |
603 | |
604 | if ($this->user_language !== null) |
605 | { |
606 | $fallback_array[] = $this->user_language; |
607 | } |
608 | |
609 | if ($this->default_language !== null) |
610 | { |
611 | $fallback_array[] = $this->default_language; |
612 | } |
613 | |
614 | $fallback_array[] = self::FALLBACK_LANGUAGE; |
615 | |
616 | $this->language_fallback = $fallback_array; |
617 | |
618 | if ($reload) |
619 | { |
620 | $this->reload_language_files(); |
621 | } |
622 | } |
623 | |
624 | /** |
625 | * Load core language file |
626 | * |
627 | * @param string $component Name of the component to load |
628 | */ |
629 | protected function load_core_file($component) |
630 | { |
631 | // Check if the component is already loaded |
632 | if (isset($this->loaded_language_sets['core'][$component])) |
633 | { |
634 | return; |
635 | } |
636 | |
637 | $this->loader->load($component, $this->language_fallback, $this->lang); |
638 | $this->loaded_language_sets['core'][$component] = true; |
639 | } |
640 | |
641 | /** |
642 | * Load extension language file |
643 | * |
644 | * @param string $extension_name Name of the extension to load language from |
645 | * @param string $component Name of the component to load |
646 | */ |
647 | protected function load_extension($extension_name, $component) |
648 | { |
649 | // Check if the component is already loaded |
650 | if (isset($this->loaded_language_sets['ext'][$extension_name][$component])) |
651 | { |
652 | return; |
653 | } |
654 | |
655 | $this->loader->load_extension($extension_name, $component, $this->language_fallback, $this->lang); |
656 | $this->loaded_language_sets['ext'][$extension_name][$component] = true; |
657 | } |
658 | |
659 | /** |
660 | * Reload language files |
661 | */ |
662 | protected function reload_language_files() |
663 | { |
664 | $loaded_files = $this->loaded_language_sets; |
665 | $this->loaded_language_sets = array( |
666 | 'core' => array(), |
667 | 'ext' => array(), |
668 | ); |
669 | |
670 | // Reload core files |
671 | foreach ($loaded_files['core'] as $component => $value) |
672 | { |
673 | $this->load_core_file($component); |
674 | } |
675 | |
676 | // Reload extension files |
677 | foreach ($loaded_files['ext'] as $ext_name => $ext_info) |
678 | { |
679 | foreach ($ext_info as $ext_component => $value) |
680 | { |
681 | $this->load_extension($ext_name, $ext_component); |
682 | } |
683 | } |
684 | } |
685 | } |