Files
人事系统开发 1ba6efd8ed MRBS 1.12.2 等保2.0二级整改完整提交
包含:登录失败锁定、90天密码有效期、30分钟会话超时、
强制改密、登录审计日志、屏幕水印、企业背景图、
备案信息固定底部、favicon、JS空集合保护、
会话过期体验优化(403 JSON)、display_errors 关闭、
固定 key 根治 Integrity check failed 等全部改动

注意:config.inc.php/.htaccess/.user.ini 含敏感信息,
通过 .gitignore 排除,勿推送到公开仓库。
2026-09-09 16:55:02 +08:00

1277 lines
45 KiB
PHP

<?php
declare(strict_types=1);
namespace MRBS;
use MRBS\Intl\Locale;
use ResourceBundle;
class System
{
public const BIG_ENDIAN = 0;
public const LITTLE_ENDIAN = 1;
/**
* A set of special cases where the default region is different from the language.
* (Normally the region is the same as the language, eg 'fr' => 'FR'.)
* @var array<string, string> $default_regions
*/
private static $default_regions = array(
'ca' => 'ES',
'cs' => 'CZ',
'da' => 'DK',
'el' => 'GR',
'en' => 'GB',
'et' => 'EE',
'eu' => 'ES',
'ja' => 'JP',
'ko' => 'KR',
'nb' => 'NO',
'nn' => 'NO',
'sh' => 'RS',
'sl' => 'SI',
'sr' => 'RS',
'sv' => 'SE',
'zh' => 'CN',
);
// A map is needed to convert from the HTTP language specifier to a
// locale specifier for Windows
//
// The ordering of this array is important as it is also used to map in the
// reverse direction, ie to convert a Windows style locale into an xx-yy style
// locale by finding the first occurrence of a value and then using the
// corresponding key.
//
// See https://www.iana.org/assignments/language-subtag-registry/language-subtag-registry
// for language tags.
//
// Windows locales can be found by running the following PHP code on a Windows system
/*
foreach (range('a', 'z') as $a)
{
foreach (range('a', 'z') as $b)
{
foreach (range('a', 'z') as $c)
{
$locale = "$a$b$c";
setlocale(LC_ALL, $locale);
$result = setlocale(LC_ALL, '0');
if ($locale != $result)
{
echo "$locale: $result\n";
}
}
}
}
*/
private static $lang_map_windows = array(
'aa-et' => 'zzz', // Afar_Ethiopia.utf8
'af-za' => 'afk', // Afrikaans_South Africa.1252
'am' => 'amh', // Amharic.utf8
'am-et' => 'amh', // Amharic_Ethiopia.utf8
'ar-ae' => 'aru', // Arabic_United Arab Emirates.1256
'ar-bh' => 'arh', // Arabic_Bahrain.1256
'ar-dz' => 'arg', // Arabic_Algeria.1256
'ar-eg' => 'are', // Arabic_Egypt.1256
'ar-iq' => 'ari', // Arabic_Iraq.1256
'ar-jo' => 'arj', // Arabic_Jordan.1256
'ar-kw' => 'ark', // Arabic_Kuwait.1256
'ar-lb' => 'arb', // Arabic_Lebanon.1256
'ar-ly' => 'arl', // Arabic_Libya.1256
'ar-ma' => 'arm', // Arabic_Morocco.1256
'ar-om' => 'aro', // Arabic_Oman.1256
'ar-qa' => 'arq', // Arabic_Qatar.1256
'ar-sa' => 'ara', // Arabic_Saudi Arabia.1256
'ar-sy' => 'ars', // Arabic_Syria.1256
'ar-tn' => 'art', // Arabic_Tunisia.1256
'ar-ye' => 'ary', // Arabic_Yemen.1256
'arn' => 'mpd', // Mapudungun.1252
'arn-cl' => 'mpd', // Mapudungun_Chile.1252
'as-in' => 'asm', // Assamese_India.utf8
'az' => 'aze', // Azerbaijani.1254
'az-cyrl' => 'azc', // Azerbaijani (Cyrillic).1251
'az-cyrl-az' => 'azc', // Azerbaijani (Cyrillic)_Azerbaijan.1251
'az-latn' => 'aze', // Azerbaijani.1254
'az-latn-az' => 'aze', // Azerbaijani_Azerbaijan.1254
'ba-ru' => 'bas', // Bashkir_Russia.1251
'bg' => 'bgr', // Bulgarian.1251
'bg-bg' => 'bgr', // Bulgarian_Bulgaria.1251
'be' => 'bel', // Belarusian.1251
'be-by' => 'bel', // Belarusian_Belarus.1251
'bn-bd' => 'bnb', // Bangla_Bangladesh.utf8
'bn-in' => 'bng', // Bengali_India.utf8
'bo-cn' => 'bob', // Tibetan_China.utf8
'br-fr' => 'bre', // Breton_France.1252
'bs' => 'bsb', // Bosnian.1250'
'bs-cyrl' => 'bsc', // Bosnian (Cyrillic).1251
'bs-cyrl-ba' => 'bsc', // Bosnian (Cyrillic)_Bosnia and Herzegovina.1251
'bs-latn' => 'bsb', // Bosnian_Bosnia and Herzegovina.1250'
'bs-latn-ba' => 'bsb', // Bosnian_Bosnia and Herzegovina.1250
'ca' => 'cat', // Catalan_Spain.1252
'ca-es' => 'cat', // Catalan_Spain.1252
'chr-us' => 'cre', // Cherokee_United States.utf8
'ckb-iq' => 'kur', // Central Kurdish_Iraq.1256
'co' => 'cos', // Corsican.1252
'co-fr' => 'cos', // Corsican_France.1252
'cs' => 'csy', // Czech.1250
'cs-cz' => 'csy', // Czech_Czechia.1250
'cy' => 'cym', // Welsh.1252'
'cy-gb' => 'cym', // Welsh_United Kingdom.1252'
'da' => 'dan', // Danish.1252
'da-dk' => 'dan', // Danish_Denmark.1252
'de' => 'deu', // German.1252
'de-at' => 'dea', // German_Austria.1252
'de-ch' => 'des', // German_Switzerland.1252
'de-de' => 'deu', // German_Germany.1252
'de-li' => 'dec', // German_Liechtenstein.1252
'de-lu' => 'del', // German_Luxembourg.1252
'dsb-de' => 'dsb', // Lower Sorbian_Germany.1252
'dv-mv' => 'div', // Divehi_Maldives.utf8'
'el' => 'ell', // Greek.1253
'el-gr' => 'ell', // Greek_Greece.1253
'en' => 'enu', // English.1252
'en-au' => 'ena', // English_Australia.1252
'en-bz' => 'enl', // English_Belize.1252
'en-ca' => 'enc', // English_Canada.1252
'en-cb' => 'enb', // English_Caribbean.1252
'en-gb' => 'eng', // English_United Kingdom.1252
'en-hk' => 'enh', // English_Hong Kong SAR.1252
'en-ie' => 'eni', // English_Ireland.1252
'en-in' => 'enn', // English_India.1252
'en-jm' => 'enj', // English_Jamaica.1252
'en-my' => 'enm', // English_Malaysia.1252
'en-nz' => 'enz', // English_New Zealand.1252
'en-ph' => 'enp', // English_Philippines.1252
'en-sg' => 'ene', // English_Singapore.1252
'en-tt' => 'ent', // English_Trinidad and Tobago.1252
'en-us' => 'enu', // English_United States.1252
'en-za' => 'ens', // English_South Africa.1252
'en-zw' => 'enw', // English_Zimbabwe.1252
'es' => 'esp', // Spanish_Spain.1252
'es-419' => 'esj', // Spanish_Latin America.1252
'es-ar' => 'ess', // Spanish_Argentina.1252
'es-bo' => 'esb', // Spanish_Bolivia.1252
'es-cl' => 'esl', // Spanish_Chile.1252
'es-co' => 'eso', // Spanish_Colombia.1252
'es-cr' => 'esc', // Spanish_Costa Rica.1252
'es-cu' => 'esk', // Spanish_Cuba.1252
'es-do' => 'esd', // Spanish_Dominican Republic.1252
'es-ec' => 'esf', // Spanish_Ecuador.1252
'es-es' => 'esn', // Spanish_Spain.1252
'es-gt' => 'esg', // Spanish_Guatemala.1252
'es-hn' => 'esh', // Spanish_Honduras.1252
'es-mx' => 'esm', // Spanish_Mexico.1252
'es-ni' => 'esi', // Spanish_Nicaragua.1252
'es-pa' => 'esa', // Spanish_Panama.1252
'es-pe' => 'esr', // Spanish_Peru.1252
'es-pr' => 'esu', // Spanish_Puerto Rico.1252
'es-py' => 'esz', // Spanish_Paraguay.1252
'es-sv' => 'ese', // Spanish_El Salvador.1252
'es-us' => 'est', // Spanish_United States.1252
'es-uy' => 'esy', // Spanish_Uruguay.1252
'es-ve' => 'esv', // Spanish_Venezuela.1252
'et' => 'eti', // Estonian.1257
'et-ee' => 'eti', // Estonian_Estonia.1257
'eu' => 'euq', // Basque.1252
'eu-es' => 'euq', // Basque_Spain.1252
'fa' => 'far', // Persian.1256
'fa-ir' => 'far', // Persian_Iran.1256
'ff-latn-sn' => 'ful', // Fulah (Latin)_Senegal.1252
'fi' => 'fin', // Finnish.1252
'fi-fi' => 'fin', // Finnish_Finland.1252
'fil' => 'fpo', // Filipino.1252
'fil-ph' => 'fpo', // Filipino_Philippines.1252
'fo' => 'fos', // Faroese.1252
'fo-fo' => 'fos', // Faroese_Faroe Islands.1252
'fr' => 'fra', // French.1252
'fr-be' => 'frb', // French_Belgium.1252
'fr-ca' => 'frc', // French_Canada.1252
'fr-cg' => 'frd', // French_Congo (DRC).1252
'fr-ch' => 'frs', // French_Switzerland.1252
'fr-ci' => 'fri', // French_Côte d'Ivoire.1252
'fr-cm' => 'fre', // French_Cameroon.1252
'fr-fr' => 'fra', // French_France.1252
'fr-ht' => 'frh', // French_Haiti.1252
'fr-lu' => 'frl', // French_Luxembourg.1252
'fr-ma' => 'fro', // French_Morocco.1252
'fr-mc' => 'frm', // French_Monaco.1252
'fr-ml' => 'frf', // French_Mali.1252
'fr-re' => 'frr', // French_Réunion.1252'
'fr-sn' => 'frn', // French_Senegal.1252
'fy' => 'fyn', // Western Frisian.1252
'fy-nl' => 'fyn', // Western Frisian_Netherlands.1252
'ga' => 'ire', // Irish.1252
'ga-ie' => 'ire', // Irish_Ireland.1252
'gaz-et' => 'orm', // Oromo_Ethiopia.utf8
'gd' => 'gla', // Scottish Gaelic.1252
'gd-gb' => 'gla', // Scottish Gaelic_United Kingdom.1252
'gl' => 'glc', // Galician.1252
'gl-es' => 'glc', // Galician_Spain.1252
'gn-py' => 'grn', // Guarani_Paraguay.1252
'gsw-fr' => 'gsw', // Alsatian_France.1252
'gu' => 'guj', // Gujarati.utf8
'gu-in' => 'guj', // Gujarati_India.utf8
'ha' => 'hau', // Hausa.1252
'ha-latn' => 'hau', // Hausa.1252'
'ha-latn-ng' => 'hau', // Hausa_Nigeria.1252
'haw-us' => 'haw', // Hawaiian_United States.1252
'he' => 'heb', // Hebrew_Israel.1255
'he-il' => 'heb', // Hebrew_Israel.1255
'hi' => 'hin', // Hindi.utf8
'hi-in' => 'hin', // Hindi_India.utf8
'hr' => 'hrv', // Croatian.1250
'hr-ba' => 'hrb', // Croatian_Bosnia and Herzegovina.1250
'hr-hr' => 'hrv', // Croatian_Croatia.1250
'hsb' => 'hsb', // Upper Sorbian.1252
'hsb-de' => 'hsb', // Upper Sorbian_Germany.1252
'hu' => 'hun', // Hungarian.1250
'hu-hu' => 'hun', // Hungarian_Hungary.1250
'hy' => 'hye', // Armenian.utf8
'hy-am' => 'hye', // Armenian_Armenia.utf8
'id' => 'ind', // Indonesian.1252
'id-id' => 'ind', // Indonesian_Indonesia.1252
'ig' => 'ibo', // Igbo.1252
'ig-ng' => 'ibo', // Igbo_Nigeria.1252
'ii' => 'iii', // Yi.utf8
'ii-cn' => 'iii', // Yi_China.utf8
'is' => 'isl', // Icelandic.1252
'is-is' => 'isl', // Icelandic_Iceland.1252
'it' => 'ita', // Italian.1252
'it-ch' => 'its', // Italian_Switzerland.1252
'it-it' => 'ita', // Italian_Italy.1252
'iu' => 'iuk', // Inuktitut.1252
'iu-cans-ca' => 'ius', // Inuktitut (Syllabics)_Canada.utf8
'iu-latn' => 'iuk', // Inuktitut.1252
'iu-latn-ca' => 'iuk', // Inuktitut_Canada.1252
'ja' => 'jpn', // Japanese.932
'ja-jp' => 'jpn', // Japanese_Japan.932
'jv-id' => 'jav', // Javanese_Indonesia.1252
'ka' => 'kat', // Georgian.utf8
'ka-ge' => 'kat', // Georgian_Georgia.utf8
'kk' => 'kkz', // Kazakh.utf8
'kk-kz' => 'kkz', // Kazakh_Kazakhstan.utf8
'kl-gl' => 'kal', // Greenlandic_Greenland.1252
'km' => 'khm', // Khmer.utf8
'km-kh' => 'khm', // Khmer_Cambodia.utf8
'kn' => 'kdi', // Kannada.utf8
'kn-in' => 'kdi', // Kannada_India.utf8
'ko' => 'kor', // Korean.949
'ko-kr' => 'kor', // Korean_Korea.949
'kok' => 'knk', // Konkani.utf8
'kok-in' => 'knk', // Konkani_India.utf8
'ky-kg' => 'kyr', // Kyrgyz_Kyrgyzstan.1251
'lb' => 'lbx', // Luxembourgish.1252
'lb-lu' => 'lbx', // Luxembourgish_Luxembourg.1252
'lo' => 'lao', // Lao.utf8
'lo-la' => 'lao', // Lao_Laos.utf8
'lt' => 'lth', // Lithuanian.1257
'lt-lt' => 'lth', // Lithuanian_Lithuania.1257
'lv' => 'lvi', // Latvian.1257
'lv-lv' => 'lvi', // Latvian_Latvia.1257
'mk' => 'mki', // Macedonian.1251
'mk-mk' => 'mki', // Macedonian_North Macedonia.1251
'mi' => 'mri', // Maori.utf8
'mi-nz' => 'mri', // Maori_New Zealand.utf8
'ml' => 'mym', // Malayalam.utf8
'ml-in' => 'mym', // Malayalam_India.utf8
'mn' => 'mnn', // Mongolian_Mongolia.1251
'mn-mn' => 'mnn', // Mongolian_Mongolia.1251
'mn-mong-cn' => 'mng', // Mongolian (Traditional Mongolian)_China.utf8
'mn-mong-mn' => 'mnm', // Mongolian (Traditional Mongolian)_Mongolia.utf8
'moh' => 'mwk', // Mohawk.1252
'moh-ca' => 'mwk', // Mohawk_Canada.1252
'mr' => 'mar', // Marathi.utf8
'mr-in' => 'mar', // Marathi_India.utf8
'ms' => 'msl', // Malay.1252
'ms-bn' => 'msb', // Malay_Brunei.1252
'ms-my' => 'msl', // Malay_Malaysia.1252
'mt' => 'mlt', // Maltese.utf8
'mt-mt' => 'mlt', // Maltese_Malta.utf8
'my' => 'mya', // Burmese.utf8
'my-mm' => 'mya', // Burmese_Myanmar.utf8
'nb' => 'nor', // Norwegian Bokmål.1252
'nb-no' => 'nor', // Norwegian Bokmål_Norway.1252
'ne-in' => 'nei', // Nepali_India.utf8
'ne-np' => 'nep', // Nepali_Nepal.utf8
'ngo-gn' => 'nqo', // N'ko_Guinea.utf8
'nl' => 'nld', // Dutch.1252
'nl-be' => 'nlb', // Dutch_Belgium.1252
'nl-nl' => 'nld', // Dutch_Netherlands.1252
'nn' => 'non', // Norwegian Nynorsk.1252
'nn-no' => 'non', // Norwegian Nynorsk_Norway.1252
'no' => 'nor', // Norwegian.1252
'no-no' => 'nor', // Norwegian_Norway.1252
'nso-za' => 'nso', // Sesotho sa Leboa_South Africa.1252
'oc' => 'oci', // Occitan.1252
'oc-fr' => 'oci', // Occitan_France.1252
'ory-in' => 'ori', // Odia_India.utf8
'pa-in' => 'pan', // Punjabi_India.utf8
'pa-pk' => 'pap', // Punjabi_Pakistan.1256
'pl' => 'plk', // Polish.1250
'pl-pl' => 'plk', // Polish_Poland.1250
'plt-mg' => 'mlg', // Malagasy_Madagascar.utf8
'prs' => 'prs', // Dari.1256
'prs-af' => 'prs', // Dari_Afghanistan.1256
'ps-af' => 'pas', // Pashto_Afghanistan.utf8
'pt' => 'ptb', // Portuguese.1252
'pt-ao' => 'pta', // Portuguese_Angola.1252
'pt-br' => 'ptb', // Portuguese_Brazil.1252
'pt-pt' => 'ptg', // Portuguese_Portugal.1252
'quc-gt' => 'qut', // K'iche'_Guatemala.1252
'quz-bo' => 'qub', // Quechua_Bolivia.1252
'quz-ec' => 'que', // Quechua_Ecuador.1252
'quz-pe' => 'qup', // Quechua_Peru.1252
'rm-ch' => 'rmc', // Romansh_Switzerland.1252
'ro' => 'rom', // Romanian.1250
'ro-md' => 'rod', // Romanian_Moldova.1250
'ro-ro' => 'rom', // Romanian_Romania.1250
'ru' => 'rus', // Russian.1251
'ru-md' => 'rum', // Russian_Moldova.1251
'ru-ru' => 'rus', // Russian_Russia.1251
'rw' => 'kin', // Kinyarwanda.1252
'rw-rw' => 'kin', // Kinyarwanda_Rwanda.1252
'sa' => 'san', // Sanskrit.utf8
'sa-in' => 'san', // Sanskrit_India.utf8
'sah-ru' => 'sah', // Sakha_Russia.1251
'sd-pk' => 'sip', // Sindhi_Pakistan.1256
'se-fi' => 'smg', // Sami (Northern)_Finland.1252
'se-no' => 'sme', // Northern Sami_Norway.1252
'se-se' => 'smf', // Sami (Northern)_Sweden.1252
'si' => 'sin', // Sinhala.utf8
'si-lk' => 'sin', // Sinhala_Sri Lanka.utf8
'sk' => 'sky', // Slovak.1250
'sk-sk' => 'sky', // Slovak_Slovakia.1250
'sl' => 'slv', // Slovenian.1250
'sl-si' => 'slv', // Slovenian_Slovenia.1250
'sma-no' => 'sma', // Sami (Southern)_Norway.1252
'sma-se' => 'smb', // Sami (Southern)_Sweden.1252
'smj-no' => 'smj', // Sami (Lule)_Norway.1252
'smj-se' => 'smk', // Sami (Lule)_Sweden.1252
'smn-fi' => 'smn', // Sami (Inari)_Finland.1252
'sms-fi' => 'sms', // Sami (Skolt)_Finland.1252
'sn-zw' => 'sna', // Shona_Zimbabwe.utf8
'so-so' => 'som', // Somali_Somalia.utf8
'sq' => 'sqi', // Albanian.1250
'sq-al' => 'sqi', // Albanian_Albania.1250
'sr' => 'srl', // Serbian.1250
'sr-cyrl-ba' => 'srn', // Serbian (Cyrillic)_Bosnia and Herzegovina.1251
'sr-cyrl-me' => 'srq', // Serbian (Cyrillic)_Montenegro.1251
'sr-cyrl-rs' => 'sro', // Serbian (Cyrillic)_Serbia.1251
'sr-latn-ba' => 'srs', // Serbian (Latin)_Bosnia and Herzegovina.1250
'sr-latn-me' => 'srp', // Serbian (Latin)_Montenegro.1250
'sr-latn-rs' => 'srm', // Serbian (Latin)_Serbia.1250
'sr-hr' => 'srb', // Serbian_Croatia.1250
'sr-rs' => 'srb', // Serbian_Serbia.1250
'st-za' => 'sot', // Sesotho_South Africa.utf8
'sv' => 'sve', // Swedish.1252
'sv-fi' => 'svf', // Swedish_Finland.1252
'sv-se' => 'sve', // Swedish_Sweden.1252
'sw' => 'swk', // Kiswahili.1252
'sw-ke' => 'swk', // Kiswahili_Kenya.1252
'syr' => 'syr', // Syriac.utf8
'syr-sy' => 'syr', // Syriac_Syria.utf8
'ta-in' => 'tai', // Tamil_India.utf8
'ta-lk' => 'tam', // Tamil_Sri Lanka.utf8
'te-in' => 'tel', // Telugu_India.utf8
'tg-cyrl-tj' => 'taj', // Tajik_Tajikistan.1251
'th' => 'tha', // Thai.874
'th-th' => 'tha', // Thai_Thailand.874
'ti-er' => 'tir', // Tigrinya_Eritrea.utf8
'ti-et' => 'tie', // Tigrinya_Ethiopia.utf8
'tk' => 'tuk', // Turkmen_Turkmenistan.1250
'tk-tm' => 'tuk', // Turkmen_Turkmenistan.1250
'tn-bw' => 'tsb', // Setswana_Botswana.1252
'tn-za' => 'tsn', // Setswana_South Africa.1252
'tr' => 'trk', // Turkish.1254
'tr-tr' => 'trk', // Turkish_Turkey.1254
'ts-za' => 'tso', // Tsonga_South Africa.utf8
'tt' => 'ttt', // Tatar.1251
'tt-ru' => 'ttt', // Tatar_Russia.1251
'tzm-latn-dz' => 'tza', // Central Atlas Tamazight_Algeria.1252
'tzm-latn-ma' => 'tzm', // Central Atlas Tamazight (Tifinagh)_Morocco.utf8
'ug' => 'uig', // Uyghur.1256
'ug-cn' => 'uig', // Uyghur_China.1256
'uk' => 'ukr', // Ukrainian.1251
'uk-ua' => 'ukr', // Ukrainian_Ukraine.1251
'ur-in' => 'uri', // Urdu_India.1256
'ur-pk' => 'urd', // Urdu_Pakistan.1256
'uz-cyrl' => 'uzc', // Uzbek (Cyrillic).1251
'uz-cyrl-uz' => 'uzc', // Uzbek (Cyrillic)_Uzbekistan.1251
'uz-latn' => 'uzb', // Uzbek.1254
'uz-latn-uz' => 'uzb', // Uzbek_Uzbekistan.1254
'vi' => 'vit', // Vietnamese.1258
'vi-vn' => 'vit', // Vietnamese_Vietnam.1258
'wo' => 'wol', // Wolof.1252
'wo-sn' => 'wol', // Wolof_Senegal.1252
'xh' => 'xho', // isiXhosa.1252
'xh-za' => 'xho', // isiXhosa_South Africa.1252
'yo' => 'yor', // Yoruba.1252
'yo-ng' => 'yor', // Yoruba_Nigeria.1252
'zgh-ma' => 'zhg', // Standard Moroccan Tamazight_Morocco.utf8
'zh' => 'chs', // Chinese.936
'zh-cn' => 'chs', // Chinese_China.936
'zh-hans-sg' => 'zhi', // Chinese (Simplified)_Singapore.936
'zh-hant-hk' => 'zhh', // Chinese (Traditional)_Hong Kong SAR.950
'zh-hant-mo' => 'zhm', // Chinese (Traditional)_Macao SAR.950
'zh-hk' => 'zhh', // Chinese_Hong Kong SAR.950
'zh-mo' => 'zhm', // Chinese_Macao SAR.950
'zh-sg' => 'zhi', // Chinese_Singapore.936
'zh-tw' => 'cht', // Chinese_Taiwan.950
'zu' => 'zul', // isiZulu.1252
'zu-za' => 'zul' // isiZulu_South Africa.1252
);
// This maps a Windows locale to the charset it uses, which are
// all Windows code pages
//
// The code pages used by these locales found at:
// http://msdn.microsoft.com/en-us/goglobal/bb896001.aspx
private static $winlocale_codepage_map = array(
'afk' => 'CP1252',
'amh' => 'utf-8',
'ara' => 'CP1256',
'arb' => 'CP1256',
'are' => 'CP1256',
'arg' => 'CP1256',
'arh' => 'CP1256',
'ari' => 'CP1256',
'arj' => 'CP1256',
'ark' => 'CP1256',
'arl' => 'CP1256',
'arm' => 'CP1256',
'aro' => 'CP1256',
'arq' => 'CP1256',
'ars' => 'CP1256',
'art' => 'CP1256',
'aru' => 'CP1256',
'ary' => 'CP1256',
'asm' => 'utf-8',
'azc' => 'CP1251',
'aze' => 'CP1254',
'bas' => 'CP1251',
'bel' => 'CP1251',
'bgr' => 'CP1251',
'bnb' => 'utf-8',
'bng' => 'utf-8',
'bob' => 'utf-8',
'bre' => 'CP1252',
'bsb' => 'CP1250',
'bsc' => 'CP1251',
'cat' => 'CP1252',
'chh' => 'CP950',
'chi' => 'CP936',
'chs' => 'CP936',
'cht' => 'CP950',
'cos' => 'CP1252',
'cre' => 'utf-8',
'csy' => 'CP1250',
'cym' => 'CP1252',
'dan' => 'CP1252',
'dea' => 'CP1252',
'dec' => 'CP1252',
'del' => 'CP1252',
'des' => 'CP1252',
'deu' => 'CP1252',
'div' => 'utf-8',
'dsb' => 'CP1252',
'ell' => 'CP1253',
'ena' => 'CP1252',
'enb' => 'CP1252',
'enc' => 'CP1252',
'ene' => 'CP1252',
'eng' => 'CP1252',
'enh' => 'CP1252',
'eni' => 'CP1252',
'enj' => 'CP1252',
'enl' => 'CP1252',
'enm' => 'CP1252',
'enn' => 'CP1252',
'enp' => 'CP1252',
'ens' => 'CP1252',
'ent' => 'CP1252',
'enu' => 'CP1252',
'enw' => 'CP1252',
'enz' => 'CP1252',
'esa' => 'CP1252',
'esb' => 'CP1252',
'esc' => 'CP1252',
'esd' => 'CP1252',
'ese' => 'CP1252',
'esf' => 'CP1252',
'esg' => 'CP1252',
'esh' => 'CP1252',
'esi' => 'CP1252',
'esj' => 'CP1252',
'esk' => 'CP1252',
'esl' => 'CP1252',
'esm' => 'CP1252',
'esn' => 'CP1252',
'eso' => 'CP1252',
'esp' => 'CP1252',
'esr' => 'CP1252',
'ess' => 'CP1252',
'est' => 'CP1252',
'esu' => 'CP1252',
'esv' => 'CP1252',
'esy' => 'CP1252',
'esz' => 'CP1252',
'euq' => 'CP1252',
'eti' => 'CP1257',
'far' => 'CP1256',
'fin' => 'CP1252',
'fos' => 'CP1252',
'fpo' => 'CP1252',
'fra' => 'CP1252',
'frb' => 'CP1252',
'frc' => 'CP1252',
'frd' => 'CP1252',
'fre' => 'CP1252',
'frf' => 'CP1252',
'frh' => 'CP1252',
'fri' => 'CP1252',
'frl' => 'CP1252',
'frm' => 'CP1252',
'frn' => 'CP1252',
'fro' => 'CP1252',
'frr' => 'CP1252',
'frs' => 'CP1252',
'ful' => 'CP1252',
'fyn' => 'CP1252',
'gla' => 'CP1252',
'glc' => 'CP1252',
'grn' => 'CP1252',
'gsw' => 'CP1252',
'guj' => 'utf-8',
'hau' => 'CP1252',
'haw' => 'CP1252',
'heb' => 'CP1255',
'hin' => 'utf-8',
'hrb' => 'CP1250',
'hrv' => 'CP1250',
'hsb' => 'CP1252',
'hun' => 'CP1250',
'hye' => 'utf-8',
'ibo' => 'CP1252',
'iii' => 'utf-8',
'ind' => 'CP1252',
'ire' => 'CP1252',
'isl' => 'CP1252',
'ita' => 'CP1252',
'its' => 'CP1252',
'ius' => 'utf-8',
'iuk' => 'CP1252',
'ivl' => 'CP1252', // Invariant Language_Invariant Country.1252
'jav' => 'CP1252',
'jpn' => 'CP932',
'kal' => 'CP1252',
'kat' => 'utf-8',
'kdi' => 'utf-8',
'khm' => 'utf-8',
'kin' => 'CP1252',
'kkz' => 'utf-8',
'knk' => 'utf-8',
'kor' => 'CP949',
'kur' => 'CP1256',
'kyr' => 'CP1251',
'lao' => 'utf-8',
'lbx' => 'CP1252',
'lth' => 'CP1257',
'lvi' => 'CP1257',
'mar' => 'utf-8',
'mki' => 'CP1251',
'mlg' => 'utf-8',
'mlt' => 'utf-8',
'mng' => 'utf-8',
'mnm' => 'utf-8',
'mnn' => 'CP1251',
'mon' => 'CP1251',
'mpd' => 'CP1252',
'mri' => 'utf-8',
'msb' => 'CP1252',
'msl' => 'CP1252',
'mwk' => 'CP1252',
'mya' => 'utf-8',
'mym' => 'utf-8',
'nei' => 'utf-8',
'nep' => 'utf-8',
'ngo' => 'utf-8',
'nlb' => 'CP1252',
'nld' => 'CP1252',
'non' => 'CP1252',
'nor' => 'CP1252',
'nso' => 'CP1252',
'oci' => 'CP1252',
'ori' => 'utf-8',
'orm' => 'utf-8',
'pan' => 'utf-8',
'pap' => 'CP1256',
'pas' => 'utf-8',
'plk' => 'CP1250',
'prs' => 'CP1256',
'pta' => 'CP1252',
'ptb' => 'CP1252',
'ptg' => 'CP1252',
'qub' => 'CP1252',
'que' => 'CP1252',
'qup' => 'CP1252',
'qut' => 'CP1252',
'rmc' => 'CP1252',
'rod' => 'CP1250',
'rom' => 'CP1250',
'rum' => 'CP1251',
'rus' => 'CP1251',
'sah' => 'CP1251',
'san' => 'utf-8',
'sin' => 'utf-8',
'sip' => 'CP1256',
'sky' => 'CP1250',
'slv' => 'CP1250',
'sma' => 'CP1252',
'smb' => 'CP1252',
'sme' => 'CP1252',
'smf' => 'CP1252',
'smg' => 'CP1252',
'smj' => 'CP1252',
'smk' => 'CP1252',
'smn' => 'CP1252',
'sms' => 'CP1252',
'sna' => 'utf-8',
'som' => 'utf-8',
'sot' => 'utf-8',
'sqi' => 'CP1250',
'srb' => 'CP1250',
'srl' => 'CP1250',
'srm' => 'CP1250',
'srn' => 'CP1251',
'sro' => 'CP1251',
'srp' => 'CP1250',
'srq' => 'CP1251',
'srs' => 'CP1250',
'sve' => 'CP1252',
'svf' => 'CP1252',
'swk' => 'CP1252',
'syr' => 'utf-8',
'tai' => 'utf-8',
'tam' => 'utf-8',
'taj' => 'CP1251',
'tel' => 'utf-8',
'tha' => 'CP874',
'tie' => 'utf-8',
'tir' => 'utf-8',
'trk' => 'CP1254',
'tsb' => 'CP1252',
'tsn' => 'CP1252',
'tso' => 'utf-8',
'ttt' => 'CP1251',
'tuk' => 'CP1250',
'tza' => 'CP1252',
'tzm' => 'utf-8',
'uig' => 'CP1256',
'ukr' => 'CP1251',
'urb' => 'CP1256',
'urd' => 'CP1256',
'uri' => 'CP1256',
'usa' => 'CP1252',
'uzb' => 'CP1254',
'uzc' => 'CP1251',
'val' => 'CP1252',
'vit' => 'CP1258',
'wol' => 'CP1252',
'xho' => 'CP1252',
'yor' => 'CP1252',
'zhg' => 'utf-8',
'zhh' => 'CP950',
'zhi' => 'CP936',
'zhm' => 'CP950',
'zul' => 'CP1252',
'zzz' => 'utf-8'
);
// IBM AIX locale to code set table
// See http://publibn.boulder.ibm.com/doc_link/en_US/a_doc_lib/libs/basetrf2/setlocale.htm
private static $aixlocale_codepage_map = array(
'Ar_AA' => 'IBM-1046',
'ar_AA' => 'ISO8859-6',
'bg_BG' => 'ISO8856-5',
'cs_CZ' => 'ISO8859-2',
'Da_DK' => 'IBM-850',
'da_DK' => 'ISO8859-1',
'De_CH' => 'IBM-850',
'de_CH' => 'ISO8859-1',
'De_DE' => 'IBM-850',
'de_DE' => 'ISO8859-1',
'el_GR' => 'ISO8859-7',
'En_GB' => 'IBM-850',
'en_GB' => 'ISO8859-1',
'En_US' => 'IBM-850',
'en_US' => 'ISO8859-1',
'Es_ES' => 'IBM-850',
'es_ES' => 'ISO8859-1',
'Fi_FI' => 'IBM-850',
'fi_FI' => 'ISO8859-1',
'Fr_BE' => 'IBM-850',
'fr_BE' => 'ISO8859-1',
'Fr_CA' => 'IBM-850',
'fr_CA' => 'ISO8859-1',
'Fr_FR' => 'IBM-850',
'fr_FR' => 'ISO8859-1 ',
'Fr_CH' => 'IBM-850',
'fr_CH' => 'ISO8859-1',
'hr_HR' => 'ISO8859-2',
'hu_HU' => 'ISO8859-2',
'Is_IS' => 'IBM-850',
'is_IS' => 'ISO8859-1',
'It_IT' => 'IBM-850',
'it_IT' => 'ISO8859-1',
'Iw_IL' => 'IBM-856',
'iw_IL' => 'ISO8859-8',
'Ja_JP' => 'IBM-943',
'ko_KR' => 'IBM-eucKR',
'mk_MK' => 'ISO8859-5',
'Nl_BE' => 'IBM-850',
'nl_BE' => 'ISO8859-1',
'Nl_NL' => 'IBM-850',
'nl_NL' => 'ISO8859-1',
'No_NO' => 'IBM-850',
'no_NO' => 'ISO8859-1',
'pl_PL' => 'ISO8859-2',
'Pt_PT' => 'IBM-850',
'pt_PT' => 'ISO8859-1',
'ro_RO' => 'ISO8859-2',
'ru_RU' => 'ISO8859-5',
'sh_SP' => 'ISO8859-2',
'sl_SI' => 'ISO8859-2',
'sk_SK' => 'ISO8859-2',
'sr_SP' => 'ISO8859-5',
'Zh_CN' => 'GBK',
'Sv_SE' => 'IBM-850',
'sv_SE' => 'ISO8859-1',
'tr_TR' => 'ISO8859-9',
'zh_TW' => 'IBM-eucTW'
);
// IBM AIX libiconv UTF-8 converters
// See http://publibn.boulder.ibm.com/doc_link/en_US/a_doc_lib/aixprggd/genprogc/convert_prg.htm#HDRDNNRI49HOWA
private static $aix_utf8_converters = array(
'ISO8859-1',
'ISO8859-2',
'ISO8859-3',
'ISO8859-4',
'ISO8859-5',
'ISO8859-6',
'ISO8859-7',
'ISO8859-8',
'ISO8859-9',
'JISX0201.1976-0',
'JISX0208.1983-0',
'CNS11643.1986-1',
'CNS11643.1986-2',
'KSC5601.1987-0',
'IBM-eucCN',
'IBM-eucJP',
'IBM-eucKR',
'IBM-eucTW',
'IBM-udcJP',
'IBM-udcTW',
'IBM-sbdTW',
'UCS-2',
'IBM-437',
'IBM-850',
'IBM-852',
'IBM-857',
'IBM-860',
'IBM-861',
'IBM-863',
'IBM-865',
'IBM-869',
'IBM-921',
'IBM-922',
'IBM-932',
'IBM-943',
'IBM-934',
'IBM-935',
'IBM-936',
'IBM-938',
'IBM-942',
'IBM-944',
'IBM-946',
'IBM-948',
'IBM-1124',
'IBM-1129',
'TIS-620',
'IBM-037',
'IBM-273',
'IBM-277',
'IBM-278',
'IBM-280',
'IBM-284',
'IBM-285',
'IBM-297',
'IBM-500',
'IBM-875',
'IBM-930',
'IBM-933',
'IBM-937',
'IBM-939',
'IBM-1026',
'IBM-1112',
'IBM-1122',
'IBM-1124',
'IBM-1129',
'IBM-1381',
'GBK',
'TIS-620'
);
// GNU iconv code set to IBM AIX libiconv code set table
// Keys of this table should be in lowercase, and searches should be performed using lowercase!
private static $gnu_iconv_to_aix_iconv_codepage_map = array(
// "iso-8859-[1-9]" --> "ISO8859-[1-9]" according to http://publibn.boulder.ibm.com/doc_link/en_US/a_doc_lib/libs/basetrf2/setlocale.htm
'iso-8859-1' => 'ISO8859-1',
'iso-8859-2' => 'ISO8859-2',
'iso-8859-3' => 'ISO8859-3',
'iso-8859-4' => 'ISO8859-4',
'iso-8859-5' => 'ISO8859-5',
'iso-8859-6' => 'ISO8859-6',
'iso-8859-7' => 'ISO8859-7',
'iso-8859-8' => 'ISO8859-8',
'iso-8859-9' => 'ISO8859-9',
// "big5" --> "IBM-eucTW" according to http://kadesh.cepba.upc.es/mancpp/classref/ref/ITranscoder_DSC.htm
'big5' => 'IBM-eucTW',
// "big-5" --> "IBM-eucTW" (see above)
'big-5' => 'IBM-eucTW'
);
// Works out whether the machine architecture is little-endian or big-endian
public static function getEndianness() : int
{
static $result;
if (!isset($result))
{
$testint = 0x00FF;
$p = pack('S', $testint);
$result = ($testint===current(unpack('v', $p))) ? self::LITTLE_ENDIAN : self::BIG_ENDIAN;
}
return $result;
}
public static function getServerOS() : string
{
static $server_os = null;
if (!isset($server_os))
{
if (stristr(PHP_OS,'Darwin'))
{
$server_os = 'macosx';
}
elseif (stristr(PHP_OS, 'WIN'))
{
$server_os = 'windows';
}
elseif (stristr(PHP_OS, 'Linux'))
{
$server_os = 'linux';
}
elseif (stristr(PHP_OS, 'BSD'))
{
$server_os = 'bsd';
}
elseif (stristr(PHP_OS, 'SunOS'))
{
$server_os = 'sunos';
}
elseif (stristr(PHP_OS, 'AIX'))
{
$server_os = 'aix';
}
else
{
$server_os = 'unsupported';
}
}
return $server_os;
}
// Returns information about the operating system PHP is running on
public static function info() : string
{
// On some systems php_uname() is disabled for security reasons
if (in_array('php_uname', explode(',', ini_get('disable_functions'))))
{
return PHP_OS;
}
return php_uname();
}
/**
* Checks whether a language tag is advertised as being available on this system.
*
* Note that this method just tells us which locales are supported by the 'intl' extension. It
* doesn't tell us which locales are supported by setlocale(), which uses a different library.
*
* @return bool|null NULL if the advertised locales aren't known, otherwise TRUE/FALSE.
*/
private static function isAdvertisedLocale(string $langtag) : ?bool
{
if (!class_exists('\\ResourceBundle'))
{
// Could try using locale -a but that requires exec() which is not
// available on most systems.
// Could also use IntlCalendar::getAvailableLocales(), but that needs
// the intl extension, just like ResourceBundle::getLocales().
return null;
}
// Get the available locales
$locales = ResourceBundle::getLocales('');
// Put our locale into PHP's format
$locale = Locale::composeLocale(Locale::parseLocale($langtag));
// See whether our locale exists.
return in_array($locale, $locales);
}
/**
* Checks whether a language tag is available on this system.
*
* WARNING! This method is not reliable on Windows. It may return TRUE even if the locale is not
* available on the system.
*
* @param string $langtag A language tag in BCP 47 format.
*/
public static function isAvailableLocale(string $langtag) : bool
{
// If the OS is able to tell us whether the locale is supported, then
// use that answer.
if (null !== ($result = self::isAdvertisedLocale($langtag)))
{
return $result;
}
// Otherwise try setting the locale
return self::testLocale($langtag);
}
// Add a codeset suffix to $locale
private static function addCodeset(string $locale) : string
{
$server_os = self::getServerOS();
switch ($server_os)
{
case 'sunos':
case 'linux':
case 'bsd':
$codeset = '.UTF-8';
break;
case 'macosx':
case 'windows':
$codeset = '.utf-8';
break;
default:
$codeset = '';
break;
}
return $locale . $codeset;
}
/**
* Returns an array of locales in the correct format for the server OS given a BCP 47 language tag.
*
* There is an array of locales to try because some operating systems and versions accept locales
* with underscores, some with hyphens and some as special codes.
*
* @param string $langtag A BCP 47 language tag.
* @return string[]
*/
public static function getOSlocale(string $langtag) : array
{
static $locales = [];
if (!isset($locales[$langtag]))
{
$locales[$langtag] = self::getLocaleAlternatives($langtag);
// Add on a codeset [is this still necessary??]
$locales[$langtag] = array_map(self::class . '::addCodeset', $locales[$langtag]);;
}
return $locales[$langtag];
}
/**
* The inverse of getOSlocale(). Turns an OS-specific locale into a BCP 47 style language tag.
*
* This is provided for backwards compatibility with old versions of MRBS where the $override_locale
* config setting was required to be operating-system-specific (eg 'en_GB.utf-8' on Unix systems or
* 'eng' on Windows). Now $override_locale should be in BCP 47 format, but we accept old-style settings.
*/
public static function getBCPlocale(string $locale) : string
{
$result = $locale;
// Strip anything like '.utf-8' off the end
if (mb_strpos($result, '.') !== false)
{
$result = strstr($locale, '.', true);
}
// Convert an old-style Windows locale, eg 'eng' to a BCP 47 one, eg 'en-gb'
if ((self::getServerOS() == 'windows') && in_array($result, self::$lang_map_windows))
{
$result = array_search($result, self::$lang_map_windows);
}
// Parse it and then recompose it. This will get the capitalisation correct, eg
// "sr-Latn-RS". Note, though, that BCP 47 language tags are case-insensitive and
// the capitalisation is just a convention.
$result = Locale::composeLocale(Locale::parseLocale($result));
// Convert underscores to hyphens. Locale::composeLocale() returns underscores.
$result = str_replace('_', '-', $result);
return $result;
}
public static function utf8ConvertFromLocale(string $string, ?string $locale=null) : string
{
$server_os = self::getServerOS();
if ($server_os == 'windows')
{
if (!isset($locale))
{
$locale = Language::getInstance()->getWebLocale();
}
$locale = mb_strtolower($locale);
if (isset(self::$lang_map_windows[$locale]) &&
array_key_exists(self::$lang_map_windows[$locale], self::$winlocale_codepage_map))
{
$from_encoding = self::$winlocale_codepage_map[self::$lang_map_windows[$locale]];
$to_encoding = 'utf-8';
$string = iconv($from_encoding, $to_encoding, $string);
if ($string === false)
{
$message = "iconv() failed converting from '$from_encoding' to '$to_encoding'";
throw new Exception($message);
}
}
}
else if ($server_os == 'aix')
{
$string = self::utf8ConvertAix($string, $locale);
}
return $string;
}
private static function getLocaleAlternatives(string $langtag) : array
{
$locales = array();
// Put the $langtag into standard PHP format
$subtags = Locale::parseLocale($langtag);
if (!empty($subtags))
{
$locale = Locale::composeLocale($subtags);
// The first locale to try is one with hyphens instead of underscores. These work on newer
// Windows systems, whereas underscores do not. Also, on Windows systems, although
// setlocale will succeed with, for example, both 'en_GB' and 'en-GB', only 'en-GB' (and
// indeed 'eng') will give the date in the correct format when using strftime('%x').
$locales[] = str_replace('_', '-', $locale);
// The next locale to try is a PHP style locale, ie with underscores.
// Make sure we haven't already got it
if (!in_array($locale, $locales))
{
$locales[] = $locale;
}
if (self::getServerOS() == 'windows')
{
// Add in the three-letter code if any as a last resort
if (isset(self::$lang_map_windows[mb_strtolower($langtag)]))
{
$locales[] = self::$lang_map_windows[mb_strtolower($langtag)];
}
}
// If there isn't a region specified then add one, because on some systems
// setlocale(LC_ALL, 'en'), for example, doesn't work, even though 'en' seems
// to be an available locale.
if (!isset($subtags['region']))
{
$subtags['region'] = self::getDefaultRegion($subtags['language']);
if (isset($subtags['region'])) // avoid an infinite recursion
{
$locales = array_merge($locales, self::getLocaleAlternatives(Locale::composeLocale($subtags)));
}
}
// Finally, if there's a script subtag, then add a locale with the script removed. For example,
// setlocale() will usually fail with 'zh-Hant-TW' but succeed with 'zh-TW'.
if (isset($subtags['script']))
{
unset($subtags['script']);
$locales = array_merge($locales, self::getLocaleAlternatives(Locale::composeLocale($subtags)));
}
}
return $locales;
}
/**
* Returns the default region for a language.
*/
private static function getDefaultRegion(string $language) : string
{
if (isset(self::$default_regions[$language]))
{
return self::$default_regions[$language];
}
return mb_strtoupper($language);
}
// AIX version of utf8_convert(); needed as locales won't give us UTF-8
// NOTE: Should ONLY be called with input encoded in the default code set of the current locale!
// NOTE: Uses the LC_TIME category for determining the current locale setting, so should preferably be used on date/time input only!
private static function utf8ConvertAix(string $string, ?string $aix_locale=null) : string
{
if (!isset($aix_locale))
{
// Retrieve current locale setting
$aix_locale = setlocale(LC_TIME, '0');
}
if ($aix_locale === false)
{
// Locale setting could not be retrieved; return string unchanged
return $string;
}
if (!array_key_exists($aix_locale, self::$aixlocale_codepage_map))
{
// The default code page of locale could not be found; return string unchanged
return $string;
}
$aix_codepage = self::$aixlocale_codepage_map[$aix_locale];
if (!in_array($aix_codepage, self::$aix_utf8_converters, true))
{
// No suitable UTF-8 converter was found for this code page; return string unchanged
return $string;
}
// Convert string to UTF-8
$from_encoding = $aix_codepage;
$to_encoding = 'UTF-8';
$string = iconv($from_encoding, $to_encoding, $string);
if ($string === false)
{
$message = "iconv() failed converting from '$from_encoding' to '$to_encoding'";
throw new Exception($message);
}
return $string;
}
// Translates a GNU libiconv character encoding name to its corresponding IBM AIX libiconv character
// encoding name. Returns FALSE if character encoding name is unknown.
private static function getAixCharacterEncoding(?string $character_encoding)
{
// Check arguments
if ($character_encoding == null ||
!is_string($character_encoding) ||
empty($character_encoding))
{
return false;
}
// Convert character encoding name to lowercase
$character_encoding = mb_strtolower($character_encoding);
// Check that we know of an IBM AIX libiconv character encoding name equivalent for this character encoding name
if (!array_key_exists($character_encoding, self::$gnu_iconv_to_aix_iconv_codepage_map))
{
return false;
}
return self::$gnu_iconv_to_aix_iconv_codepage_map[$character_encoding];
}
/**
* Tests whether a language tag can be set on this system. Preserves the current locale.
*
* WARNING! This method is unreliable on Windows systems where setlocale(LC_ALL, 'xyz.utf-8')
* will return 'xyz.utf-8', even though the locale doesn't exist.
*/
private static function testLocale(string $langtag) : bool
{
// TODO: Do something better for Windows systems? Could check whether the locale exists in
// TODO: a known list of locales. However, it's probably not worth it because (a) we will
// TODO: only ever use this method with locales that are supported by other MRBS components,
// TODO: and (b) we will eventually move to using the intl extension anyway.
// Save the original locales so that we can restore them later. Note that
// there could be different locales for different categories
$original_locales = explode(';', setlocale(LC_ALL, '0'));
// Try the test locale
$result = Language::setLocale(LC_ALL, $langtag);
// Restore the original settings
foreach ($original_locales as $locale_setting)
{
if (mb_strpos($locale_setting, '=') !== false)
{
list($category, $locale) = explode('=', $locale_setting);
// Need to turn the string back into a constant (sometimes PHP doesn't recognise a LC_ constant,
// so check that it has been defined first before turning it into a constant).
$category = (defined($category)) ? constant($category) : null;
}
else
{
$category = LC_ALL;
$locale = $locale_setting;
}
if (isset($category))
{
setlocale($category, $locale);
}
}
return ($result !== false);
}
}