|
|
<?php |
|
|
|
|
|
declare(strict_types=1); |
|
|
|
|
|
namespace PhpMyAdmin; |
|
|
|
|
|
use function __; |
|
|
use function closedir; |
|
|
use function count; |
|
|
use function explode; |
|
|
use function file_exists; |
|
|
use function is_dir; |
|
|
use function opendir; |
|
|
use function preg_grep; |
|
|
use function readdir; |
|
|
use function strtolower; |
|
|
use function trigger_error; |
|
|
use function uasort; |
|
|
use function ucfirst; |
|
|
|
|
|
use const E_USER_ERROR; |
|
|
|
|
|
/** |
|
|
* Language selection manager |
|
|
*/ |
|
|
class LanguageManager |
|
|
{ |
|
|
/** |
|
|
* Definition data for languages |
|
|
* |
|
|
* Each member contains: |
|
|
* - Language code |
|
|
* - English language name |
|
|
* - Native language name |
|
|
* - Match regular expression |
|
|
* - MySQL locale |
|
|
* |
|
|
* @var array<string, string[]> |
|
|
* @psalm-var array<string, array{non-empty-string, non-empty-string, string, non-empty-string, string}> |
|
|
*/ |
|
|
private static $languageData = [ |
|
|
'af' => [ |
|
|
'af', |
|
|
'Afrikaans', |
|
|
'', |
|
|
'af|afrikaans', |
|
|
'', |
|
|
], |
|
|
'am' => [ |
|
|
'am', |
|
|
'Amharic', |
|
|
'አማርኛ', |
|
|
'am|amharic', |
|
|
'', |
|
|
], |
|
|
'ar' => [ |
|
|
'ar', |
|
|
'Arabic', |
|
|
'العربية', |
|
|
'ar|arabic', |
|
|
'ar_AE', |
|
|
], |
|
|
'ar_ly' => [ |
|
|
'ar_LY', |
|
|
'Arabic (Libya)', |
|
|
'ليبي', |
|
|
'ar[_-]ly|arabic (libya)|libian arabic', |
|
|
'ar_LY', |
|
|
], |
|
|
'az' => [ |
|
|
'az', |
|
|
'Azerbaijani', |
|
|
'Azərbaycanca', |
|
|
'az|azerbaijani', |
|
|
'', |
|
|
], |
|
|
'bn' => [ |
|
|
'bn', |
|
|
'Bangla', |
|
|
'বাংলা', |
|
|
'bn|bangla', |
|
|
'', |
|
|
], |
|
|
'be' => [ |
|
|
'be', |
|
|
'Belarusian', |
|
|
'Беларуская', |
|
|
'be|belarusian', |
|
|
'be_BY', |
|
|
], |
|
|
'be@latin' => [ |
|
|
'be@latin', |
|
|
'Belarusian (latin)', |
|
|
'Biełaruskaja', |
|
|
'be[-_]lat|be@latin|belarusian latin', |
|
|
'', |
|
|
], |
|
|
'ber' => [ |
|
|
'ber', |
|
|
'Berber', |
|
|
'Tamaziɣt', |
|
|
'ber|berber', |
|
|
'', |
|
|
], |
|
|
'bg' => [ |
|
|
'bg', |
|
|
'Bulgarian', |
|
|
'Български', |
|
|
'bg|bulgarian', |
|
|
'bg_BG', |
|
|
], |
|
|
'bs' => [ |
|
|
'bs', |
|
|
'Bosnian', |
|
|
'Bosanski', |
|
|
'bs|bosnian', |
|
|
'', |
|
|
], |
|
|
'br' => [ |
|
|
'br', |
|
|
'Breton', |
|
|
'Brezhoneg', |
|
|
'br|breton', |
|
|
'', |
|
|
], |
|
|
'brx' => [ |
|
|
'brx', |
|
|
'Bodo', |
|
|
'बड़ो', |
|
|
'brx|bodo', |
|
|
'', |
|
|
], |
|
|
'ca' => [ |
|
|
'ca', |
|
|
'Catalan', |
|
|
'Català', |
|
|
'ca|catalan', |
|
|
'ca_ES', |
|
|
], |
|
|
'ckb' => [ |
|
|
'ckb', |
|
|
'Sorani', |
|
|
'سۆرانی', |
|
|
'ckb|sorani', |
|
|
'', |
|
|
], |
|
|
'cs' => [ |
|
|
'cs', |
|
|
'Czech', |
|
|
'Čeština', |
|
|
'cs|czech', |
|
|
'cs_CZ', |
|
|
], |
|
|
'cy' => [ |
|
|
'cy', |
|
|
'Welsh', |
|
|
'Cymraeg', |
|
|
'cy|welsh', |
|
|
'', |
|
|
], |
|
|
'da' => [ |
|
|
'da', |
|
|
'Danish', |
|
|
'Dansk', |
|
|
'da|danish', |
|
|
'da_DK', |
|
|
], |
|
|
'de' => [ |
|
|
'de', |
|
|
'German', |
|
|
'Deutsch', |
|
|
'de|german', |
|
|
'de_DE', |
|
|
], |
|
|
'el' => [ |
|
|
'el', |
|
|
'Greek', |
|
|
'Ελληνικά', |
|
|
'el|greek', |
|
|
'', |
|
|
], |
|
|
'en' => [ |
|
|
'en', |
|
|
'English', |
|
|
'', |
|
|
'en|english', |
|
|
'en_US', |
|
|
], |
|
|
'en_gb' => [ |
|
|
'en_GB', |
|
|
'English (United Kingdom)', |
|
|
'', |
|
|
'en[_-]gb|english (United Kingdom)', |
|
|
'en_GB', |
|
|
], |
|
|
'enm' => [ |
|
|
'enm', |
|
|
'English (Middle)', |
|
|
'', |
|
|
'enm|english (middle)', |
|
|
'', |
|
|
], |
|
|
'eo' => [ |
|
|
'eo', |
|
|
'Esperanto', |
|
|
'Esperanto', |
|
|
'eo|esperanto', |
|
|
'', |
|
|
], |
|
|
'es' => [ |
|
|
'es', |
|
|
'Spanish', |
|
|
'Español', |
|
|
'es|spanish', |
|
|
'es_ES', |
|
|
], |
|
|
'et' => [ |
|
|
'et', |
|
|
'Estonian', |
|
|
'Eesti', |
|
|
'et|estonian', |
|
|
'et_EE', |
|
|
], |
|
|
'eu' => [ |
|
|
'eu', |
|
|
'Basque', |
|
|
'Euskara', |
|
|
'eu|basque', |
|
|
'eu_ES', |
|
|
], |
|
|
'fa' => [ |
|
|
'fa', |
|
|
'Persian', |
|
|
'فارسی', |
|
|
'fa|persian', |
|
|
'', |
|
|
], |
|
|
'fi' => [ |
|
|
'fi', |
|
|
'Finnish', |
|
|
'Suomi', |
|
|
'fi|finnish', |
|
|
'fi_FI', |
|
|
], |
|
|
'fil' => [ |
|
|
'fil', |
|
|
'Filipino', |
|
|
'Pilipino', |
|
|
'fil|filipino', |
|
|
'', |
|
|
], |
|
|
'fr' => [ |
|
|
'fr', |
|
|
'French', |
|
|
'Français', |
|
|
'fr|french', |
|
|
'fr_FR', |
|
|
], |
|
|
'fy' => [ |
|
|
'fy', |
|
|
'Frisian', |
|
|
'Frysk', |
|
|
'fy|frisian', |
|
|
'', |
|
|
], |
|
|
'gl' => [ |
|
|
'gl', |
|
|
'Galician', |
|
|
'Galego', |
|
|
'gl|galician', |
|
|
'gl_ES', |
|
|
], |
|
|
'gu' => [ |
|
|
'gu', |
|
|
'Gujarati', |
|
|
'ગુજરાતી', |
|
|
'gu|gujarati', |
|
|
'gu_IN', |
|
|
], |
|
|
'he' => [ |
|
|
'he', |
|
|
'Hebrew', |
|
|
'עברית', |
|
|
'he|hebrew', |
|
|
'he_IL', |
|
|
], |
|
|
'hi' => [ |
|
|
'hi', |
|
|
'Hindi', |
|
|
'हिन्दी', |
|
|
'hi|hindi', |
|
|
'hi_IN', |
|
|
], |
|
|
'hr' => [ |
|
|
'hr', |
|
|
'Croatian', |
|
|
'Hrvatski', |
|
|
'hr|croatian', |
|
|
'hr_HR', |
|
|
], |
|
|
'hu' => [ |
|
|
'hu', |
|
|
'Hungarian', |
|
|
'Magyar', |
|
|
'hu|hungarian', |
|
|
'hu_HU', |
|
|
], |
|
|
'hy' => [ |
|
|
'hy', |
|
|
'Armenian', |
|
|
'Հայերէն', |
|
|
'hy|armenian', |
|
|
'', |
|
|
], |
|
|
'ia' => [ |
|
|
'ia', |
|
|
'Interlingua', |
|
|
'', |
|
|
'ia|interlingua', |
|
|
'', |
|
|
], |
|
|
'id' => [ |
|
|
'id', |
|
|
'Indonesian', |
|
|
'Bahasa Indonesia', |
|
|
'id|indonesian', |
|
|
'id_ID', |
|
|
], |
|
|
'ig' => [ |
|
|
'ig', |
|
|
'Igbo', |
|
|
'Asụsụ Igbo', |
|
|
'ig|igbo', |
|
|
'', |
|
|
], |
|
|
'it' => [ |
|
|
'it', |
|
|
'Italian', |
|
|
'Italiano', |
|
|
'it|italian', |
|
|
'it_IT', |
|
|
], |
|
|
'ja' => [ |
|
|
'ja', |
|
|
'Japanese', |
|
|
'日本語', |
|
|
'ja|japanese', |
|
|
'ja_JP', |
|
|
], |
|
|
'ko' => [ |
|
|
'ko', |
|
|
'Korean', |
|
|
'한국어', |
|
|
'ko|korean', |
|
|
'ko_KR', |
|
|
], |
|
|
'ka' => [ |
|
|
'ka', |
|
|
'Georgian', |
|
|
'ქართული', |
|
|
'ka|georgian', |
|
|
'', |
|
|
], |
|
|
'kab' => [ |
|
|
'kab', |
|
|
'Kabylian', |
|
|
'Taqbaylit', |
|
|
'kab|kabylian', |
|
|
'', |
|
|
], |
|
|
'kk' => [ |
|
|
'kk', |
|
|
'Kazakh', |
|
|
'Қазақ', |
|
|
'kk|kazakh', |
|
|
'', |
|
|
], |
|
|
'km' => [ |
|
|
'km', |
|
|
'Khmer', |
|
|
'ខ្មែរ', |
|
|
'km|khmer', |
|
|
'', |
|
|
], |
|
|
'kn' => [ |
|
|
'kn', |
|
|
'Kannada', |
|
|
'ಕನ್ನಡ', |
|
|
'kn|kannada', |
|
|
'', |
|
|
], |
|
|
'ksh' => [ |
|
|
'ksh', |
|
|
'Colognian', |
|
|
'Kölsch', |
|
|
'ksh|colognian', |
|
|
'', |
|
|
], |
|
|
'ku' => [ |
|
|
'ku', |
|
|
'Kurdish', |
|
|
'کوردی', |
|
|
'ku|kurdish', |
|
|
'', |
|
|
], |
|
|
'ky' => [ |
|
|
'ky', |
|
|
'Kyrgyz', |
|
|
'Кыргызча', |
|
|
'ky|kyrgyz', |
|
|
'', |
|
|
], |
|
|
'li' => [ |
|
|
'li', |
|
|
'Limburgish', |
|
|
'Lèmbörgs', |
|
|
'li|limburgish', |
|
|
'', |
|
|
], |
|
|
'lt' => [ |
|
|
'lt', |
|
|
'Lithuanian', |
|
|
'Lietuvių', |
|
|
'lt|lithuanian', |
|
|
'lt_LT', |
|
|
], |
|
|
'lv' => [ |
|
|
'lv', |
|
|
'Latvian', |
|
|
'Latviešu', |
|
|
'lv|latvian', |
|
|
'lv_LV', |
|
|
], |
|
|
'mk' => [ |
|
|
'mk', |
|
|
'Macedonian', |
|
|
'Macedonian', |
|
|
'mk|macedonian', |
|
|
'mk_MK', |
|
|
], |
|
|
'ml' => [ |
|
|
'ml', |
|
|
'Malayalam', |
|
|
'Malayalam', |
|
|
'ml|malayalam', |
|
|
'', |
|
|
], |
|
|
'mn' => [ |
|
|
'mn', |
|
|
'Mongolian', |
|
|
'Монгол', |
|
|
'mn|mongolian', |
|
|
'mn_MN', |
|
|
], |
|
|
'ms' => [ |
|
|
'ms', |
|
|
'Malay', |
|
|
'Bahasa Melayu', |
|
|
'ms|malay', |
|
|
'ms_MY', |
|
|
], |
|
|
'my' => [ |
|
|
'my', |
|
|
'Burmese', |
|
|
'မြန်မာ', |
|
|
'my|burmese', |
|
|
'', |
|
|
], |
|
|
'ne' => [ |
|
|
'ne', |
|
|
'Nepali', |
|
|
'नेपाली', |
|
|
'ne|nepali', |
|
|
'', |
|
|
], |
|
|
'nb' => [ |
|
|
'nb', |
|
|
'Norwegian', |
|
|
'Norsk', |
|
|
'nb|norwegian', |
|
|
'nb_NO', |
|
|
], |
|
|
'nn' => [ |
|
|
'nn', |
|
|
'Norwegian Nynorsk', |
|
|
'Nynorsk', |
|
|
'nn|nynorsk', |
|
|
'nn_NO', |
|
|
], |
|
|
'nl' => [ |
|
|
'nl', |
|
|
'Dutch', |
|
|
'Nederlands', |
|
|
'nl|dutch', |
|
|
'nl_NL', |
|
|
], |
|
|
'pa' => [ |
|
|
'pa', |
|
|
'Punjabi', |
|
|
'ਪੰਜਾਬੀ', |
|
|
'pa|punjabi', |
|
|
'', |
|
|
], |
|
|
'pl' => [ |
|
|
'pl', |
|
|
'Polish', |
|
|
'Polski', |
|
|
'pl|polish', |
|
|
'pl_PL', |
|
|
], |
|
|
'pt' => [ |
|
|
'pt', |
|
|
'Portuguese', |
|
|
'Português', |
|
|
'pt|portuguese', |
|
|
'pt_PT', |
|
|
], |
|
|
'pt_br' => [ |
|
|
'pt_BR', |
|
|
'Portuguese (Brazil)', |
|
|
'Português (Brasil)', |
|
|
'pt[-_]br|portuguese (brazil)', |
|
|
'pt_BR', |
|
|
], |
|
|
'rcf' => [ |
|
|
'rcf', |
|
|
'Réunion Creole', |
|
|
'Kréol', |
|
|
'rcf|creole (reunion)', |
|
|
'', |
|
|
], |
|
|
'ro' => [ |
|
|
'ro', |
|
|
'Romanian', |
|
|
'Română', |
|
|
'ro|romanian', |
|
|
'ro_RO', |
|
|
], |
|
|
'ru' => [ |
|
|
'ru', |
|
|
'Russian', |
|
|
'Русский', |
|
|
'ru|russian', |
|
|
'ru_RU', |
|
|
], |
|
|
'si' => [ |
|
|
'si', |
|
|
'Sinhala', |
|
|
'සිංහල', |
|
|
'si|sinhala', |
|
|
'', |
|
|
], |
|
|
'sk' => [ |
|
|
'sk', |
|
|
'Slovak', |
|
|
'Slovenčina', |
|
|
'sk|slovak', |
|
|
'sk_SK', |
|
|
], |
|
|
'sl' => [ |
|
|
'sl', |
|
|
'Slovenian', |
|
|
'Slovenščina', |
|
|
'sl|slovenian', |
|
|
'sl_SI', |
|
|
], |
|
|
'sq' => [ |
|
|
'sq', |
|
|
'Albanian', |
|
|
'Shqip', |
|
|
'sq|albanian', |
|
|
'sq_AL', |
|
|
], |
|
|
'sr@latin' => [ |
|
|
'sr@latin', |
|
|
'Serbian (latin)', |
|
|
'Srpski', |
|
|
'sr[-_]lat|sr@latin|serbian latin', |
|
|
'sr_YU', |
|
|
], |
|
|
'sr' => [ |
|
|
'sr', |
|
|
'Serbian', |
|
|
'Српски', |
|
|
'sr|serbian', |
|
|
'sr_YU', |
|
|
], |
|
|
'sv' => [ |
|
|
'sv', |
|
|
'Swedish', |
|
|
'Svenska', |
|
|
'sv|swedish', |
|
|
'sv_SE', |
|
|
], |
|
|
'ta' => [ |
|
|
'ta', |
|
|
'Tamil', |
|
|
'தமிழ்', |
|
|
'ta|tamil', |
|
|
'ta_IN', |
|
|
], |
|
|
'te' => [ |
|
|
'te', |
|
|
'Telugu', |
|
|
'తెలుగు', |
|
|
'te|telugu', |
|
|
'te_IN', |
|
|
], |
|
|
'th' => [ |
|
|
'th', |
|
|
'Thai', |
|
|
'ภาษาไทย', |
|
|
'th|thai', |
|
|
'th_TH', |
|
|
], |
|
|
'tk' => [ |
|
|
'tk', |
|
|
'Turkmen', |
|
|
'Türkmençe', |
|
|
'tk|turkmen', |
|
|
'', |
|
|
], |
|
|
'tr' => [ |
|
|
'tr', |
|
|
'Turkish', |
|
|
'Türkçe', |
|
|
'tr|turkish', |
|
|
'tr_TR', |
|
|
], |
|
|
'tt' => [ |
|
|
'tt', |
|
|
'Tatarish', |
|
|
'Tatarça', |
|
|
'tt|tatarish', |
|
|
'', |
|
|
], |
|
|
'tzm' => [ |
|
|
'tzm', |
|
|
'Central Atlas Tamazight', |
|
|
'Tamaziɣt', |
|
|
'tzm|central atlas tamazight', |
|
|
'', |
|
|
], |
|
|
'ug' => [ |
|
|
'ug', |
|
|
'Uyghur', |
|
|
'ئۇيغۇرچە', |
|
|
'ug|uyghur', |
|
|
'', |
|
|
], |
|
|
'uk' => [ |
|
|
'uk', |
|
|
'Ukrainian', |
|
|
'Українська', |
|
|
'uk|ukrainian', |
|
|
'uk_UA', |
|
|
], |
|
|
'ur' => [ |
|
|
'ur', |
|
|
'Urdu', |
|
|
'اُردوُ', |
|
|
'ur|urdu', |
|
|
'ur_PK', |
|
|
], |
|
|
'uz@latin' => [ |
|
|
'uz@latin', |
|
|
'Uzbek (latin)', |
|
|
'O‘zbekcha', |
|
|
'uz[-_]lat|uz@latin|uzbek-latin', |
|
|
'', |
|
|
], |
|
|
'uz' => [ |
|
|
'uz', |
|
|
'Uzbek (cyrillic)', |
|
|
'Ўзбекча', |
|
|
'uz[-_]cyr|uz@cyrillic|uzbek-cyrillic', |
|
|
'', |
|
|
], |
|
|
'vi' => [ |
|
|
'vi', |
|
|
'Vietnamese', |
|
|
'Tiếng Việt', |
|
|
'vi|vietnamese', |
|
|
'vi_VN', |
|
|
], |
|
|
'vls' => [ |
|
|
'vls', |
|
|
'Flemish', |
|
|
'West-Vlams', |
|
|
'vls|flemish', |
|
|
'', |
|
|
], |
|
|
'zh_tw' => [ |
|
|
'zh_TW', |
|
|
'Chinese traditional', |
|
|
'中文', |
|
|
'zh[-_](tw|hk)|chinese traditional', |
|
|
'zh_TW', |
|
|
], |
|
|
// only TW and HK use traditional Chinese while others (CN, SG, MY) |
|
|
// use simplified Chinese |
|
|
'zh_cn' => [ |
|
|
'zh_CN', |
|
|
'Chinese simplified', |
|
|
'中文', |
|
|
'zh(?![-_](tw|hk))([-_][[:alpha:]]{2,3})?|chinese simplified', |
|
|
'zh_CN', |
|
|
], |
|
|
]; |
|
|
|
|
|
/** @var array */ |
|
|
private $availableLocales; |
|
|
|
|
|
/** @var array */ |
|
|
private $availableLanguages = []; |
|
|
|
|
|
/** @var bool */ |
|
|
private $langFailedConfig = false; |
|
|
|
|
|
/** @var bool */ |
|
|
private $langFailedCookie = false; |
|
|
|
|
|
/** @var bool */ |
|
|
private $langFailedRequest = false; |
|
|
|
|
|
/** @var LanguageManager */ |
|
|
private static $instance; |
|
|
|
|
|
/** |
|
|
* Returns LanguageManager singleton |
|
|
* |
|
|
* @return LanguageManager |
|
|
*/ |
|
|
public static function getInstance() |
|
|
{ |
|
|
if (self::$instance === null) { |
|
|
self::$instance = new LanguageManager(); |
|
|
} |
|
|
|
|
|
return self::$instance; |
|
|
} |
|
|
|
|
|
/** |
|
|
* Returns list of available locales |
|
|
* |
|
|
* @return array |
|
|
*/ |
|
|
public function listLocaleDir() |
|
|
{ |
|
|
$result = ['en']; |
|
|
|
|
|
/* Check for existing directory */ |
|
|
if (! is_dir(LOCALE_PATH)) { |
|
|
return $result; |
|
|
} |
|
|
|
|
|
/* Open the directory */ |
|
|
$handle = @opendir(LOCALE_PATH); |
|
|
/* This can happen if the kit is English-only */ |
|
|
if ($handle === false) { |
|
|
return $result; |
|
|
} |
|
|
|
|
|
/* Process all files */ |
|
|
while (($file = readdir($handle)) !== false) { |
|
|
$path = LOCALE_PATH |
|
|
. '/' . $file |
|
|
. '/LC_MESSAGES/phpmyadmin.mo'; |
|
|
if ($file === '.' || $file === '..' || ! @file_exists($path)) { |
|
|
continue; |
|
|
} |
|
|
|
|
|
$result[] = $file; |
|
|
} |
|
|
|
|
|
/* Close the handle */ |
|
|
closedir($handle); |
|
|
|
|
|
return $result; |
|
|
} |
|
|
|
|
|
/** |
|
|
* Returns (cached) list of all available locales |
|
|
* |
|
|
* @return array of strings |
|
|
*/ |
|
|
public function availableLocales() |
|
|
{ |
|
|
if (! $this->availableLocales) { |
|
|
if (! isset($GLOBALS['config']) || empty($GLOBALS['config']->get('FilterLanguages'))) { |
|
|
$this->availableLocales = $this->listLocaleDir(); |
|
|
} else { |
|
|
$this->availableLocales = preg_grep( |
|
|
'@' . $GLOBALS['config']->get('FilterLanguages') . '@', |
|
|
$this->listLocaleDir() |
|
|
); |
|
|
} |
|
|
} |
|
|
|
|
|
return $this->availableLocales; |
|
|
} |
|
|
|
|
|
/** |
|
|
* Checks whether there are some languages available |
|
|
*/ |
|
|
public function hasChoice(): bool |
|
|
{ |
|
|
return count($this->availableLanguages()) > 1; |
|
|
} |
|
|
|
|
|
/** |
|
|
* Returns (cached) list of all available languages |
|
|
* |
|
|
* @return Language[] array of Language objects |
|
|
*/ |
|
|
public function availableLanguages() |
|
|
{ |
|
|
if (! $this->availableLanguages) { |
|
|
$this->availableLanguages = []; |
|
|
|
|
|
foreach ($this->availableLocales() as $lang) { |
|
|
$lang = strtolower($lang); |
|
|
if (isset(static::$languageData[$lang])) { |
|
|
$data = static::$languageData[$lang]; |
|
|
$this->availableLanguages[$lang] = new Language($data[0], $data[1], $data[2], $data[3], $data[4]); |
|
|
} else { |
|
|
$this->availableLanguages[$lang] = new Language( |
|
|
$lang, |
|
|
ucfirst($lang), |
|
|
ucfirst($lang), |
|
|
$lang, |
|
|
'' |
|
|
); |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
return $this->availableLanguages; |
|
|
} |
|
|
|
|
|
/** |
|
|
* Returns (cached) list of all available languages sorted |
|
|
* by name |
|
|
* |
|
|
* @return Language[] array of Language objects |
|
|
*/ |
|
|
public function sortedLanguages() |
|
|
{ |
|
|
$this->availableLanguages(); |
|
|
uasort($this->availableLanguages, static function (Language $a, Language $b) { |
|
|
return $a->cmp($b); |
|
|
}); |
|
|
|
|
|
return $this->availableLanguages; |
|
|
} |
|
|
|
|
|
/** |
|
|
* Return Language object for given code |
|
|
* |
|
|
* @param string $code Language code |
|
|
* |
|
|
* @return Language|false Language object or false on failure |
|
|
*/ |
|
|
public function getLanguage($code) |
|
|
{ |
|
|
$code = strtolower($code); |
|
|
$langs = $this->availableLanguages(); |
|
|
if (isset($langs[$code])) { |
|
|
return $langs[$code]; |
|
|
} |
|
|
|
|
|
return false; |
|
|
} |
|
|
|
|
|
/** |
|
|
* Return currently active Language object |
|
|
* |
|
|
* @return Language Language object |
|
|
*/ |
|
|
public function getCurrentLanguage() |
|
|
{ |
|
|
return $this->availableLanguages[strtolower($GLOBALS['lang'])]; |
|
|
} |
|
|
|
|
|
/** |
|
|
* Activates language based on configuration, user preferences or |
|
|
* browser |
|
|
* |
|
|
* @return Language |
|
|
*/ |
|
|
public function selectLanguage() |
|
|
{ |
|
|
// check forced language |
|
|
if (! empty($GLOBALS['config']->get('Lang'))) { |
|
|
$lang = $this->getLanguage($GLOBALS['config']->get('Lang')); |
|
|
if ($lang !== false) { |
|
|
return $lang; |
|
|
} |
|
|
|
|
|
$this->langFailedConfig = true; |
|
|
} |
|
|
|
|
|
// Don't use REQUEST in following code as it might be confused by cookies |
|
|
// with same name. Check user requested language (POST) |
|
|
if (! empty($_POST['lang'])) { |
|
|
$lang = $this->getLanguage($_POST['lang']); |
|
|
if ($lang !== false) { |
|
|
return $lang; |
|
|
} |
|
|
|
|
|
$this->langFailedRequest = true; |
|
|
} |
|
|
|
|
|
// check user requested language (GET) |
|
|
if (! empty($_GET['lang'])) { |
|
|
$lang = $this->getLanguage($_GET['lang']); |
|
|
if ($lang !== false) { |
|
|
return $lang; |
|
|
} |
|
|
|
|
|
$this->langFailedRequest = true; |
|
|
} |
|
|
|
|
|
// check previous set language |
|
|
if (! empty($GLOBALS['config']->getCookie('pma_lang'))) { |
|
|
$lang = $this->getLanguage($GLOBALS['config']->getCookie('pma_lang')); |
|
|
if ($lang !== false) { |
|
|
return $lang; |
|
|
} |
|
|
|
|
|
$this->langFailedCookie = true; |
|
|
} |
|
|
|
|
|
$langs = $this->availableLanguages(); |
|
|
|
|
|
// try to find out user's language by checking its HTTP_ACCEPT_LANGUAGE variable; |
|
|
$accepted_languages = Core::getenv('HTTP_ACCEPT_LANGUAGE'); |
|
|
if ($accepted_languages) { |
|
|
foreach (explode(',', $accepted_languages) as $header) { |
|
|
foreach ($langs as $language) { |
|
|
if ($language->matchesAcceptLanguage($header)) { |
|
|
return $language; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
// try to find out user's language by checking its HTTP_USER_AGENT variable |
|
|
$user_agent = Core::getenv('HTTP_USER_AGENT'); |
|
|
if (! empty($user_agent)) { |
|
|
foreach ($langs as $language) { |
|
|
if ($language->matchesUserAgent($user_agent)) { |
|
|
return $language; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
// Didn't catch any valid lang : we use the default settings |
|
|
if (isset($langs[$GLOBALS['config']->get('DefaultLang')])) { |
|
|
return $langs[$GLOBALS['config']->get('DefaultLang')]; |
|
|
} |
|
|
|
|
|
// Fallback to English |
|
|
return $langs['en']; |
|
|
} |
|
|
|
|
|
/** |
|
|
* Displays warnings about invalid languages. This needs to be postponed |
|
|
* to show messages at time when language is initialized. |
|
|
*/ |
|
|
public function showWarnings(): void |
|
|
{ |
|
|
// now, that we have loaded the language strings we can send the errors |
|
|
if (! $this->langFailedConfig && ! $this->langFailedCookie && ! $this->langFailedRequest) { |
|
|
return; |
|
|
} |
|
|
|
|
|
trigger_error( |
|
|
__('Ignoring unsupported language code.'), |
|
|
E_USER_ERROR |
|
|
); |
|
|
} |
|
|
}
|
|
|
|