diff options
Diffstat (limited to 'phpBB')
-rw-r--r-- | phpBB/composer.json | 2 | ||||
-rw-r--r-- | phpBB/config/default/container/services.yml | 1 | ||||
-rw-r--r-- | phpBB/config/default/container/services_language.yml | 22 | ||||
-rw-r--r-- | phpBB/config/default/container/services_user.yml | 1 | ||||
-rw-r--r-- | phpBB/includes/acp/acp_extensions.php | 8 | ||||
-rw-r--r-- | phpBB/includes/acp/acp_language.php | 38 | ||||
-rw-r--r-- | phpBB/includes/functions.php | 180 | ||||
-rw-r--r-- | phpBB/includes/functions_compatibility.php | 19 | ||||
-rw-r--r-- | phpBB/includes/functions_user.php | 2 | ||||
-rw-r--r-- | phpBB/install/index.php | 8 | ||||
-rw-r--r-- | phpBB/phpbb/captcha/plugins/captcha_abstract.php | 2 | ||||
-rw-r--r-- | phpBB/phpbb/language/exception/invalid_plural_rule_exception.php | 22 | ||||
-rw-r--r-- | phpBB/phpbb/language/exception/language_exception.php | 22 | ||||
-rw-r--r-- | phpBB/phpbb/language/exception/language_file_not_found.php | 22 | ||||
-rw-r--r-- | phpBB/phpbb/language/language.php | 562 | ||||
-rw-r--r-- | phpBB/phpbb/language/language_file_helper.php | 71 | ||||
-rw-r--r-- | phpBB/phpbb/language/language_file_loader.php | 212 | ||||
-rw-r--r-- | phpBB/phpbb/user.php | 336 |
18 files changed, 1083 insertions, 447 deletions
diff --git a/phpBB/composer.json b/phpBB/composer.json index 31462b81eb..419779e5f7 100644 --- a/phpBB/composer.json +++ b/phpBB/composer.json @@ -35,6 +35,7 @@ "symfony/dependency-injection": "2.8.*@dev", "symfony/event-dispatcher": "2.8.*@dev", "symfony/filesystem": "2.8.*@dev", + "symfony/finder": "2.8.*@dev", "symfony/http-kernel": "2.8.*@dev", "symfony/routing": "2.8.*@dev", "symfony/security-core": "2.8.*@dev", @@ -54,7 +55,6 @@ "symfony/css-selector": "2.8.*@dev", "symfony/debug": "2.8.*@dev", "symfony/dom-crawler": "2.8.*@dev", - "symfony/finder": "2.8.*@dev", "symfony/http-foundation": "2.8.*@dev", "symfony/process": "2.8.*@dev" } diff --git a/phpBB/config/default/container/services.yml b/phpBB/config/default/container/services.yml index 11032408d7..670ea3bd61 100644 --- a/phpBB/config/default/container/services.yml +++ b/phpBB/config/default/container/services.yml @@ -9,6 +9,7 @@ imports: - { resource: services_event.yml } - { resource: services_feed.yml } - { resource: services_help.yml } + - { resource: services_language.yml } - { resource: services_mimetype_guesser.yml } - { resource: services_notification.yml } - { resource: services_password.yml } diff --git a/phpBB/config/default/container/services_language.yml b/phpBB/config/default/container/services_language.yml new file mode 100644 index 0000000000..aa3631ded1 --- /dev/null +++ b/phpBB/config/default/container/services_language.yml @@ -0,0 +1,22 @@ +services: + language.helper.language_file: + class: phpbb\language\language_file_helper + arguments: + - %core.root_path% + + language: + class: phpbb\language\language + arguments: + - @language.loader + + language.loader_abstract: + abstract: true + class: phpbb\language\language_file_loader + arguments: + - %core.root_path% + - %core.php_ext% + + language.loader: + parent: language.loader_abstract + calls: + - [set_extension_manager, ["@ext.manager"]] diff --git a/phpBB/config/default/container/services_user.yml b/phpBB/config/default/container/services_user.yml index 1ca853ea45..ff114f022a 100644 --- a/phpBB/config/default/container/services_user.yml +++ b/phpBB/config/default/container/services_user.yml @@ -8,6 +8,7 @@ services: user: class: phpbb\user arguments: + - @language - %datetime.class% user_loader: diff --git a/phpBB/includes/acp/acp_extensions.php b/phpBB/includes/acp/acp_extensions.php index cbef13dfd0..0373a3b115 100644 --- a/phpBB/includes/acp/acp_extensions.php +++ b/phpBB/includes/acp/acp_extensions.php @@ -76,7 +76,7 @@ class acp_extensions { $md_manager->get_metadata('all'); } - catch(\phpbb\extension\exception $e) + catch (\phpbb\extension\exception $e) { $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); trigger_error($message, E_USER_WARNING); @@ -353,7 +353,7 @@ class acp_extensions $enabled_extension_meta_data[$name]['S_VERSIONCHECK'] = true; $enabled_extension_meta_data[$name]['U_VERSIONCHECK_FORCE'] = $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')); } - catch(\phpbb\extension\exception $e) + catch (\phpbb\extension\exception $e) { $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); $this->template->assign_block_vars('disabled', array( @@ -410,7 +410,7 @@ class acp_extensions $disabled_extension_meta_data[$name]['S_VERSIONCHECK'] = true; $disabled_extension_meta_data[$name]['U_VERSIONCHECK_FORCE'] = $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')); } - catch(\phpbb\extension\exception $e) + catch (\phpbb\extension\exception $e) { $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); $this->template->assign_block_vars('disabled', array( @@ -470,7 +470,7 @@ class acp_extensions $available_extension_meta_data[$name]['S_VERSIONCHECK'] = true; $available_extension_meta_data[$name]['U_VERSIONCHECK_FORCE'] = $this->u_action . '&action=details&versioncheck_force=1&ext_name=' . urlencode($md_manager->get_metadata('name')); } - catch(\phpbb\extension\exception $e) + catch (\phpbb\extension\exception $e) { $message = call_user_func_array(array($this->user, 'lang'), array_merge(array($e->getMessage()), $e->get_parameters())); $this->template->assign_block_vars('disabled', array( diff --git a/phpBB/includes/acp/acp_language.php b/phpBB/includes/acp/acp_language.php index 3fd118b0dd..e7ee7f47d6 100644 --- a/phpBB/includes/acp/acp_language.php +++ b/phpBB/includes/acp/acp_language.php @@ -31,7 +31,7 @@ class acp_language function main($id, $mode) { - global $config, $db, $user, $template, $phpbb_log; + global $config, $db, $user, $template, $phpbb_log, $phpbb_container; global $phpbb_root_path, $phpEx, $request; include_once($phpbb_root_path . 'includes/functions_user.' . $phpEx); @@ -377,37 +377,19 @@ class acp_language $db->sql_freeresult($result); $new_ary = $iso = array(); - $dp = @opendir("{$phpbb_root_path}language"); - if ($dp) + /** @var \phpbb\language\language_file_helper $language_helper */ + $language_helper = $phpbb_container->get('language.helper.language_file'); + $iso = $language_helper->get_available_languages(); + + foreach ($iso as $lang_array) { - while (($file = readdir($dp)) !== false) - { - if ($file[0] == '.' || !is_dir($phpbb_root_path . 'language/' . $file)) - { - continue; - } + $lang_iso = $lang_array['iso']; - if (file_exists("{$phpbb_root_path}language/$file/iso.txt")) - { - if (!in_array($file, $installed)) - { - if ($iso = file("{$phpbb_root_path}language/$file/iso.txt")) - { - if (sizeof($iso) == 3) - { - $new_ary[$file] = array( - 'iso' => $file, - 'name' => trim($iso[0]), - 'local_name'=> trim($iso[1]), - 'author' => trim($iso[2]) - ); - } - } - } - } + if (!in_array($lang_iso, $installed)) + { + $new_ary[$lang_iso] = $lang_array; } - closedir($dp); } unset($installed); diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php index 98b5af372a..2ed0eff81c 100644 --- a/phpBB/includes/functions.php +++ b/phpBB/includes/functions.php @@ -1719,7 +1719,7 @@ function redirect($url, $return = false, $disable_cd_check = false) $failover_flag = false; - if (empty($user->lang)) + if (!$user->is_setup()) { $user->add_lang('common'); } @@ -2243,7 +2243,7 @@ function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = fa $err = ''; // Make sure user->setup() has been called - if (empty($user->lang)) + if (!$user->is_setup()) { $user->setup(); } @@ -3268,7 +3268,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline) case E_USER_ERROR: - if (!empty($user) && !empty($user->lang)) + if (!empty($user) && $user->is_setup()) { $msg_text = (!empty($user->lang[$msg_text])) ? $user->lang[$msg_text] : $msg_text; $msg_title = (!isset($msg_title)) ? $user->lang['GENERAL_ERROR'] : ((!empty($user->lang[$msg_title])) ? $user->lang[$msg_title] : $msg_title); @@ -3388,7 +3388,7 @@ function msg_handler($errno, $msg_text, $errfile, $errline) // We re-init the auth array to get correct results on login/logout $auth->acl($user->data); - if (empty($user->lang)) + if (!$user->is_setup()) { $user->setup(); } @@ -3762,178 +3762,6 @@ function phpbb_optionset($bit, $set, $data) } /** -* Determine which plural form we should use. -* For some languages this is not as simple as for English. -* -* @param $rule int ID of the plural rule we want to use, see http://wiki.phpbb.com/Plural_Rules#Plural_Rules -* @param $number int|float The number we want to get the plural case for. Float numbers are floored. -* @return int The plural-case we need to use for the number plural-rule combination -*/ -function phpbb_get_plural_form($rule, $number) -{ - $number = (int) $number; - - if ($rule > 15 || $rule < 0) - { - trigger_error('INVALID_PLURAL_RULE'); - } - - /** - * The following plural rules are based on a list published by the Mozilla Developer Network - * https://developer.mozilla.org/en/Localization_and_Plurals - */ - switch ($rule) - { - case 0: - /** - * Families: Asian (Chinese, Japanese, Korean, Vietnamese), Persian, Turkic/Altaic (Turkish), Thai, Lao - * 1 - everything: 0, 1, 2, ... - */ - return 1; - - case 1: - /** - * 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) - * 1 - 1 - * 2 - everything else: 0, 2, 3, ... - */ - return ($number == 1) ? 1 : 2; - - case 2: - /** - * Families: Romanic (French, Brazilian Portuguese) - * 1 - 0, 1 - * 2 - everything else: 2, 3, ... - */ - return (($number == 0) || ($number == 1)) ? 1 : 2; - - case 3: - /** - * Families: Baltic (Latvian) - * 1 - 0 - * 2 - ends in 1, not 11: 1, 21, ... 101, 121, ... - * 3 - everything else: 2, 3, ... 10, 11, 12, ... 20, 22, ... - */ - return ($number == 0) ? 1 : ((($number % 10 == 1) && ($number % 100 != 11)) ? 2 : 3); - - case 4: - /** - * Families: Celtic (Scottish Gaelic) - * 1 - is 1 or 11: 1, 11 - * 2 - is 2 or 12: 2, 12 - * 3 - others between 3 and 19: 3, 4, ... 10, 13, ... 18, 19 - * 4 - everything else: 0, 20, 21, ... - */ - return ($number == 1 || $number == 11) ? 1 : (($number == 2 || $number == 12) ? 2 : (($number >= 3 && $number <= 19) ? 3 : 4)); - - case 5: - /** - * Families: Romanic (Romanian) - * 1 - 1 - * 2 - is 0 or ends in 01-19: 0, 2, 3, ... 19, 101, 102, ... 119, 201, ... - * 3 - everything else: 20, 21, ... - */ - return ($number == 1) ? 1 : ((($number == 0) || (($number % 100 > 0) && ($number % 100 < 20))) ? 2 : 3); - - case 6: - /** - * Families: Baltic (Lithuanian) - * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, ... - * 2 - ends in 0 or ends in 10-20: 0, 10, 11, 12, ... 19, 20, 30, 40, ... - * 3 - everything else: 2, 3, ... 8, 9, 22, 23, ... 29, 32, 33, ... - */ - return (($number % 10 == 1) && ($number % 100 != 11)) ? 1 : ((($number % 10 < 2) || (($number % 100 >= 10) && ($number % 100 < 20))) ? 2 : 3); - - case 7: - /** - * Families: Slavic (Croatian, Serbian, Russian, Ukrainian) - * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, ... - * 2 - ends in 2-4, not 12-14: 2, 3, 4, 22, 23, 24, 32, ... - * 3 - everything else: 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 26, ... - */ - return (($number % 10 == 1) && ($number % 100 != 11)) ? 1 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 2 : 3); - - case 8: - /** - * Families: Slavic (Slovak, Czech) - * 1 - 1 - * 2 - 2, 3, 4 - * 3 - everything else: 0, 5, 6, 7, ... - */ - return ($number == 1) ? 1 : ((($number >= 2) && ($number <= 4)) ? 2 : 3); - - case 9: - /** - * Families: Slavic (Polish) - * 1 - 1 - * 2 - ends in 2-4, not 12-14: 2, 3, 4, 22, 23, 24, 32, ... 104, 122, ... - * 3 - everything else: 0, 5, 6, ... 11, 12, 13, 14, 15, ... 20, 21, 25, ... - */ - return ($number == 1) ? 1 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 2 : 3); - - case 10: - /** - * Families: Slavic (Slovenian, Sorbian) - * 1 - ends in 01: 1, 101, 201, ... - * 2 - ends in 02: 2, 102, 202, ... - * 3 - ends in 03-04: 3, 4, 103, 104, 203, 204, ... - * 4 - everything else: 0, 5, 6, 7, 8, 9, 10, 11, ... - */ - return ($number % 100 == 1) ? 1 : (($number % 100 == 2) ? 2 : ((($number % 100 == 3) || ($number % 100 == 4)) ? 3 : 4)); - - case 11: - /** - * Families: Celtic (Irish Gaeilge) - * 1 - 1 - * 2 - 2 - * 3 - is 3-6: 3, 4, 5, 6 - * 4 - is 7-10: 7, 8, 9, 10 - * 5 - everything else: 0, 11, 12, ... - */ - return ($number == 1) ? 1 : (($number == 2) ? 2 : (($number >= 3 && $number <= 6) ? 3 : (($number >= 7 && $number <= 10) ? 4 : 5))); - - case 12: - /** - * Families: Semitic (Arabic) - * 1 - 1 - * 2 - 2 - * 3 - ends in 03-10: 3, 4, ... 10, 103, 104, ... 110, 203, 204, ... - * 4 - ends in 11-99: 11, ... 99, 111, 112, ... - * 5 - everything else: 100, 101, 102, 200, 201, 202, ... - * 6 - 0 - */ - 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)))); - - case 13: - /** - * Families: Semitic (Maltese) - * 1 - 1 - * 2 - is 0 or ends in 01-10: 0, 2, 3, ... 9, 10, 101, 102, ... - * 3 - ends in 11-19: 11, 12, ... 18, 19, 111, 112, ... - * 4 - everything else: 20, 21, ... - */ - return ($number == 1) ? 1 : ((($number == 0) || (($number % 100 > 1) && ($number % 100 < 11))) ? 2 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 3 : 4)); - - case 14: - /** - * Families: Slavic (Macedonian) - * 1 - ends in 1: 1, 11, 21, ... - * 2 - ends in 2: 2, 12, 22, ... - * 3 - everything else: 0, 3, 4, ... 10, 13, 14, ... 20, 23, ... - */ - return ($number % 10 == 1) ? 1 : (($number % 10 == 2) ? 2 : 3); - - case 15: - /** - * Families: Icelandic - * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, 131, ... - * 2 - everything else: 0, 2, 3, ... 10, 11, 12, ... 20, 22, ... - */ - return (($number % 10 == 1) && ($number % 100 != 11)) ? 1 : 2; - } -} - -/** * Login using http authenticate. * * @param array $param Parameter array, see $param_defaults array. diff --git a/phpBB/includes/functions_compatibility.php b/phpBB/includes/functions_compatibility.php index 2d064e37cb..8655203754 100644 --- a/phpBB/includes/functions_compatibility.php +++ b/phpBB/includes/functions_compatibility.php @@ -482,3 +482,22 @@ function phpbb_realpath($path) return $phpbb_filesystem->realpath($path); } + +/** + * Determine which plural form we should use. + * For some languages this is not as simple as for English. + * + * @param $rule int ID of the plural rule we want to use, see http://wiki.phpbb.com/Plural_Rules#Plural_Rules + * @param $number int|float The number we want to get the plural case for. Float numbers are floored. + * @return int The plural-case we need to use for the number plural-rule combination + * + * @deprecated 3.2.0-dev (To be removed: 3.3.0) + */ +function phpbb_get_plural_form($rule, $number) +{ + global $phpbb_container; + + /** @var \phpbb\language\language $language */ + $language = $phpbb_container->get('language'); + return $language->get_plural_form($number, $rule); +} diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php index c7234bb8e8..e8c2fbcbfa 100644 --- a/phpBB/includes/functions_user.php +++ b/phpBB/includes/functions_user.php @@ -3384,7 +3384,7 @@ function get_group_name($group_id) $row = $db->sql_fetchrow($result); $db->sql_freeresult($result); - if (!$row || ($row['group_type'] == GROUP_SPECIAL && empty($user->lang))) + if (!$row || ($row['group_type'] == GROUP_SPECIAL && !$user->is_setup())) { return ''; } diff --git a/phpBB/install/index.php b/phpBB/install/index.php index dd3590e854..df1229c9f2 100644 --- a/phpBB/install/index.php +++ b/phpBB/install/index.php @@ -241,7 +241,8 @@ $sub = $request->variable('sub', ''); // Set PHP error handler to ours set_error_handler(defined('PHPBB_MSG_HANDLER') ? PHPBB_MSG_HANDLER : 'msg_handler'); -$user = new \phpbb\user('\phpbb\datetime'); +$lang_service = new \phpbb\language\language(new \phpbb\language\language_file_loader($phpbb_root_path, $phpEx)); +$user = new \phpbb\user($lang_service, '\phpbb\datetime'); $auth = new \phpbb\auth\auth(); // Add own hook handler, if present. :o @@ -287,14 +288,15 @@ $twig_environment = new \phpbb\template\twig\environment( ); $phpbb_container->set('template.twig.environment', $twig_environment); +$twig_context = new \phpbb\template\context(); $template = new \phpbb\template\twig\twig( $phpbb_path_helper, $config, $user, - new \phpbb\template\context(), + $twig_context, $twig_environment, $cache_path, - array($phpbb_container->get('template.twig.extensions.phpbb')) + array(new \phpbb\template\twig\extension($twig_context, $user)) ); $paths = array($phpbb_root_path . 'install/update/new/adm/style', $phpbb_admin_path . 'style'); diff --git a/phpBB/phpbb/captcha/plugins/captcha_abstract.php b/phpBB/phpbb/captcha/plugins/captcha_abstract.php index 799947a84e..b29f144f97 100644 --- a/phpBB/phpbb/captcha/plugins/captcha_abstract.php +++ b/phpBB/phpbb/captcha/plugins/captcha_abstract.php @@ -195,7 +195,7 @@ abstract class captcha_abstract { global $config, $db, $user; - if (empty($user->lang)) + if (!$user->is_setup()) { $user->setup(); } diff --git a/phpBB/phpbb/language/exception/invalid_plural_rule_exception.php b/phpBB/phpbb/language/exception/invalid_plural_rule_exception.php new file mode 100644 index 0000000000..94e3466208 --- /dev/null +++ b/phpBB/phpbb/language/exception/invalid_plural_rule_exception.php @@ -0,0 +1,22 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +namespace phpbb\language\exception; + +/** + * Thrown when nonexistent plural rule is specified + */ +class invalid_plural_rule_exception extends language_exception +{ + +} diff --git a/phpBB/phpbb/language/exception/language_exception.php b/phpBB/phpbb/language/exception/language_exception.php new file mode 100644 index 0000000000..b1258414aa --- /dev/null +++ b/phpBB/phpbb/language/exception/language_exception.php @@ -0,0 +1,22 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +namespace phpbb\language\exception; + +/** + * Base exception class for language exceptions + */ +class language_exception extends \phpbb\exception\runtime_exception +{ + +} diff --git a/phpBB/phpbb/language/exception/language_file_not_found.php b/phpBB/phpbb/language/exception/language_file_not_found.php new file mode 100644 index 0000000000..89364267eb --- /dev/null +++ b/phpBB/phpbb/language/exception/language_file_not_found.php @@ -0,0 +1,22 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +namespace phpbb\language\exception; + +/** + * This exception is thrown when the language file is not found + */ +class language_file_not_found extends language_exception +{ + +} diff --git a/phpBB/phpbb/language/language.php b/phpBB/phpbb/language/language.php new file mode 100644 index 0000000000..9c9a3b8df1 --- /dev/null +++ b/phpBB/phpbb/language/language.php @@ -0,0 +1,562 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +namespace phpbb\language; + +use phpbb\language\exception\invalid_plural_rule_exception; + +/** + * Wrapper class for loading translations + */ +class language +{ + /** + * Global fallback language + * + * ISO code of the language to fallback to when the specified language entries + * cannot be found. + * + * @var string + */ + const FALLBACK_LANGUAGE = 'en'; + + /** + * @var array List of common language files + */ + protected $common_language_files; + + /** + * @var bool + */ + protected $common_language_files_loaded; + + /** + * @var string ISO code of the default board language + */ + protected $default_language; + + /** + * @var string ISO code of the User's language + */ + protected $user_language; + + /** + * @var array Language fallback array (the order is important) + */ + protected $language_fallback; + + /** + * @var array Array of language variables + */ + protected $lang; + + /** + * @var array Loaded language sets + */ + protected $loaded_language_sets; + + /** + * @var \phpbb\language\language_file_loader Language file loader + */ + protected $loader; + + /** + * Constructor + * + * @param \phpbb\language\language_file_loader $loader Language file loader + */ + public function __construct(language_file_loader $loader) + { + $this->loader = $loader; + + // Set up default information + $this->user_language = false; + $this->default_language = false; + $this->lang = array( + // For BC with user::help array + '__help' => array(), + ); + $this->loaded_language_sets = array( + 'core' => array(), + 'ext' => array(), + ); + + // Common language files + $this->common_language_files = array( + 'common', + ); + $this->common_language_files_loaded = false; + + $this->language_fallback = array(self::FALLBACK_LANGUAGE); + } + + /** + * Function to set user's language to display. + * + * @param string $user_lang_iso ISO code of the User's language + */ + public function set_user_language($user_lang_iso) + { + $this->user_language = $user_lang_iso; + + $this->set_fallback_array(); + } + + /** + * Function to set the board's default language to display. + * + * @param string $default_lang_iso ISO code of the board's default language + */ + public function set_default_language($default_lang_iso) + { + $this->default_language = $default_lang_iso; + + $this->set_fallback_array(); + } + + /** + * Returns language array + * + * Note: This function is needed for the BC purposes, until \phpbb\user::lang[] is + * not removed. + * + * @return array Array of loaded language strings + */ + public function get_lang_array() + { + // Load common language files if they not loaded yet + if (!$this->common_language_files_loaded) + { + $this->load_common_language_files(); + } + + return $this->lang; + } + + /** + * Add Language Items + * + * Note: $use_help is assigned where needed (only use them to force inclusion). + * + * Examples: + * <code> + * $component = array('posting'); + * $component = array('posting', 'viewtopic') + * $component = 'posting' + * </code> + * + * @param string|array $component The name of the language component to load + * @param string|null $extension_name Name of the extension to load component from, or null for core file + */ + public function add_lang($component, $extension_name = null) + { + // Load common language files if they not loaded yet + // This needs to be here to correctly merge language arrays + if (!$this->common_language_files_loaded) + { + $this->load_common_language_files(); + } + + if (!is_array($component)) + { + if (!is_null($extension_name)) + { + $this->load_extension($extension_name, $component); + } + else + { + $this->load_core_file($component); + } + } + else + { + foreach ($component as $lang_file) + { + $this->add_lang($lang_file, $extension_name); + } + } + } + + /** + * Advanced language substitution + * + * Function to mimic sprintf() with the possibility of using phpBB's language system to substitute nullar/singular/plural forms. + * Params are the language key and the parameters to be substituted. + * This function/functionality is inspired by SHS` and Ashe. + * + * Example call: <samp>$user->lang('NUM_POSTS_IN_QUEUE', 1);</samp> + * + * If the first parameter is an array, the elements are used as keys and subkeys to get the language entry: + * Example: <samp>$user->lang(array('datetime', 'AGO'), 1)</samp> uses $user->lang['datetime']['AGO'] as language entry. + * + * @return string Return localized string or the language key if the translation is not available + */ + public function lang() + { + // Load common language files if they not loaded yet + if (!$this->common_language_files_loaded) + { + $this->load_common_language_files(); + } + + $args = func_get_args(); + $key = $args[0]; + + if (is_array($key)) + { + $lang = &$this->lang[array_shift($key)]; + + foreach ($key as $_key) + { + $lang = &$lang[$_key]; + } + } + else + { + $lang = &$this->lang[$key]; + } + + // Return if language string does not exist + if (!isset($lang) || (!is_string($lang) && !is_array($lang))) + { + return $key; + } + + // If the language entry is a string, we simply mimic sprintf() behaviour + if (is_string($lang)) + { + if (sizeof($args) == 1) + { + return $lang; + } + + // Replace key with language entry and simply pass along... + $args[0] = $lang; + return call_user_func_array('sprintf', $args); + } + else if (sizeof($lang) == 0) + { + // If the language entry is an empty array, we just return the language key + return $args[0]; + } + + // It is an array... now handle different nullar/singular/plural forms + $key_found = false; + + // We now get the first number passed and will select the key based upon this number + for ($i = 1, $num_args = sizeof($args); $i < $num_args; $i++) + { + if (is_int($args[$i]) || is_float($args[$i])) + { + if ($args[$i] == 0 && isset($lang[0])) + { + // We allow each translation using plural forms to specify a version for the case of 0 things, + // so that "0 users" may be displayed as "No users". + $key_found = 0; + break; + } + else + { + $use_plural_form = $this->get_plural_form($args[$i]); + if (isset($lang[$use_plural_form])) + { + // The key we should use exists, so we use it. + $key_found = $use_plural_form; + } + else + { + // If the key we need to use does not exist, we fall back to the previous one. + $numbers = array_keys($lang); + + foreach ($numbers as $num) + { + if ($num > $use_plural_form) + { + break; + } + + $key_found = $num; + } + } + break; + } + } + } + + // Ok, let's check if the key was found, else use the last entry (because it is mostly the plural form) + if ($key_found === false) + { + $numbers = array_keys($lang); + $key_found = end($numbers); + } + + // Use the language string we determined and pass it to sprintf() + $args[0] = $lang[$key_found]; + return call_user_func_array('sprintf', $args); + } + + /** + * Loads common language files + */ + protected function load_common_language_files() + { + if (!$this->common_language_files_loaded) + { + foreach ($this->common_language_files as $lang_file) + { + $this->load_core_file($lang_file); + } + + $this->common_language_files_loaded = true; + } + } + + /** + * Determine which plural form we should use. + * + * For some languages this is not as simple as for English. + * + * @param int|float $number The number we want to get the plural case for. Float numbers are floored. + * @param int|bool $force_rule False to use the plural rule of the language package + * or an integer to force a certain plural rule + * + * @return int The plural-case we need to use for the number plural-rule combination + * + * @throws \phpbb\language\exception\invalid_plural_rule_exception When $force_rule has an invalid value + */ + public function get_plural_form($number, $force_rule = false) + { + $number = (int) $number; + $plural_rule = ($force_rule !== false) ? $force_rule : ((isset($this->lang['PLURAL_RULE'])) ? $this->lang['PLURAL_RULE'] : 1); + + if ($plural_rule > 15 || $plural_rule < 0) + { + throw new invalid_plural_rule_exception('INVALID_PLURAL_RULE', array( + 'plural_rule' => $plural_rule, + )); + } + + /** + * The following plural rules are based on a list published by the Mozilla Developer Network + * https://developer.mozilla.org/en/Localization_and_Plurals + */ + switch ($plural_rule) + { + case 0: + /** + * Families: Asian (Chinese, Japanese, Korean, Vietnamese), Persian, Turkic/Altaic (Turkish), Thai, Lao + * 1 - everything: 0, 1, 2, ... + */ + return 1; + + case 1: + /** + * 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) + * 1 - 1 + * 2 - everything else: 0, 2, 3, ... + */ + return ($number === 1) ? 1 : 2; + + case 2: + /** + * Families: Romanic (French, Brazilian Portuguese) + * 1 - 0, 1 + * 2 - everything else: 2, 3, ... + */ + return (($number === 0) || ($number === 1)) ? 1 : 2; + + case 3: + /** + * Families: Baltic (Latvian) + * 1 - 0 + * 2 - ends in 1, not 11: 1, 21, ... 101, 121, ... + * 3 - everything else: 2, 3, ... 10, 11, 12, ... 20, 22, ... + */ + return ($number === 0) ? 1 : ((($number % 10 === 1) && ($number % 100 != 11)) ? 2 : 3); + + case 4: + /** + * Families: Celtic (Scottish Gaelic) + * 1 - is 1 or 11: 1, 11 + * 2 - is 2 or 12: 2, 12 + * 3 - others between 3 and 19: 3, 4, ... 10, 13, ... 18, 19 + * 4 - everything else: 0, 20, 21, ... + */ + return ($number === 1 || $number === 11) ? 1 : (($number === 2 || $number === 12) ? 2 : (($number >= 3 && $number <= 19) ? 3 : 4)); + + case 5: + /** + * Families: Romanic (Romanian) + * 1 - 1 + * 2 - is 0 or ends in 01-19: 0, 2, 3, ... 19, 101, 102, ... 119, 201, ... + * 3 - everything else: 20, 21, ... + */ + return ($number === 1) ? 1 : ((($number === 0) || (($number % 100 > 0) && ($number % 100 < 20))) ? 2 : 3); + + case 6: + /** + * Families: Baltic (Lithuanian) + * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, ... + * 2 - ends in 0 or ends in 10-20: 0, 10, 11, 12, ... 19, 20, 30, 40, ... + * 3 - everything else: 2, 3, ... 8, 9, 22, 23, ... 29, 32, 33, ... + */ + return (($number % 10 === 1) && ($number % 100 != 11)) ? 1 : ((($number % 10 < 2) || (($number % 100 >= 10) && ($number % 100 < 20))) ? 2 : 3); + + case 7: + /** + * Families: Slavic (Croatian, Serbian, Russian, Ukrainian) + * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, ... + * 2 - ends in 2-4, not 12-14: 2, 3, 4, 22, 23, 24, 32, ... + * 3 - everything else: 0, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 25, 26, ... + */ + return (($number % 10 === 1) && ($number % 100 != 11)) ? 1 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 10) || ($number % 100 >= 20))) ? 2 : 3); + + case 8: + /** + * Families: Slavic (Slovak, Czech) + * 1 - 1 + * 2 - 2, 3, 4 + * 3 - everything else: 0, 5, 6, 7, ... + */ + return ($number === 1) ? 1 : ((($number >= 2) && ($number <= 4)) ? 2 : 3); + + case 9: + /** + * Families: Slavic (Polish) + * 1 - 1 + * 2 - ends in 2-4, not 12-14: 2, 3, 4, 22, 23, 24, 32, ... 104, 122, ... + * 3 - everything else: 0, 5, 6, ... 11, 12, 13, 14, 15, ... 20, 21, 25, ... + */ + return ($number === 1) ? 1 : ((($number % 10 >= 2) && ($number % 10 <= 4) && (($number % 100 < 12) || ($number % 100 > 14))) ? 2 : 3); + + case 10: + /** + * Families: Slavic (Slovenian, Sorbian) + * 1 - ends in 01: 1, 101, 201, ... + * 2 - ends in 02: 2, 102, 202, ... + * 3 - ends in 03-04: 3, 4, 103, 104, 203, 204, ... + * 4 - everything else: 0, 5, 6, 7, 8, 9, 10, 11, ... + */ + return ($number % 100 === 1) ? 1 : (($number % 100 === 2) ? 2 : ((($number % 100 === 3) || ($number % 100 === 4)) ? 3 : 4)); + + case 11: + /** + * Families: Celtic (Irish Gaeilge) + * 1 - 1 + * 2 - 2 + * 3 - is 3-6: 3, 4, 5, 6 + * 4 - is 7-10: 7, 8, 9, 10 + * 5 - everything else: 0, 11, 12, ... + */ + return ($number === 1) ? 1 : (($number === 2) ? 2 : (($number >= 3 && $number <= 6) ? 3 : (($number >= 7 && $number <= 10) ? 4 : 5))); + + case 12: + /** + * Families: Semitic (Arabic) + * 1 - 1 + * 2 - 2 + * 3 - ends in 03-10: 3, 4, ... 10, 103, 104, ... 110, 203, 204, ... + * 4 - ends in 11-99: 11, ... 99, 111, 112, ... + * 5 - everything else: 100, 101, 102, 200, 201, 202, ... + * 6 - 0 + */ + 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)))); + + case 13: + /** + * Families: Semitic (Maltese) + * 1 - 1 + * 2 - is 0 or ends in 01-10: 0, 2, 3, ... 9, 10, 101, 102, ... + * 3 - ends in 11-19: 11, 12, ... 18, 19, 111, 112, ... + * 4 - everything else: 20, 21, ... + */ + return ($number === 1) ? 1 : ((($number === 0) || (($number % 100 > 1) && ($number % 100 < 11))) ? 2 : ((($number % 100 > 10) && ($number % 100 < 20)) ? 3 : 4)); + + case 14: + /** + * Families: Slavic (Macedonian) + * 1 - ends in 1: 1, 11, 21, ... + * 2 - ends in 2: 2, 12, 22, ... + * 3 - everything else: 0, 3, 4, ... 10, 13, 14, ... 20, 23, ... + */ + return ($number % 10 === 1) ? 1 : (($number % 10 === 2) ? 2 : 3); + + case 15: + /** + * Families: Icelandic + * 1 - ends in 1, not 11: 1, 21, 31, ... 101, 121, 131, ... + * 2 - everything else: 0, 2, 3, ... 10, 11, 12, ... 20, 22, ... + */ + return (($number % 10 === 1) && ($number % 100 != 11)) ? 1 : 2; + } + } + + /** + * Returns language fallback data + * + * @return array + */ + protected function set_fallback_array() + { + $fallback_array = array(); + + if ($this->user_language !== false) + { + $fallback_array[] = $this->user_language; + } + + if ($this->default_language !== false) + { + $fallback_array[] = $this->default_language; + } + + $fallback_array[] = self::FALLBACK_LANGUAGE; + + $this->language_fallback = $fallback_array; + } + + /** + * Load core language file + * + * @param string $component Name of the component to load + */ + protected function load_core_file($component) + { + // Check if the component is already loaded + if (isset($this->loaded_language_sets['core'][$component])) + { + return; + } + + $this->loader->load($component, $this->language_fallback, $this->lang); + $this->loaded_language_sets['core'][$component] = true; + } + + /** + * Load extension language file + * + * @param string $extension_name Name of the extension to load language from + * @param string $component Name of the component to load + */ + protected function load_extension($extension_name, $component) + { + // Check if the component is already loaded + if (isset($this->loaded_language_sets['ext'][$extension_name][$component])) + { + return; + } + + $this->loader->load_extension($extension_name, $component, $this->language_fallback, $this->lang); + $this->loaded_language_sets['ext'][$extension_name][$component] = true; + } +} diff --git a/phpBB/phpbb/language/language_file_helper.php b/phpBB/phpbb/language/language_file_helper.php new file mode 100644 index 0000000000..18d7b62e21 --- /dev/null +++ b/phpBB/phpbb/language/language_file_helper.php @@ -0,0 +1,71 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +namespace phpbb\language; + +use Symfony\Component\Finder\Finder; + +/** + * Helper class for language file related functions + */ +class language_file_helper +{ + /** + * @var string Path to phpBB's root + */ + protected $phpbb_root_path; + + /** + * Constructor + * + * @param string $phpbb_root_path Path to phpBB's root + */ + public function __construct($phpbb_root_path) + { + $this->phpbb_root_path = $phpbb_root_path; + } + + /** + * Returns available languages + * + * @return array + */ + public function get_available_languages() + { + // Find available language packages + $finder = new Finder(); + $finder->files() + ->name('iso.txt') + ->depth('== 1') + ->in($this->phpbb_root_path . 'language'); + + $available_languages = array(); + foreach ($finder as $file) + { + $path = $file->getRelativePath(); + $info = explode("\n", $file->getContents()); + + $available_languages[] = array( + // Get the name of the directory containing iso.txt + 'iso' => $path, + + // Recover data from file + 'name' => trim($info[0]), + 'local_name' => trim($info[1]), + 'author' => trim($info[2]) + ); + } + + return $available_languages; + } +} diff --git a/phpBB/phpbb/language/language_file_loader.php b/phpBB/phpbb/language/language_file_loader.php new file mode 100644 index 0000000000..510a29279a --- /dev/null +++ b/phpBB/phpbb/language/language_file_loader.php @@ -0,0 +1,212 @@ +<?php +/** + * + * This file is part of the phpBB Forum Software package. + * + * @copyright (c) phpBB Limited <https://www.phpbb.com> + * @license GNU General Public License, version 2 (GPL-2.0) + * + * For full copyright and license information, please see + * the docs/CREDITS.txt file. + * + */ + +namespace phpbb\language; + +use \phpbb\language\exception\language_file_not_found; + +/** + * Language file loader + */ +class language_file_loader +{ + /** + * @var string Path to phpBB's root + */ + protected $phpbb_root_path; + + /** + * @var string Extension of PHP files + */ + protected $php_ext; + + /** + * @var \phpbb\extension\manager Extension manager + */ + protected $extension_manager; + + /** + * Constructor + * + * @param string $phpbb_root_path Path to phpBB's root + * @param string $php_ext Extension of PHP files + */ + public function __construct($phpbb_root_path, $php_ext) + { + $this->phpbb_root_path = $phpbb_root_path; + $this->php_ext = $php_ext; + + $this->extension_manager = null; + } + + /** + * Extension manager setter + * + * @param \phpbb\extension\manager $extension_manager Extension manager + */ + public function set_extension_manager(\phpbb\extension\manager $extension_manager) + { + $this->extension_manager = $extension_manager; + } + + /** + * Loads language array for the given component + * + * @param string $component Name of the language component + * @param string|array $locale ISO code of the language to load, or array of ISO codes if you want to + * specify additional language fallback steps + * @param array $lang Array reference containing language strings + */ + public function load($component, $locale, &$lang) + { + $locale = (array) $locale; + + // Determine path to language directory + $path = $this->phpbb_root_path . 'language/'; + + $this->load_file($path, $component, $locale, $lang); + } + + /** + * Loads language array for the given extension component + * + * @param string $extension Name of the extension + * @param string $component Name of the language component + * @param string|array $locale ISO code of the language to load, or array of ISO codes if you want to + * specify additional language fallback steps + * @param array $lang Array reference containing language strings + */ + public function load_extension($extension, $component, $locale, &$lang) + { + // Check if extension manager was loaded + if ($this->extension_manager === null) + { + // If not, let's return + return; + } + + $locale = (array) $locale; + + // Determine path to language directory + $path = $this->extension_manager->get_extension_path($extension, true) . 'language/'; + + $this->load_file($path, $component, $locale, $lang); + } + + /** + * Prepares language file loading + * + * @param string $path Path to search for file in + * @param string $component Name of the language component + * @param array $locale Array containing language fallback options + * @param array $lang Array reference of language strings + */ + protected function load_file($path, $component, $locale, &$lang) + { + // This is BC stuff and not the best idea as it makes language fallback + // implementation quite hard like below. + if (strpos($this->phpbb_root_path . $component, $path) === 0) + { + // Filter out the path + $path_diff = str_replace($path, '', dirname($this->phpbb_root_path . $component)); + $language_file = basename($component, '.' . $this->php_ext); + $component = ''; + + // This step is needed to resolve language/en/subdir style $component + // $path already points to the language base directory so we need to eliminate + // the first directory from the path (that should be the language directory) + $path_diff_parts = explode('/', $path_diff); + + if (sizeof($path_diff_parts) > 1) + { + array_shift($path_diff_parts); + $component = implode('/', $path_diff_parts) . '/'; + } + + $component .= $language_file; + } + + // Determine filename + $filename = $component . '.' . $this->php_ext; + + // Determine path to file + $file_path = $this->get_language_file_path($path, $filename, $locale); + + // Load language array + $this->load_language_file($file_path, $lang); + } + + /** + * This function implements language fallback logic + * + * @param string $path Path to language directory + * @param string $filename Filename to load language strings from + * + * @return string Relative path to language file + * + * @throws \phpbb\language\exception\language_file_not_exists When the path to the file cannot be resolved + */ + protected function get_language_file_path($path, $filename, $locales) + { + // Language fallback logic + foreach ($locales as $locale) + { + $language_file_path = $path . $locale . '/' . $filename; + + // If we are in install, try to use the updated version, when available + if (defined('IN_INSTALL')) + { + $install_language_path = str_replace('language/', 'install/update/new/language/', $language_file_path); + if (file_exists($install_language_path)) + { + return $install_language_path; + } + } + + if (file_exists($language_file_path)) + { + return $language_file_path; + } + } + + // The language file is not exist + throw new language_file_not_found('Language file ' . $language_file_path . ' couldn\'t be opened.'); + } + + /** + * Loads language file + * + * @param string $path Path to language file to load + * @param array $lang Reference of the array of language strings + */ + protected function load_language_file($path, &$lang) + { + // BC code for language files with help + $help = array(); + + // Do not suppress error if in DEBUG mode + if (defined('DEBUG')) + { + include $path; + } + else + { + @include $path; + } + + if (!empty($help)) + { + $lang['__help'] = array_merge($lang['__help'], $help); + } + } +} diff --git a/phpBB/phpbb/user.php b/phpBB/phpbb/user.php index 882e9cef26..c33070d6f4 100644 --- a/phpBB/phpbb/user.php +++ b/phpBB/phpbb/user.php @@ -21,8 +21,11 @@ namespace phpbb; */ class user extends \phpbb\session { - var $lang = array(); - var $help = array(); + /** + * @var \phpbb\language\language + */ + protected $language; + var $style = array(); var $date_format; @@ -42,35 +45,63 @@ class user extends \phpbb\session var $img_lang; var $img_array = array(); + /** @var bool */ + protected $is_setup_flag; + // Able to add new options (up to id 31) var $keyoptions = array('viewimg' => 0, 'viewflash' => 1, 'viewsmilies' => 2, 'viewsigs' => 3, 'viewavatars' => 4, 'viewcensors' => 5, 'attachsig' => 6, 'bbcode' => 8, 'smilies' => 9, 'sig_bbcode' => 15, 'sig_smilies' => 16, 'sig_links' => 17); /** * Constructor to set the lang path + * * @param string $datetime_class Class name of datetime class + * @param \phpbb\language\language $lang phpBB's Language loader */ - function __construct($datetime_class) + function __construct(\phpbb\language\language $lang, $datetime_class) { global $phpbb_root_path; $this->lang_path = $phpbb_root_path . 'language/'; + $this->language = $lang; $this->datetime = $datetime_class; + + $this->is_setup_flag = false; } /** - * Function to set custom language path (able to use directory outside of phpBB) - * - * @param string $lang_path New language path used. - * @access public - */ - function set_custom_lang_path($lang_path) + * Returns whether user::setup was called + * + * @return bool + */ + public function is_setup() { - $this->lang_path = $lang_path; + return $this->is_setup_flag; + } - if (substr($this->lang_path, -1) != '/') + /** + * Magic getter for BC compatibility + * + * Implement array access for user::lang. + * + * @param string $param_name Name of the BC component the user want to access + * + * @return array The appropriate array + * + * @deprecated 3.2.0-dev (To be removed: 4.0.0) + */ + public function __get($param_name) + { + if ($param_name === 'lang') + { + return $this->language->get_lang_array(); + } + else if ($param_name === 'help') { - $this->lang_path .= '/'; + $help_array = $this->language->get_lang_array(); + return $help_array['__help']; } + + return array(); } /** @@ -81,6 +112,8 @@ class user extends \phpbb\session global $db, $request, $template, $config, $auth, $phpEx, $phpbb_root_path, $cache; global $phpbb_dispatcher; + $this->language->set_default_language($config['default_lang']); + if ($this->data['user_id'] != ANONYMOUS) { $user_lang_name = (file_exists($this->lang_path . $this->data['user_lang'] . "/common.$phpEx")) ? $this->data['user_lang'] : basename($config['default_lang']); @@ -98,6 +131,7 @@ class user extends \phpbb\session { $lang_override = $request->variable($config['cookie_name'] . '_lang', '', true, \phpbb\request\request_interface::COOKIE); } + if ($lang_override) { $use_lang = basename($lang_override); @@ -108,6 +142,7 @@ class user extends \phpbb\session { $user_lang_name = basename($config['default_lang']); } + $user_date_format = $config['default_dateformat']; $user_timezone = $config['board_timezone']; @@ -187,6 +222,8 @@ class user extends \phpbb\session $this->lang_name = $user_lang_name; $this->date_format = $user_date_format; + $this->language->set_user_language($user_lang_name); + try { $this->timezone = new \DateTimeZone($user_timezone); @@ -197,17 +234,6 @@ class user extends \phpbb\session $this->timezone = new \DateTimeZone('UTC'); } - // We include common language file here to not load it every time a custom language file is included - $lang = &$this->lang; - - // Do not suppress error if in DEBUG mode - $include_result = (defined('DEBUG')) ? (include $this->lang_path . $this->lang_name . "/common.$phpEx") : (@include $this->lang_path . $this->lang_name . "/common.$phpEx"); - - if ($include_result === false) - { - die('Language file ' . $this->lang_path . $this->lang_name . "/common.$phpEx" . " couldn't be opened."); - } - $this->add_lang($lang_set); unset($lang_set); @@ -393,6 +419,8 @@ class user extends \phpbb\session } } + $this->is_setup_flag = true; + return; } @@ -406,103 +434,13 @@ class user extends \phpbb\session * * If the first parameter is an array, the elements are used as keys and subkeys to get the language entry: * Example: <samp>$user->lang(array('datetime', 'AGO'), 1)</samp> uses $user->lang['datetime']['AGO'] as language entry. + * + * @deprecated 3.2.0-dev (To be removed 4.0.0) */ function lang() { $args = func_get_args(); - $key = $args[0]; - - if (is_array($key)) - { - $lang = &$this->lang[array_shift($key)]; - - foreach ($key as $_key) - { - $lang = &$lang[$_key]; - } - } - else - { - $lang = &$this->lang[$key]; - } - - // Return if language string does not exist - if (!isset($lang) || (!is_string($lang) && !is_array($lang))) - { - return $key; - } - - // If the language entry is a string, we simply mimic sprintf() behaviour - if (is_string($lang)) - { - if (sizeof($args) == 1) - { - return $lang; - } - - // Replace key with language entry and simply pass along... - $args[0] = $lang; - return call_user_func_array('sprintf', $args); - } - else if (sizeof($lang) == 0) - { - // If the language entry is an empty array, we just return the language key - return $args[0]; - } - - // It is an array... now handle different nullar/singular/plural forms - $key_found = false; - - // We now get the first number passed and will select the key based upon this number - for ($i = 1, $num_args = sizeof($args); $i < $num_args; $i++) - { - if (is_int($args[$i]) || is_float($args[$i])) - { - if ($args[$i] == 0 && isset($lang[0])) - { - // We allow each translation using plural forms to specify a version for the case of 0 things, - // so that "0 users" may be displayed as "No users". - $key_found = 0; - break; - } - else - { - $use_plural_form = $this->get_plural_form($args[$i]); - if (isset($lang[$use_plural_form])) - { - // The key we should use exists, so we use it. - $key_found = $use_plural_form; - } - else - { - // If the key we need to use does not exist, we fall back to the previous one. - $numbers = array_keys($lang); - - foreach ($numbers as $num) - { - if ($num > $use_plural_form) - { - break; - } - - $key_found = $num; - } - } - break; - } - } - } - - // Ok, let's check if the key was found, else use the last entry (because it is mostly the plural form) - if ($key_found === false) - { - $numbers = array_keys($lang); - $key_found = end($numbers); - } - - // Use the language string we determined and pass it to sprintf() - $args[0] = $lang[$key_found]; - return call_user_func_array('sprintf', $args); + return call_user_func_array(array($this->language, 'lang'), $args); } /** @@ -512,24 +450,22 @@ class user extends \phpbb\session * @param $number int|float The number we want to get the plural case for. Float numbers are floored. * @param $force_rule mixed False to use the plural rule of the language package * or an integer to force a certain plural rule - * @return int The plural-case we need to use for the number plural-rule combination + * @return int|bool The plural-case we need to use for the number plural-rule combination, false if $force_rule + * was invalid. + * + * @deprecated: 3.2.0-dev (To be removed: 3.3.0) */ function get_plural_form($number, $force_rule = false) { - $number = (int) $number; - - // Default to English system - $plural_rule = ($force_rule !== false) ? $force_rule : ((isset($this->lang['PLURAL_RULE'])) ? $this->lang['PLURAL_RULE'] : 1); - - return phpbb_get_plural_form($plural_rule, $number); + return $this->language->get_plural_form($number, $force_rule); } /** * Add Language Items - use_db and use_help are assigned where needed (only use them to force inclusion) * * @param mixed $lang_set specifies the language entries to include - * @param bool $use_db internal variable for recursion, do not use - * @param bool $use_help internal variable for recursion, do not use + * @param bool $use_db internal variable for recursion, do not use @deprecated 3.2.0-dev (To be removed: 3.3.0) + * @param bool $use_help internal variable for recursion, do not use @deprecated 3.2.0-dev (To be removed: 3.3.0) * @param string $ext_name The extension to load language from, or empty for core files * * Examples: @@ -540,11 +476,14 @@ class user extends \phpbb\session * $lang_set = 'posting' * $lang_set = array('help' => 'faq', 'db' => array('help:faq', 'posting')) * </code> + * + * Note: $use_db and $use_help should be removed. The old function was kept for BC purposes, + * so the BC logic is handled here. + * + * @deprecated: 3.2.0-dev (To be removed: 3.3.0) */ function add_lang($lang_set, $use_db = false, $use_help = false, $ext_name = '') { - global $phpEx; - if (is_array($lang_set)) { foreach ($lang_set as $key => $lang_file) @@ -555,6 +494,7 @@ class user extends \phpbb\session if ($key == 'db') { + // This is never used $this->add_lang($lang_file, true, $use_help, $ext_name); } else if ($key == 'help') @@ -563,7 +503,7 @@ class user extends \phpbb\session } else if (!is_array($lang_file)) { - $this->set_lang($this->lang, $this->help, $lang_file, $use_db, $use_help, $ext_name); + $this->set_lang($lang_file, $use_help, $ext_name); } else { @@ -574,8 +514,37 @@ class user extends \phpbb\session } else if ($lang_set) { - $this->set_lang($this->lang, $this->help, $lang_set, $use_db, $use_help, $ext_name); + $this->set_lang($lang_set, $use_help, $ext_name); + } + } + + /** + * BC function for loading language files + * + * @deprecated 3.2.0-dev (To be removed: 3.3.0) + */ + private function set_lang($lang_set, $use_help, $ext_name) + { + if (empty($ext_name)) + { + $ext_name = null; + } + + if ($use_help && strpos($lang_set, '/') !== false) + { + $component = dirname($lang_set) . '/help_' . basename($lang_set); + + if ($component[0] === '/') + { + $component = substr($component, 1); + } + } + else + { + $component = (($use_help) ? 'help_' : '') . $lang_set; } + + $this->language->add_lang($component, $ext_name); } /** @@ -585,6 +554,10 @@ class user extends \phpbb\session * @param mixed $lang_set specifies the language entries to include * @param bool $use_db internal variable for recursion, do not use * @param bool $use_help internal variable for recursion, do not use + * + * Note: $use_db and $use_help should be removed. Kept for BC purposes. + * + * @deprecated: 3.2.0-dev (To be removed: 3.3.0) */ function add_lang_ext($ext_name, $lang_set, $use_db = false, $use_help = false) { @@ -597,109 +570,6 @@ class user extends \phpbb\session } /** - * Set language entry (called by add_lang) - * @access private - */ - function set_lang(&$lang, &$help, $lang_file, $use_db = false, $use_help = false, $ext_name = '') - { - global $phpbb_root_path, $phpEx; - - // Make sure the language name is set (if the user setup did not happen it is not set) - if (!$this->lang_name) - { - global $config; - $this->lang_name = basename($config['default_lang']); - } - - // $lang == $this->lang - // $help == $this->help - // - add appropriate variables here, name them as they are used within the language file... - if (!$use_db) - { - if ($use_help && strpos($lang_file, '/') !== false) - { - $filename = dirname($lang_file) . '/help_' . basename($lang_file); - } - else - { - $filename = (($use_help) ? 'help_' : '') . $lang_file; - } - - if ($ext_name) - { - global $phpbb_extension_manager; - $ext_path = $phpbb_extension_manager->get_extension_path($ext_name, true); - - $lang_path = $ext_path . 'language/'; - } - else - { - $lang_path = $this->lang_path; - } - - if (strpos($phpbb_root_path . $filename, $lang_path . $this->lang_name . '/') === 0) - { - $language_filename = $phpbb_root_path . $filename; - } - else - { - $language_filename = $lang_path . $this->lang_name . '/' . $filename . '.' . $phpEx; - } - - // If we are in install, try to use the updated version, when available - $install_language_filename = str_replace('language/', 'install/update/new/language/', $language_filename); - if (defined('IN_INSTALL') && file_exists($install_language_filename)) - { - $language_filename = $install_language_filename; - } - - if (!file_exists($language_filename)) - { - global $config; - - if ($this->lang_name == 'en') - { - // The user's selected language is missing the file, the board default's language is missing the file, and the file doesn't exist in /en. - $language_filename = str_replace($lang_path . 'en', $lang_path . $this->data['user_lang'], $language_filename); - trigger_error('Language file ' . $language_filename . ' couldn\'t be opened.', E_USER_ERROR); - } - else if ($this->lang_name == basename($config['default_lang'])) - { - // Fall back to the English Language - $reset_lang_name = $this->lang_name; - $this->lang_name = 'en'; - $this->set_lang($lang, $help, $lang_file, $use_db, $use_help, $ext_name); - $this->lang_name = $reset_lang_name; - } - else if ($this->lang_name == $this->data['user_lang']) - { - // Fall back to the board default language - $reset_lang_name = $this->lang_name; - $this->lang_name = basename($config['default_lang']); - $this->set_lang($lang, $help, $lang_file, $use_db, $use_help, $ext_name); - $this->lang_name = $reset_lang_name; - } - - return; - } - - // Do not suppress error if in DEBUG mode - $include_result = (defined('DEBUG')) ? (include $language_filename) : (@include $language_filename); - - if ($include_result === false) - { - trigger_error('Language file ' . $language_filename . ' couldn\'t be opened.', E_USER_ERROR); - } - } - else if ($use_db) - { - // Get Database Language Strings - // Put them into $lang if nothing is prefixed, put them into $help if help: is prefixed - // For example: help:faq, posting - } - } - - /** * Format user date * * @param int $gmepoch unix timestamp @@ -808,7 +678,7 @@ class user extends \phpbb\session if ($alt) { - $alt = $this->lang($alt); + $alt = $this->language->lang($alt); $title = ' title="' . $alt . '"'; } return '<span class="imageset ' . $img . '"' . $title . '>' . $alt . '</span>'; |