PageRenderTime 47ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 1ms

/libraries/classes/LanguageManager.php

http://github.com/phpmyadmin/phpmyadmin
PHP | 975 lines | 840 code | 46 blank | 89 comment | 31 complexity | 5e074cb50bff19e327702dbc7239c597 MD5 | raw file
Possible License(s): GPL-2.0, MIT, LGPL-3.0
  1. <?php
  2. declare(strict_types=1);
  3. namespace PhpMyAdmin;
  4. use function __;
  5. use function closedir;
  6. use function count;
  7. use function explode;
  8. use function file_exists;
  9. use function is_dir;
  10. use function opendir;
  11. use function preg_grep;
  12. use function readdir;
  13. use function strtolower;
  14. use function trigger_error;
  15. use function uasort;
  16. use function ucfirst;
  17. use const E_USER_ERROR;
  18. /**
  19. * Language selection manager
  20. */
  21. class LanguageManager
  22. {
  23. /**
  24. * Definition data for languages
  25. *
  26. * Each member contains:
  27. * - Language code
  28. * - English language name
  29. * - Native language name
  30. * - Match regular expression
  31. * - MySQL locale
  32. *
  33. * @var array
  34. */
  35. private static $languageData = [
  36. 'af' => [
  37. 'af',
  38. 'Afrikaans',
  39. '',
  40. 'af|afrikaans',
  41. '',
  42. ],
  43. 'am' => [
  44. 'am',
  45. 'Amharic',
  46. 'አማርኛ',
  47. 'am|amharic',
  48. '',
  49. ],
  50. 'ar' => [
  51. 'ar',
  52. 'Arabic',
  53. '&#1575;&#1604;&#1593;&#1585;&#1576;&#1610;&#1577;',
  54. 'ar|arabic',
  55. 'ar_AE',
  56. ],
  57. 'ar_ly' => [
  58. 'ar_LY',
  59. 'Arabic (Libya)',
  60. 'ليبي',
  61. 'ar[_-]ly|arabic (libya)|libian arabic',
  62. 'ar_LY',
  63. ],
  64. 'az' => [
  65. 'az',
  66. 'Azerbaijani',
  67. 'Az&#601;rbaycanca',
  68. 'az|azerbaijani',
  69. '',
  70. ],
  71. 'bn' => [
  72. 'bn',
  73. 'Bangla',
  74. 'বাংলা',
  75. 'bn|bangla',
  76. '',
  77. ],
  78. 'be' => [
  79. 'be',
  80. 'Belarusian',
  81. '&#1041;&#1077;&#1083;&#1072;&#1088;&#1091;&#1089;&#1082;&#1072;&#1103;',
  82. 'be|belarusian',
  83. 'be_BY',
  84. ],
  85. 'be@latin' => [
  86. 'be@latin',
  87. 'Belarusian (latin)',
  88. 'Bie&#0322;aruskaja',
  89. 'be[-_]lat|be@latin|belarusian latin',
  90. '',
  91. ],
  92. 'ber' => [
  93. 'ber',
  94. 'Berber',
  95. 'Tamaziɣt',
  96. 'ber|berber',
  97. '',
  98. ],
  99. 'bg' => [
  100. 'bg',
  101. 'Bulgarian',
  102. '&#1041;&#1098;&#1083;&#1075;&#1072;&#1088;&#1089;&#1082;&#1080;',
  103. 'bg|bulgarian',
  104. 'bg_BG',
  105. ],
  106. 'bs' => [
  107. 'bs',
  108. 'Bosnian',
  109. 'Bosanski',
  110. 'bs|bosnian',
  111. '',
  112. ],
  113. 'br' => [
  114. 'br',
  115. 'Breton',
  116. 'Brezhoneg',
  117. 'br|breton',
  118. '',
  119. ],
  120. 'brx' => [
  121. 'brx',
  122. 'Bodo',
  123. 'बड़ो',
  124. 'brx|bodo',
  125. '',
  126. ],
  127. 'ca' => [
  128. 'ca',
  129. 'Catalan',
  130. 'Catal&agrave;',
  131. 'ca|catalan',
  132. 'ca_ES',
  133. ],
  134. 'ckb' => [
  135. 'ckb',
  136. 'Sorani',
  137. 'سۆرانی',
  138. 'ckb|sorani',
  139. '',
  140. ],
  141. 'cs' => [
  142. 'cs',
  143. 'Czech',
  144. 'Čeština',
  145. 'cs|czech',
  146. 'cs_CZ',
  147. ],
  148. 'cy' => [
  149. 'cy',
  150. 'Welsh',
  151. 'Cymraeg',
  152. 'cy|welsh',
  153. '',
  154. ],
  155. 'da' => [
  156. 'da',
  157. 'Danish',
  158. 'Dansk',
  159. 'da|danish',
  160. 'da_DK',
  161. ],
  162. 'de' => [
  163. 'de',
  164. 'German',
  165. 'Deutsch',
  166. 'de|german',
  167. 'de_DE',
  168. ],
  169. 'el' => [
  170. 'el',
  171. 'Greek',
  172. '&Epsilon;&lambda;&lambda;&eta;&nu;&iota;&kappa;&#940;',
  173. 'el|greek',
  174. '',
  175. ],
  176. 'en' => [
  177. 'en',
  178. 'English',
  179. '',
  180. 'en|english',
  181. 'en_US',
  182. ],
  183. 'en_gb' => [
  184. 'en_GB',
  185. 'English (United Kingdom)',
  186. '',
  187. 'en[_-]gb|english (United Kingdom)',
  188. 'en_GB',
  189. ],
  190. 'eo' => [
  191. 'eo',
  192. 'Esperanto',
  193. 'Esperanto',
  194. 'eo|esperanto',
  195. '',
  196. ],
  197. 'es' => [
  198. 'es',
  199. 'Spanish',
  200. 'Espa&ntilde;ol',
  201. 'es|spanish',
  202. 'es_ES',
  203. ],
  204. 'et' => [
  205. 'et',
  206. 'Estonian',
  207. 'Eesti',
  208. 'et|estonian',
  209. 'et_EE',
  210. ],
  211. 'eu' => [
  212. 'eu',
  213. 'Basque',
  214. 'Euskara',
  215. 'eu|basque',
  216. 'eu_ES',
  217. ],
  218. 'fa' => [
  219. 'fa',
  220. 'Persian',
  221. '&#1601;&#1575;&#1585;&#1587;&#1740;',
  222. 'fa|persian',
  223. '',
  224. ],
  225. 'fi' => [
  226. 'fi',
  227. 'Finnish',
  228. 'Suomi',
  229. 'fi|finnish',
  230. 'fi_FI',
  231. ],
  232. 'fil' => [
  233. 'fil',
  234. 'Filipino',
  235. 'Pilipino',
  236. 'fil|filipino',
  237. '',
  238. ],
  239. 'fr' => [
  240. 'fr',
  241. 'French',
  242. 'Fran&ccedil;ais',
  243. 'fr|french',
  244. 'fr_FR',
  245. ],
  246. 'fy' => [
  247. 'fy',
  248. 'Frisian',
  249. 'Frysk',
  250. 'fy|frisian',
  251. '',
  252. ],
  253. 'gl' => [
  254. 'gl',
  255. 'Galician',
  256. 'Galego',
  257. 'gl|galician',
  258. 'gl_ES',
  259. ],
  260. 'gu' => [
  261. 'gu',
  262. 'Gujarati',
  263. 'ગુજરાતી',
  264. 'gu|gujarati',
  265. 'gu_IN',
  266. ],
  267. 'he' => [
  268. 'he',
  269. 'Hebrew',
  270. '&#1506;&#1489;&#1512;&#1497;&#1514;',
  271. 'he|hebrew',
  272. 'he_IL',
  273. ],
  274. 'hi' => [
  275. 'hi',
  276. 'Hindi',
  277. '&#2361;&#2367;&#2344;&#2381;&#2342;&#2368;',
  278. 'hi|hindi',
  279. 'hi_IN',
  280. ],
  281. 'hr' => [
  282. 'hr',
  283. 'Croatian',
  284. 'Hrvatski',
  285. 'hr|croatian',
  286. 'hr_HR',
  287. ],
  288. 'hu' => [
  289. 'hu',
  290. 'Hungarian',
  291. 'Magyar',
  292. 'hu|hungarian',
  293. 'hu_HU',
  294. ],
  295. 'hy' => [
  296. 'hy',
  297. 'Armenian',
  298. 'Հայերէն',
  299. 'hy|armenian',
  300. '',
  301. ],
  302. 'ia' => [
  303. 'ia',
  304. 'Interlingua',
  305. '',
  306. 'ia|interlingua',
  307. '',
  308. ],
  309. 'id' => [
  310. 'id',
  311. 'Indonesian',
  312. 'Bahasa Indonesia',
  313. 'id|indonesian',
  314. 'id_ID',
  315. ],
  316. 'ig' => [
  317. 'ig',
  318. 'Igbo',
  319. 'Asụsụ Igbo',
  320. 'ig|igbo',
  321. '',
  322. ],
  323. 'it' => [
  324. 'it',
  325. 'Italian',
  326. 'Italiano',
  327. 'it|italian',
  328. 'it_IT',
  329. ],
  330. 'ja' => [
  331. 'ja',
  332. 'Japanese',
  333. '&#26085;&#26412;&#35486;',
  334. 'ja|japanese',
  335. 'ja_JP',
  336. ],
  337. 'ko' => [
  338. 'ko',
  339. 'Korean',
  340. '&#54620;&#44397;&#50612;',
  341. 'ko|korean',
  342. 'ko_KR',
  343. ],
  344. 'ka' => [
  345. 'ka',
  346. 'Georgian',
  347. '&#4325;&#4304;&#4320;&#4311;&#4323;&#4314;&#4312;',
  348. 'ka|georgian',
  349. '',
  350. ],
  351. 'kab' => [
  352. 'kab',
  353. 'Kabylian',
  354. 'Taqbaylit',
  355. 'kab|kabylian',
  356. '',
  357. ],
  358. 'kk' => [
  359. 'kk',
  360. 'Kazakh',
  361. 'Қазақ',
  362. 'kk|kazakh',
  363. '',
  364. ],
  365. 'km' => [
  366. 'km',
  367. 'Khmer',
  368. 'ខ្មែរ',
  369. 'km|khmer',
  370. '',
  371. ],
  372. 'kn' => [
  373. 'kn',
  374. 'Kannada',
  375. 'ಕನ್ನಡ',
  376. 'kn|kannada',
  377. '',
  378. ],
  379. 'ksh' => [
  380. 'ksh',
  381. 'Colognian',
  382. 'Kölsch',
  383. 'ksh|colognian',
  384. '',
  385. ],
  386. 'ku' => [
  387. 'ku',
  388. 'Kurdish',
  389. 'کوردی',
  390. 'ku|kurdish',
  391. '',
  392. ],
  393. 'ky' => [
  394. 'ky',
  395. 'Kyrgyz',
  396. 'Кыргызча',
  397. 'ky|kyrgyz',
  398. '',
  399. ],
  400. 'li' => [
  401. 'li',
  402. 'Limburgish',
  403. 'Lèmbörgs',
  404. 'li|limburgish',
  405. '',
  406. ],
  407. 'lt' => [
  408. 'lt',
  409. 'Lithuanian',
  410. 'Lietuvi&#371;',
  411. 'lt|lithuanian',
  412. 'lt_LT',
  413. ],
  414. 'lv' => [
  415. 'lv',
  416. 'Latvian',
  417. 'Latvie&scaron;u',
  418. 'lv|latvian',
  419. 'lv_LV',
  420. ],
  421. 'mk' => [
  422. 'mk',
  423. 'Macedonian',
  424. 'Macedonian',
  425. 'mk|macedonian',
  426. 'mk_MK',
  427. ],
  428. 'ml' => [
  429. 'ml',
  430. 'Malayalam',
  431. 'Malayalam',
  432. 'ml|malayalam',
  433. '',
  434. ],
  435. 'mn' => [
  436. 'mn',
  437. 'Mongolian',
  438. '&#1052;&#1086;&#1085;&#1075;&#1086;&#1083;',
  439. 'mn|mongolian',
  440. 'mn_MN',
  441. ],
  442. 'ms' => [
  443. 'ms',
  444. 'Malay',
  445. 'Bahasa Melayu',
  446. 'ms|malay',
  447. 'ms_MY',
  448. ],
  449. 'my' => [
  450. 'my',
  451. 'Burmese',
  452. 'မြန်မာ',
  453. 'my|burmese',
  454. '',
  455. ],
  456. 'ne' => [
  457. 'ne',
  458. 'Nepali',
  459. 'नेपाली',
  460. 'ne|nepali',
  461. '',
  462. ],
  463. 'nb' => [
  464. 'nb',
  465. 'Norwegian',
  466. 'Norsk',
  467. 'nb|norwegian',
  468. 'nb_NO',
  469. ],
  470. 'nn' => [
  471. 'nn',
  472. 'Norwegian Nynorsk',
  473. 'Nynorsk',
  474. 'nn|nynorsk',
  475. 'nn_NO',
  476. ],
  477. 'nl' => [
  478. 'nl',
  479. 'Dutch',
  480. 'Nederlands',
  481. 'nl|dutch',
  482. 'nl_NL',
  483. ],
  484. 'pa' => [
  485. 'pa',
  486. 'Punjabi',
  487. 'ਪੰਜਾਬੀ',
  488. 'pa|punjabi',
  489. '',
  490. ],
  491. 'pl' => [
  492. 'pl',
  493. 'Polish',
  494. 'Polski',
  495. 'pl|polish',
  496. 'pl_PL',
  497. ],
  498. 'pt' => [
  499. 'pt',
  500. 'Portuguese',
  501. 'Portugu&ecirc;s',
  502. 'pt|portuguese',
  503. 'pt_PT',
  504. ],
  505. 'pt_br' => [
  506. 'pt_BR',
  507. 'Portuguese (Brazil)',
  508. 'Portugu&ecirc;s (Brasil)',
  509. 'pt[-_]br|portuguese (brazil)',
  510. 'pt_BR',
  511. ],
  512. 'rcf' => [
  513. 'rcf',
  514. 'R&eacute;union Creole',
  515. 'Kr&eacute;ol',
  516. 'rcf|creole (reunion)',
  517. '',
  518. ],
  519. 'ro' => [
  520. 'ro',
  521. 'Romanian',
  522. 'Rom&acirc;n&#259;',
  523. 'ro|romanian',
  524. 'ro_RO',
  525. ],
  526. 'ru' => [
  527. 'ru',
  528. 'Russian',
  529. '&#1056;&#1091;&#1089;&#1089;&#1082;&#1080;&#1081;',
  530. 'ru|russian',
  531. 'ru_RU',
  532. ],
  533. 'si' => [
  534. 'si',
  535. 'Sinhala',
  536. '&#3523;&#3538;&#3458;&#3524;&#3517;',
  537. 'si|sinhala',
  538. '',
  539. ],
  540. 'sk' => [
  541. 'sk',
  542. 'Slovak',
  543. 'Sloven&#269;ina',
  544. 'sk|slovak',
  545. 'sk_SK',
  546. ],
  547. 'sl' => [
  548. 'sl',
  549. 'Slovenian',
  550. 'Sloven&scaron;&#269;ina',
  551. 'sl|slovenian',
  552. 'sl_SI',
  553. ],
  554. 'sq' => [
  555. 'sq',
  556. 'Albanian',
  557. 'Shqip',
  558. 'sq|albanian',
  559. 'sq_AL',
  560. ],
  561. 'sr@latin' => [
  562. 'sr@latin',
  563. 'Serbian (latin)',
  564. 'Srpski',
  565. 'sr[-_]lat|sr@latin|serbian latin',
  566. 'sr_YU',
  567. ],
  568. 'sr' => [
  569. 'sr',
  570. 'Serbian',
  571. '&#1057;&#1088;&#1087;&#1089;&#1082;&#1080;',
  572. 'sr|serbian',
  573. 'sr_YU',
  574. ],
  575. 'sv' => [
  576. 'sv',
  577. 'Swedish',
  578. 'Svenska',
  579. 'sv|swedish',
  580. 'sv_SE',
  581. ],
  582. 'ta' => [
  583. 'ta',
  584. 'Tamil',
  585. 'தமிழ்',
  586. 'ta|tamil',
  587. 'ta_IN',
  588. ],
  589. 'te' => [
  590. 'te',
  591. 'Telugu',
  592. 'తెలుగు',
  593. 'te|telugu',
  594. 'te_IN',
  595. ],
  596. 'th' => [
  597. 'th',
  598. 'Thai',
  599. '&#3616;&#3634;&#3625;&#3634;&#3652;&#3607;&#3618;',
  600. 'th|thai',
  601. 'th_TH',
  602. ],
  603. 'tk' => [
  604. 'tk',
  605. 'Turkmen',
  606. 'Türkmençe',
  607. 'tk|turkmen',
  608. '',
  609. ],
  610. 'tr' => [
  611. 'tr',
  612. 'Turkish',
  613. 'T&uuml;rk&ccedil;e',
  614. 'tr|turkish',
  615. 'tr_TR',
  616. ],
  617. 'tt' => [
  618. 'tt',
  619. 'Tatarish',
  620. 'Tatar&ccedil;a',
  621. 'tt|tatarish',
  622. '',
  623. ],
  624. 'tzm' => [
  625. 'tzm',
  626. 'Central Atlas Tamazight',
  627. 'Tamaziɣt',
  628. 'tzm|central atlas tamazight',
  629. '',
  630. ],
  631. 'ug' => [
  632. 'ug',
  633. 'Uyghur',
  634. 'ئۇيغۇرچە',
  635. 'ug|uyghur',
  636. '',
  637. ],
  638. 'uk' => [
  639. 'uk',
  640. 'Ukrainian',
  641. '&#1059;&#1082;&#1088;&#1072;&#1111;&#1085;&#1089;&#1100;&#1082;&#1072;',
  642. 'uk|ukrainian',
  643. 'uk_UA',
  644. ],
  645. 'ur' => [
  646. 'ur',
  647. 'Urdu',
  648. 'اُردوُ',
  649. 'ur|urdu',
  650. 'ur_PK',
  651. ],
  652. 'uz@latin' => [
  653. 'uz@latin',
  654. 'Uzbek (latin)',
  655. 'O&lsquo;zbekcha',
  656. 'uz[-_]lat|uz@latin|uzbek-latin',
  657. '',
  658. ],
  659. 'uz' => [
  660. 'uz',
  661. 'Uzbek (cyrillic)',
  662. '&#1038;&#1079;&#1073;&#1077;&#1082;&#1095;&#1072;',
  663. 'uz[-_]cyr|uz@cyrillic|uzbek-cyrillic',
  664. '',
  665. ],
  666. 'vi' => [
  667. 'vi',
  668. 'Vietnamese',
  669. 'Tiếng Việt',
  670. 'vi|vietnamese',
  671. 'vi_VN',
  672. ],
  673. 'vls' => [
  674. 'vls',
  675. 'Flemish',
  676. 'West-Vlams',
  677. 'vls|flemish',
  678. '',
  679. ],
  680. 'zh_tw' => [
  681. 'zh_TW',
  682. 'Chinese traditional',
  683. '&#20013;&#25991;',
  684. 'zh[-_](tw|hk)|chinese traditional',
  685. 'zh_TW',
  686. ],
  687. // only TW and HK use traditional Chinese while others (CN, SG, MY)
  688. // use simplified Chinese
  689. 'zh_cn' => [
  690. 'zh_CN',
  691. 'Chinese simplified',
  692. '&#20013;&#25991;',
  693. 'zh(?![-_](tw|hk))([-_][[:alpha:]]{2,3})?|chinese simplified',
  694. 'zh_CN',
  695. ],
  696. ];
  697. /** @var array */
  698. private $availableLocales;
  699. /** @var array */
  700. private $availableLanguages = [];
  701. /** @var bool */
  702. private $langFailedConfig = false;
  703. /** @var bool */
  704. private $langFailedCookie = false;
  705. /** @var bool */
  706. private $langFailedRequest = false;
  707. /** @var LanguageManager */
  708. private static $instance;
  709. /**
  710. * Returns LanguageManager singleton
  711. *
  712. * @return LanguageManager
  713. */
  714. public static function getInstance()
  715. {
  716. if (self::$instance === null) {
  717. self::$instance = new LanguageManager();
  718. }
  719. return self::$instance;
  720. }
  721. /**
  722. * Returns list of available locales
  723. *
  724. * @return array
  725. */
  726. public function listLocaleDir()
  727. {
  728. $result = ['en'];
  729. /* Check for existing directory */
  730. if (! is_dir(LOCALE_PATH)) {
  731. return $result;
  732. }
  733. /* Open the directory */
  734. $handle = @opendir(LOCALE_PATH);
  735. /* This can happen if the kit is English-only */
  736. if ($handle === false) {
  737. return $result;
  738. }
  739. /* Process all files */
  740. while (($file = readdir($handle)) !== false) {
  741. $path = LOCALE_PATH
  742. . '/' . $file
  743. . '/LC_MESSAGES/phpmyadmin.mo';
  744. if ($file === '.' || $file === '..' || ! @file_exists($path)) {
  745. continue;
  746. }
  747. $result[] = $file;
  748. }
  749. /* Close the handle */
  750. closedir($handle);
  751. return $result;
  752. }
  753. /**
  754. * Returns (cached) list of all available locales
  755. *
  756. * @return array of strings
  757. */
  758. public function availableLocales()
  759. {
  760. if (! $this->availableLocales) {
  761. if (! isset($GLOBALS['config']) || empty($GLOBALS['config']->get('FilterLanguages'))) {
  762. $this->availableLocales = $this->listLocaleDir();
  763. } else {
  764. $this->availableLocales = preg_grep(
  765. '@' . $GLOBALS['config']->get('FilterLanguages') . '@',
  766. $this->listLocaleDir()
  767. );
  768. }
  769. }
  770. return $this->availableLocales;
  771. }
  772. /**
  773. * Checks whether there are some languages available
  774. */
  775. public function hasChoice(): bool
  776. {
  777. return count($this->availableLanguages()) > 1;
  778. }
  779. /**
  780. * Returns (cached) list of all available languages
  781. *
  782. * @return Language[] array of Language objects
  783. */
  784. public function availableLanguages()
  785. {
  786. if (! $this->availableLanguages) {
  787. $this->availableLanguages = [];
  788. foreach ($this->availableLocales() as $lang) {
  789. $lang = strtolower($lang);
  790. if (isset(static::$languageData[$lang])) {
  791. $data = static::$languageData[$lang];
  792. $this->availableLanguages[$lang] = new Language($data[0], $data[1], $data[2], $data[3], $data[4]);
  793. } else {
  794. $this->availableLanguages[$lang] = new Language(
  795. $lang,
  796. ucfirst($lang),
  797. ucfirst($lang),
  798. $lang,
  799. ''
  800. );
  801. }
  802. }
  803. }
  804. return $this->availableLanguages;
  805. }
  806. /**
  807. * Returns (cached) list of all available languages sorted
  808. * by name
  809. *
  810. * @return Language[] array of Language objects
  811. */
  812. public function sortedLanguages()
  813. {
  814. $this->availableLanguages();
  815. uasort($this->availableLanguages, static function (Language $a, Language $b) {
  816. return $a->cmp($b);
  817. });
  818. return $this->availableLanguages;
  819. }
  820. /**
  821. * Return Language object for given code
  822. *
  823. * @param string $code Language code
  824. *
  825. * @return Language|false Language object or false on failure
  826. */
  827. public function getLanguage($code)
  828. {
  829. $code = strtolower($code);
  830. $langs = $this->availableLanguages();
  831. if (isset($langs[$code])) {
  832. return $langs[$code];
  833. }
  834. return false;
  835. }
  836. /**
  837. * Return currently active Language object
  838. *
  839. * @return Language Language object
  840. */
  841. public function getCurrentLanguage()
  842. {
  843. return $this->availableLanguages[strtolower($GLOBALS['lang'])];
  844. }
  845. /**
  846. * Activates language based on configuration, user preferences or
  847. * browser
  848. *
  849. * @return Language
  850. */
  851. public function selectLanguage()
  852. {
  853. // check forced language
  854. if (! empty($GLOBALS['config']->get('Lang'))) {
  855. $lang = $this->getLanguage($GLOBALS['config']->get('Lang'));
  856. if ($lang !== false) {
  857. return $lang;
  858. }
  859. $this->langFailedConfig = true;
  860. }
  861. // Don't use REQUEST in following code as it might be confused by cookies
  862. // with same name. Check user requested language (POST)
  863. if (! empty($_POST['lang'])) {
  864. $lang = $this->getLanguage($_POST['lang']);
  865. if ($lang !== false) {
  866. return $lang;
  867. }
  868. $this->langFailedRequest = true;
  869. }
  870. // check user requested language (GET)
  871. if (! empty($_GET['lang'])) {
  872. $lang = $this->getLanguage($_GET['lang']);
  873. if ($lang !== false) {
  874. return $lang;
  875. }
  876. $this->langFailedRequest = true;
  877. }
  878. // check previous set language
  879. if (! empty($GLOBALS['config']->getCookie('pma_lang'))) {
  880. $lang = $this->getLanguage($GLOBALS['config']->getCookie('pma_lang'));
  881. if ($lang !== false) {
  882. return $lang;
  883. }
  884. $this->langFailedCookie = true;
  885. }
  886. $langs = $this->availableLanguages();
  887. // try to find out user's language by checking its HTTP_ACCEPT_LANGUAGE variable;
  888. $accepted_languages = Core::getenv('HTTP_ACCEPT_LANGUAGE');
  889. if ($accepted_languages) {
  890. foreach (explode(',', $accepted_languages) as $header) {
  891. foreach ($langs as $language) {
  892. if ($language->matchesAcceptLanguage($header)) {
  893. return $language;
  894. }
  895. }
  896. }
  897. }
  898. // try to find out user's language by checking its HTTP_USER_AGENT variable
  899. $user_agent = Core::getenv('HTTP_USER_AGENT');
  900. if (! empty($user_agent)) {
  901. foreach ($langs as $language) {
  902. if ($language->matchesUserAgent($user_agent)) {
  903. return $language;
  904. }
  905. }
  906. }
  907. // Didn't catch any valid lang : we use the default settings
  908. if (isset($langs[$GLOBALS['config']->get('DefaultLang')])) {
  909. return $langs[$GLOBALS['config']->get('DefaultLang')];
  910. }
  911. // Fallback to English
  912. return $langs['en'];
  913. }
  914. /**
  915. * Displays warnings about invalid languages. This needs to be postponed
  916. * to show messages at time when language is initialized.
  917. */
  918. public function showWarnings(): void
  919. {
  920. // now, that we have loaded the language strings we can send the errors
  921. if (! $this->langFailedConfig && ! $this->langFailedCookie && ! $this->langFailedRequest) {
  922. return;
  923. }
  924. trigger_error(
  925. __('Ignoring unsupported language code.'),
  926. E_USER_ERROR
  927. );
  928. }
  929. }