Initial implementation of LanguageManager
The LanguageManager is responsible for choosing correct language and Language class wraps invididual locales, allows matching and their activation. Issue #11847 Signed-off-by: Michal Čihař <michal@cihar.com>
This commit is contained in:
parent
39771f44c0
commit
fd045a94e7
175
libraries/Language.php
Normal file
175
libraries/Language.php
Normal file
@ -0,0 +1,175 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Hold the PMA\libraries\LanguageManager class
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
namespace PMA\libraries;
|
||||
|
||||
use PMA\libraries\LanguageManager;
|
||||
|
||||
|
||||
/**
|
||||
* Language object
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
class Language
|
||||
{
|
||||
protected $code;
|
||||
protected $name;
|
||||
protected $native;
|
||||
protected $regex;
|
||||
|
||||
/**
|
||||
* Constructs the Language object
|
||||
*
|
||||
* @param string $code Language code
|
||||
* @param string $name English name
|
||||
* @param string $native Native name
|
||||
* @param string $regex Match regullar expression
|
||||
*
|
||||
*/
|
||||
public function __construct($code, $name, $native, $regex)
|
||||
{
|
||||
$this->code = $code;
|
||||
$this->name = $name;
|
||||
$this->native = $native;
|
||||
if (strpos($regex, '[-_]') === false) {
|
||||
$regex = str_replace('|', '([-_][[:alpha:]]{2,3})?|', $regex);
|
||||
}
|
||||
$this->regex = $regex;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns native name for language
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getNativeName()
|
||||
{
|
||||
return $this->native;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns English name for language
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getEnglishName()
|
||||
{
|
||||
return $this->name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns verbose name for language
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getName()
|
||||
{
|
||||
if (! empty($this->native)) {
|
||||
return $this->native . ' - ' . $this->name;
|
||||
} else {
|
||||
return $this->name;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns language code
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function getCode()
|
||||
{
|
||||
return $this->code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether language is currently active.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isActive()
|
||||
{
|
||||
return $GLOBALS['lang'] == $this->code;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether language matches HTTP header Accept-Language.
|
||||
*
|
||||
* @param string $header Header content
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function matchesAcceptLanguage($header)
|
||||
{
|
||||
$pattern = '/^('
|
||||
. addcslashes($this->regex, '/')
|
||||
. ')(;q=[0-9]\\.[0-9])?$/i';
|
||||
return preg_match($pattern, $header);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether language matches HTTP header User-Agent
|
||||
*
|
||||
* @param string $header Header content
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function matchesUserAgent($header)
|
||||
{
|
||||
$pattern = '/(\(|\[|;[[:space:]])('
|
||||
. addcslashes($this->regex, '/')
|
||||
. ')(;|\]|\))/i';
|
||||
return preg_match($pattern, $header);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether langauge is RTL
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function isRTL()
|
||||
{
|
||||
return in_array($this->code, array('ar', 'fa', 'he', 'ur'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Activates given translation
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function activate()
|
||||
{
|
||||
$GLOBALS['lang'] = $this->code;
|
||||
|
||||
// Set locale
|
||||
_setlocale(LC_MESSAGES, $this->code);
|
||||
_bindtextdomain('phpmyadmin', LOCALE_PATH);
|
||||
_bind_textdomain_codeset('phpmyadmin', 'UTF-8');
|
||||
_textdomain('phpmyadmin');
|
||||
|
||||
/* Text direction for language */
|
||||
if ($this->isRTL()) {
|
||||
$GLOBALS['text_dir'] = 'rtl';
|
||||
} else {
|
||||
$GLOBALS['text_dir'] = 'ltr';
|
||||
}
|
||||
|
||||
/* TCPDF */
|
||||
$GLOBALS['l'] = array();
|
||||
|
||||
/* TCPDF settings */
|
||||
$GLOBALS['l']['a_meta_charset'] = 'UTF-8';
|
||||
$GLOBALS['l']['a_meta_dir'] = $GLOBALS['text_dir'];
|
||||
$GLOBALS['l']['a_meta_language'] = $this->code;
|
||||
|
||||
/* TCPDF translations */
|
||||
$GLOBALS['l']['w_page'] = __('Page number:');
|
||||
|
||||
/* Show possible warnings from langauge selection */
|
||||
LanguageManager::getInstance()->showWarnings();
|
||||
}
|
||||
}
|
||||
687
libraries/LanguageManager.php
Normal file
687
libraries/LanguageManager.php
Normal file
@ -0,0 +1,687 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* Hold the PMA\libraries\LanguageManager class
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
namespace PMA\libraries;
|
||||
|
||||
use PMA\libraries\Language;
|
||||
|
||||
/**
|
||||
* Language selection manager
|
||||
*
|
||||
* @package PhpMyAdmin
|
||||
*/
|
||||
class LanguageManager
|
||||
{
|
||||
/**
|
||||
* @var array Definition data for languages
|
||||
*
|
||||
* Each member contains:
|
||||
* - English language name
|
||||
* - Native language name
|
||||
* - Match regullar expression
|
||||
*/
|
||||
private static $_language_data = array(
|
||||
'af' => array(
|
||||
'Afrikaans',
|
||||
'',
|
||||
'af|afrikaans',
|
||||
),
|
||||
'ar' => array(
|
||||
'Arabic',
|
||||
'العربية',
|
||||
'ar|arabic',
|
||||
),
|
||||
'az' => array(
|
||||
'Azerbaijani',
|
||||
'Azərbaycanca',
|
||||
'az|azerbaijani',
|
||||
),
|
||||
'bn' => array(
|
||||
'Bangla',
|
||||
'বাংলা',
|
||||
'bn|bangla',
|
||||
),
|
||||
'be' => array(
|
||||
'Belarusian',
|
||||
'Беларуская',
|
||||
'be|belarusian',
|
||||
),
|
||||
'be@latin' => array(
|
||||
'Belarusian (latin)',
|
||||
'Biełaruskaja',
|
||||
'be[-_]lat|be@latin|belarusian latin',
|
||||
),
|
||||
'bg' => array(
|
||||
'Bulgarian',
|
||||
'Български',
|
||||
'bg|bulgarian',
|
||||
),
|
||||
'bs' => array(
|
||||
'Bosnian',
|
||||
'Bosanski',
|
||||
'bs|bosnian',
|
||||
),
|
||||
'br' => array(
|
||||
'Breton',
|
||||
'Brezhoneg',
|
||||
'br|breton',
|
||||
),
|
||||
'brx' => array(
|
||||
'Bodo',
|
||||
'बड़ो',
|
||||
'brx|bodo',
|
||||
),
|
||||
'ca' => array(
|
||||
'Catalan',
|
||||
'Català',
|
||||
'ca|catalan',
|
||||
),
|
||||
'ckb' => array(
|
||||
'Sorani',
|
||||
'سۆرانی',
|
||||
'ckb|sorani',
|
||||
),
|
||||
'cs' => array(
|
||||
'Czech',
|
||||
'Čeština',
|
||||
'cs|czech',
|
||||
),
|
||||
'cy' => array(
|
||||
'Welsh',
|
||||
'Cymraeg',
|
||||
'cy|welsh',
|
||||
),
|
||||
'da' => array(
|
||||
'Danish',
|
||||
'Dansk',
|
||||
'da|danish',
|
||||
),
|
||||
'de' => array(
|
||||
'German',
|
||||
'Deutsch',
|
||||
'de|german',
|
||||
),
|
||||
'el' => array(
|
||||
'Greek',
|
||||
'Ελληνικά',
|
||||
'el|greek',
|
||||
),
|
||||
'en' => array(
|
||||
'English',
|
||||
'',
|
||||
'en|english',
|
||||
),
|
||||
'en_gb' => array(
|
||||
'English (United Kingdom)',
|
||||
'',
|
||||
'en[_-]gb|english (United Kingdom)',
|
||||
),
|
||||
'eo' => array(
|
||||
'Esperanto',
|
||||
'Esperanto',
|
||||
'eo|esperanto',
|
||||
),
|
||||
'es' => array(
|
||||
'Spanish',
|
||||
'Español',
|
||||
'es|spanish',
|
||||
),
|
||||
'et' => array(
|
||||
'Estonian',
|
||||
'Eesti',
|
||||
'et|estonian',
|
||||
),
|
||||
'eu' => array(
|
||||
'Basque',
|
||||
'Euskara',
|
||||
'eu|basque',
|
||||
),
|
||||
'fa' => array(
|
||||
'Persian',
|
||||
'فارسی',
|
||||
'fa|persian',
|
||||
),
|
||||
'fi' => array(
|
||||
'Finnish',
|
||||
'Suomi',
|
||||
'fi|finnish',
|
||||
),
|
||||
'fr' => array(
|
||||
'French',
|
||||
'Français',
|
||||
'fr|french',
|
||||
),
|
||||
'fy' => array(
|
||||
'Frisian',
|
||||
'Frysk',
|
||||
'fy|frisian',
|
||||
),
|
||||
'gl' => array(
|
||||
'Galician',
|
||||
'Galego',
|
||||
'gl|galician',
|
||||
),
|
||||
'gu' => array(
|
||||
'Gujarati',
|
||||
'ગુજરાતી',
|
||||
'gu|gujarati',
|
||||
),
|
||||
'he' => array(
|
||||
'Hebrew',
|
||||
'עברית',
|
||||
'he|hebrew',
|
||||
),
|
||||
'hi' => array(
|
||||
'Hindi',
|
||||
'हिन्दी',
|
||||
'hi|hindi',
|
||||
),
|
||||
'hr' => array(
|
||||
'Croatian',
|
||||
'Hrvatski',
|
||||
'hr|croatian',
|
||||
),
|
||||
'hu' => array(
|
||||
'Hungarian',
|
||||
'Magyar',
|
||||
'hu|hungarian',
|
||||
),
|
||||
'hy' => array(
|
||||
'Armenian',
|
||||
'Հայերէն',
|
||||
'hy|armenian',
|
||||
),
|
||||
'ia' => array(
|
||||
'Interlingua',
|
||||
'',
|
||||
'ia|interlingua',
|
||||
),
|
||||
'id' => array(
|
||||
'Indonesian',
|
||||
'Bahasa Indonesia',
|
||||
'id|indonesian',
|
||||
),
|
||||
'it' => array(
|
||||
'Italian',
|
||||
'Italiano',
|
||||
'it|italian',
|
||||
),
|
||||
'ja' => array(
|
||||
'Japanese',
|
||||
'日本語',
|
||||
'ja|japanese',
|
||||
),
|
||||
'ko' => array(
|
||||
'Korean',
|
||||
'한국어',
|
||||
'ko|korean',
|
||||
),
|
||||
'ka' => array(
|
||||
'Georgian',
|
||||
'ქართული',
|
||||
'ka|georgian',
|
||||
),
|
||||
'kk' => array(
|
||||
'Kazakh',
|
||||
'Қазақ',
|
||||
'kk|kazakh',
|
||||
),
|
||||
'km' => array(
|
||||
'Khmer',
|
||||
'ខ្មែរ',
|
||||
'km|khmer',
|
||||
),
|
||||
'kn' => array(
|
||||
'Kannada',
|
||||
'ಕನ್ನಡ',
|
||||
'kn|kannada',
|
||||
),
|
||||
'ksh' => array(
|
||||
'Colognian',
|
||||
'Kölsch',
|
||||
'ksh|colognian',
|
||||
),
|
||||
'ky' => array(
|
||||
'Kyrgyz',
|
||||
'Кыргызча',
|
||||
'ky|kyrgyz',
|
||||
),
|
||||
'li' => array(
|
||||
'Limburgish',
|
||||
'Lèmbörgs',
|
||||
'li|limburgish',
|
||||
),
|
||||
'lt' => array(
|
||||
'Lithuanian',
|
||||
'Lietuvių',
|
||||
'lt|lithuanian',
|
||||
),
|
||||
'lv' => array(
|
||||
'Latvian',
|
||||
'Latviešu',
|
||||
'lv|latvian',
|
||||
),
|
||||
'mk' => array(
|
||||
'Macedonian',
|
||||
'Macedonian',
|
||||
'mk|macedonian',
|
||||
),
|
||||
'ml' => array(
|
||||
'Malayalam',
|
||||
'Malayalam',
|
||||
'ml|malayalam',
|
||||
),
|
||||
'mn' => array(
|
||||
'Mongolian',
|
||||
'Монгол',
|
||||
'mn|mongolian',
|
||||
),
|
||||
'ms' => array(
|
||||
'Malay',
|
||||
'Bahasa Melayu',
|
||||
'ms|malay',
|
||||
),
|
||||
'ne' => array(
|
||||
'Nepali',
|
||||
'नेपाली',
|
||||
'ne|nepali',
|
||||
),
|
||||
'nl' => array(
|
||||
'Dutch',
|
||||
'Nederlands',
|
||||
'nl|dutch',
|
||||
),
|
||||
'nb' => array(
|
||||
'Norwegian',
|
||||
'Norsk',
|
||||
'nb|norwegian',
|
||||
),
|
||||
'pa' => array(
|
||||
'Punjabi',
|
||||
'ਪੰਜਾਬੀ',
|
||||
'pa|punjabi',
|
||||
),
|
||||
'pl' => array(
|
||||
'Polish',
|
||||
'Polski',
|
||||
'pl|polish',
|
||||
),
|
||||
'pt_br' => array(
|
||||
'Brazilian Portuguese',
|
||||
'Português',
|
||||
'pt[-_]br|brazilian portuguese',
|
||||
),
|
||||
'pt' => array(
|
||||
'Portuguese',
|
||||
'Português',
|
||||
'pt|portuguese',
|
||||
),
|
||||
'ro' => array(
|
||||
'Romanian',
|
||||
'Română',
|
||||
'ro|romanian',
|
||||
),
|
||||
'ru' => array(
|
||||
'Russian',
|
||||
'Русский',
|
||||
'ru|russian',
|
||||
),
|
||||
'si' => array(
|
||||
'Sinhala',
|
||||
'සිංහල',
|
||||
'si|sinhala',
|
||||
),
|
||||
'sk' => array(
|
||||
'Slovak',
|
||||
'Slovenčina',
|
||||
'sk|slovak',
|
||||
),
|
||||
'sl' => array(
|
||||
'Slovenian',
|
||||
'Slovenščina',
|
||||
'sl|slovenian',
|
||||
),
|
||||
'sq' => array(
|
||||
'Slbanian',
|
||||
'Shqip',
|
||||
'sq|albanian',
|
||||
),
|
||||
'sr@latin' => array(
|
||||
'Serbian (latin)',
|
||||
'Srpski',
|
||||
'sr[-_]lat|sr@latin|serbian latin',
|
||||
),
|
||||
'sr' => array(
|
||||
'Serbian',
|
||||
'Српски',
|
||||
'sr|serbian',
|
||||
),
|
||||
'sv' => array(
|
||||
'Swedish',
|
||||
'Svenska',
|
||||
'sv|swedish',
|
||||
),
|
||||
'ta' => array(
|
||||
'Tamil',
|
||||
'தமிழ்',
|
||||
'ta|tamil',
|
||||
),
|
||||
'te' => array(
|
||||
'Telugu',
|
||||
'తెలుగు',
|
||||
'te|telugu',
|
||||
),
|
||||
'th' => array(
|
||||
'Thai',
|
||||
'ภาษาไทย',
|
||||
'th|thai',
|
||||
),
|
||||
'tk' => array(
|
||||
'Turkmen',
|
||||
'Türkmençe',
|
||||
'tk|turkmen',
|
||||
),
|
||||
'tr' => array(
|
||||
'Turkish',
|
||||
'Türkçe',
|
||||
'tr|turkish',
|
||||
),
|
||||
'tt' => array(
|
||||
'Tatarish',
|
||||
'Tatarça',
|
||||
'tt|tatarish',
|
||||
),
|
||||
'ug' => array(
|
||||
'Uyghur',
|
||||
'ئۇيغۇرچە',
|
||||
'ug|uyghur',
|
||||
),
|
||||
'uk' => array(
|
||||
'Ukrainian',
|
||||
'Українська',
|
||||
'uk|ukrainian',
|
||||
),
|
||||
'ur' => array(
|
||||
'Urdu',
|
||||
'اُردوُ',
|
||||
'ur|urdu',
|
||||
),
|
||||
'uz@latin' => array(
|
||||
'Uzbek (latin)',
|
||||
'O‘zbekcha',
|
||||
'uz[-_]lat|uz@latin|uzbek-latin',
|
||||
),
|
||||
'uz' => array(
|
||||
'Uzbek (cyrillic)',
|
||||
'Ўзбекча',
|
||||
'uz[-_]cyr|uz@cyrillic|uzbek-cyrillic',
|
||||
),
|
||||
'vi' => array(
|
||||
'Vietnamese',
|
||||
'Tiếng Việt',
|
||||
'vi|vietnamese',
|
||||
),
|
||||
'vls' => array(
|
||||
'Flemish',
|
||||
'West-Vlams',
|
||||
'vls|flemish',
|
||||
),
|
||||
'zh_tw' => array(
|
||||
'Chinese traditional',
|
||||
'中文',
|
||||
'zh[-_](tw|hk)|chinese traditional',
|
||||
),
|
||||
// only TW and HK use traditional Chinese while others (CN, SG, MY)
|
||||
// use simplified Chinese
|
||||
'zh_cn' => array(
|
||||
'Chinese simplified',
|
||||
'中文',
|
||||
'zh(?)([-_][[:alpha:]]{2,3})?|chinese simplified',
|
||||
),
|
||||
);
|
||||
|
||||
private $_available_locales;
|
||||
private $_available_languages;
|
||||
private $_lang_failed_cfg;
|
||||
private $_lang_failed_cookie;
|
||||
private $_lang_failed_request;
|
||||
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 = array('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 (false !== ($file = readdir($handle))) {
|
||||
$path = LOCALE_PATH
|
||||
. '/' . $file
|
||||
. '/LC_MESSAGES/phpmyadmin.mo';
|
||||
if ($file != "."
|
||||
&& $file != ".."
|
||||
&& file_exists($path)
|
||||
) {
|
||||
$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->_available_locales) {
|
||||
|
||||
if (empty($GLOBALS['cfg']['FilterLanguages'])) {
|
||||
$this->_available_locales = $this->listLocaleDir();
|
||||
} else {
|
||||
$this->_available_locales = preg_grep(
|
||||
'@' . $GLOBALS['cfg']['FilterLanguages'] . '@',
|
||||
$this->listLocaleDir()
|
||||
);
|
||||
}
|
||||
}
|
||||
return $this->_available_locales;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns (cached) list of all available languages
|
||||
*
|
||||
* @return array of Language objects
|
||||
*/
|
||||
public function availableLanguages()
|
||||
{
|
||||
if (! $this->_available_languages) {
|
||||
$this->_available_languages = array();
|
||||
|
||||
foreach($this->availableLocales() as $lang) {
|
||||
$lang = strtolower($lang);
|
||||
if (isset($this::$_language_data[$lang])) {
|
||||
$data = $this::$_language_data[$lang];
|
||||
$this->_available_languages[$lang] = new Language(
|
||||
$lang,
|
||||
$data[0],
|
||||
$data[1],
|
||||
$data[2]
|
||||
);
|
||||
} else {
|
||||
$this->_available_languages[$lang] = new Language(
|
||||
$lang,
|
||||
ucfirst($lang),
|
||||
ucfirst($lang),
|
||||
$lang
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
return $this->_available_languages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns (cached) list of all available languages sorted
|
||||
* by name
|
||||
*
|
||||
* @return array of Language objects
|
||||
*/
|
||||
public function sortedLanguages()
|
||||
{
|
||||
$this->availableLanguages();
|
||||
uasort($this->_available_languages, function($a, $b)
|
||||
{
|
||||
return strcmp($a->name, $b->name);
|
||||
}
|
||||
);
|
||||
return $this->_available_languages;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return Language object for given code
|
||||
*
|
||||
* @param string $code Language code
|
||||
*
|
||||
* @return object|false Language object or false on failure
|
||||
*/
|
||||
public function getLanguage($code)
|
||||
{
|
||||
$langs = $this->availableLanguages();
|
||||
if (isset($langs[$code])) {
|
||||
return $langs[$code];
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Activates language based on configuration, user preferences or
|
||||
* browser
|
||||
*
|
||||
* @return Language
|
||||
*/
|
||||
public function selectLanguage()
|
||||
{
|
||||
$langs = $this->availableLanguages();
|
||||
|
||||
// check forced language
|
||||
if (! empty($GLOBALS['cfg']['Lang'])) {
|
||||
if (isset($langs[$GLOBALS['cfg']['Lang']])) {
|
||||
return $langs[$GLOBALS['cfg']['Lang']];
|
||||
}
|
||||
$this->_lang_failed_cfg = 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'])) {
|
||||
if (isset($langs[$_POST['lang']])) {
|
||||
return $langs[$_POST['lang']];
|
||||
}
|
||||
$this->_lang_failed_request = true;
|
||||
}
|
||||
|
||||
// check user requested language (GET)
|
||||
if (! empty($_GET['lang'])) {
|
||||
if (isset($langs[$_GET['lang']])) {
|
||||
return $langs[$_GET['lang']];
|
||||
}
|
||||
$this->_lang_failed_request = true;
|
||||
}
|
||||
|
||||
// check previous set language
|
||||
if (! empty($_COOKIE['pma_lang'])) {
|
||||
if (isset($langs[$_COOKIE['pma_lang']])) {
|
||||
return $langs[$_COOKIE['pma_lang']];
|
||||
}
|
||||
$this->_lang_failed_cookie = true;
|
||||
}
|
||||
|
||||
// try to find out user's language by checking its HTTP_ACCEPT_LANGUAGE variable;
|
||||
// prevent XSS
|
||||
$accepted_languages = PMA_getenv('HTTP_ACCEPT_LANGUAGE');
|
||||
if ($accepted_languages && false === mb_strpos($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 = PMA_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['cfg']['DefaultLang']])) {
|
||||
return $langs[$GLOBALS['cfg']['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.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function showWarnings()
|
||||
{
|
||||
// now, that we have loaded the language strings we can send the errors
|
||||
if ($this->_lang_failed_cfg
|
||||
|| $this->_lang_failed_cookie
|
||||
|| $this->_lang_failed_request
|
||||
) {
|
||||
trigger_error(
|
||||
__('Ignoring unsupported language code.'),
|
||||
E_USER_ERROR
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -89,6 +89,11 @@ define('PHPSECLIB_INC_DIR', './libraries/phpseclib/');
|
||||
*/
|
||||
define('SQL_PARSER_AUTOLOAD', './libraries/sql-parser/autoload.php');
|
||||
|
||||
/**
|
||||
* Path to files with compiled locales (*.mo)
|
||||
*/
|
||||
define('LOCALE_PATH', './locale/');
|
||||
|
||||
/**
|
||||
* Avoid referring to nonexistent files (causes warnings when open_basedir
|
||||
* is used)
|
||||
|
||||
217
test/classes/LanguageTest.php
Normal file
217
test/classes/LanguageTest.php
Normal file
@ -0,0 +1,217 @@
|
||||
<?php
|
||||
/* vim: set expandtab sw=4 ts=4 sts=4: */
|
||||
/**
|
||||
* tests for Advisor class
|
||||
*
|
||||
* @package PhpMyAdmin-test
|
||||
*/
|
||||
|
||||
/*
|
||||
* Include to test.
|
||||
*/
|
||||
require_once 'libraries/core.lib.php';
|
||||
|
||||
use PMA\libraries\LanguageManager;
|
||||
|
||||
/**
|
||||
* Tests behaviour of PMA_Advisor class
|
||||
*
|
||||
* @package PhpMyAdmin-test
|
||||
*/
|
||||
class LanguageTest extends PMATestCase
|
||||
{
|
||||
private $manager;
|
||||
|
||||
/**
|
||||
* Setup for Language tests.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function setup()
|
||||
{
|
||||
$loc = LOCALE_PATH . '/cs/LC_MESSAGES/phpmyadmin.mo';
|
||||
if (! is_readable($loc)) {
|
||||
$this->markTestSkipped('Missing compiled locales.');
|
||||
}
|
||||
$this->manager = new LanguageManager();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test language filtering
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testAvailable()
|
||||
{
|
||||
$GLOBALS['cfg']['FilterLanguages'] = 'cs';
|
||||
|
||||
$langs = $this->manager->availableLocales();
|
||||
|
||||
$this->assertEquals(1, count($langs));
|
||||
$this->assertContains('cs', $langs);
|
||||
$GLOBALS['cfg']['FilterLanguages'] = '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Test no language filtering
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testAllAvailable()
|
||||
{
|
||||
$GLOBALS['cfg']['FilterLanguages'] = '';
|
||||
|
||||
$langs = $this->manager->availableLocales();
|
||||
|
||||
$this->assertContains('cs', $langs);
|
||||
$this->assertContains('en', $langs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test whether listing locales works
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testList()
|
||||
{
|
||||
$langs = $this->manager->listLocaleDir();
|
||||
$this->assertContains('cs', $langs);
|
||||
$this->assertContains('en', $langs);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for getting available languages
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testLanguages()
|
||||
{
|
||||
$langs = $this->manager->availableLanguages();
|
||||
$this->assertGreaterThan(1, count($langs));
|
||||
|
||||
/* Ensure we have name for every language */
|
||||
foreach($langs as $lang) {
|
||||
$this->assertNotEquals($lang->getCode(), strtolower($lang->getEnglishName()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for getting available sorted languages
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testSortedLanguages()
|
||||
{
|
||||
$langs = $this->manager->sortedLanguages();
|
||||
$this->assertGreaterThan(1, count($langs));
|
||||
}
|
||||
|
||||
/**
|
||||
* Test getting language by code
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function testGet()
|
||||
{
|
||||
$lang = $this->manager->getLanguage('cs');
|
||||
$this->assertNotEquals(false, $lang);
|
||||
$this->assertEquals('Czech', $lang->getEnglishName());
|
||||
$this->assertEquals('Čeština', $lang->getNativeName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Test language selection
|
||||
*
|
||||
* @param string $lang Value for forced language
|
||||
* @param string $post Value for language in POST
|
||||
* @param string $get Value for language in GET
|
||||
* @param string $cookie Value for language in COOKIE
|
||||
* @param string $accept Value for HTTP Accept-Language header
|
||||
* @param string $agent Value for HTTP User-Agent header
|
||||
* @param string $default Value for default language
|
||||
* @param string $expect Expected language name
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @dataProvider selectDataProvider
|
||||
*/
|
||||
public function testSelect($lang, $post, $get, $cookie, $accept, $agent, $default, $expect)
|
||||
{
|
||||
$GLOBALS['cfg']['Lang'] = $lang;
|
||||
$_POST['lang'] = $post;
|
||||
$_GET['lang'] = $get;
|
||||
$_COOKIE['pma_lang'] = $cookie;
|
||||
$_SERVER['HTTP_ACCEPT_LANGUAGE'] = $accept;
|
||||
$_SERVER['HTTP_USER_AGENT'] = $agent;
|
||||
$GLOBALS['cfg']['DefaultLang'] = $default;
|
||||
|
||||
$lang = $this->manager->selectLanguage();
|
||||
|
||||
$this->assertEquals($expect, $lang->getEnglishName());
|
||||
|
||||
$GLOBALS['cfg']['Lang'] = '';
|
||||
$_POST['lang'] = '';
|
||||
$_GET['lang'] = '';
|
||||
$_COOKIE['pma_lang'] = '';
|
||||
$_SERVER['HTTP_ACCEPT_LANGUAGE'] = '';
|
||||
$_SERVER['HTTP_USER_AGENT'] = '';
|
||||
$GLOBALS['cfg']['DefaultLang'] = 'en';
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider for language selection test.
|
||||
*
|
||||
* @return array Test parameters.
|
||||
*/
|
||||
public function selectDataProvider()
|
||||
{
|
||||
return array(
|
||||
array('cs', 'en', '', '' ,'' ,'', '', 'Czech'),
|
||||
array('', 'cs', '', '' ,'' ,'', '', 'Czech'),
|
||||
array('', 'cs', 'en', '' ,'' ,'', '', 'Czech'),
|
||||
array('', '', 'cs', '' ,'' ,'', '', 'Czech'),
|
||||
array('', '', '', '' ,'cs,en-US;q=0.7,en;q=0.3' ,'', '', 'Czech'),
|
||||
array(
|
||||
'', '', '', '', '',
|
||||
'Mozilla/5.0 (Linux; U; Android 2.2.2; tr-tr; GM FOX)',
|
||||
'', 'Turkish'
|
||||
),
|
||||
array('', '', '', '' ,'' ,'', 'cs', 'Czech'),
|
||||
array('', '', '', '' ,'' ,'', '', 'English'),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for setting and parsing locales
|
||||
*
|
||||
* @param string $locale locale name
|
||||
*
|
||||
* @return void
|
||||
*
|
||||
* @group large
|
||||
* @dataProvider listLocales
|
||||
*/
|
||||
public function testGettext($locale)
|
||||
{
|
||||
/* We should be able to set the language */
|
||||
$this->manager->getLanguage($locale)->activate();
|
||||
|
||||
/* Grab some texts */
|
||||
$this->assertContains('%s', _ngettext('%s table', '%s tables', 10));
|
||||
$this->assertContains('%s', _ngettext('%s table', '%s tables', 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Data provider to generate list of available locales.
|
||||
*
|
||||
* @return array with arrays of available locales
|
||||
*/
|
||||
public function listLocales()
|
||||
{
|
||||
$ret = array();
|
||||
foreach (LanguageManager::getInstance()->availableLanguages() as $language) {
|
||||
$ret[] = array($language->getCode());
|
||||
}
|
||||
return $ret;
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user