i18n.php 34 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991
  1. <?php
  2. /**
  3. * SquirrelMail internationalization functions
  4. *
  5. * Copyright (c) 1999-2004 The SquirrelMail Project Team
  6. * Licensed under the GNU GPL. For full terms see the file COPYING.
  7. *
  8. * This file contains variuos functions that are needed to do
  9. * internationalization of SquirrelMail.
  10. *
  11. * Internally the output character set is used. Other characters are
  12. * encoded using Unicode entities according to HTML 4.0.
  13. *
  14. * @version $Id$
  15. * @package squirrelmail
  16. * @subpackage i18n
  17. */
  18. /** Everything uses global.php... */
  19. require_once(SM_PATH . 'functions/global.php');
  20. /**
  21. * Converts string from given charset to charset, that can be displayed by user translation.
  22. *
  23. * Function by default returns html encoded strings, if translation uses different encoding.
  24. * If Japanese translation is used - function returns string converted to euc-jp
  25. * If iconv or recode functions are enabled and translation uses utf-8 - function returns utf-8 encoded string.
  26. * If $charset is not supported - function returns unconverted string.
  27. *
  28. * sanitizing of html tags is also done by this function.
  29. *
  30. * @param string $charset
  31. * @param string $string Text to be decoded
  32. * @return string decoded string
  33. */
  34. function charset_decode ($charset, $string) {
  35. global $languages, $squirrelmail_language, $default_charset;
  36. global $use_php_recode, $use_php_iconv, $agresive_decoding;
  37. if (isset($languages[$squirrelmail_language]['XTRA_CODE']) &&
  38. function_exists($languages[$squirrelmail_language]['XTRA_CODE'])) {
  39. $string = $languages[$squirrelmail_language]['XTRA_CODE']('decode', $string);
  40. }
  41. $charset = strtolower($charset);
  42. set_my_charset();
  43. // Variables that allow to use functions without function_exist() calls
  44. if (! isset($use_php_recode) || $use_php_recode=="" ) {
  45. $use_php_recode=false; }
  46. if (! isset($use_php_iconv) || $use_php_iconv=="" ) {
  47. $use_php_iconv=false; }
  48. // Don't do conversion if charset is the same.
  49. if ( $charset == strtolower($default_charset) )
  50. return htmlspecialchars($string);
  51. // catch iso-8859-8-i thing
  52. if ( $charset == "iso-8859-8-i" )
  53. $charset = "iso-8859-8";
  54. /*
  55. * Recode converts html special characters automatically if you use
  56. * 'charset..html' decoding. There is no documented way to put -d option
  57. * into php recode function call.
  58. */
  59. if ( $use_php_recode ) {
  60. if ( $default_charset == "utf-8" ) {
  61. // other charsets can be converted to utf-8 without loss.
  62. // and output string is smaller
  63. $string = recode_string($charset . "..utf-8",$string);
  64. return htmlspecialchars($string);
  65. } else {
  66. $string = recode_string($charset . "..html",$string);
  67. // recode does not convert single quote, htmlspecialchars does.
  68. $string = str_replace("'", '&#039;', $string);
  69. return $string;
  70. }
  71. }
  72. // iconv functions does not have html target and can be used only with utf-8
  73. if ( $use_php_iconv && $default_charset=='utf-8') {
  74. $string = iconv($charset,$default_charset,$string);
  75. return htmlspecialchars($string);
  76. }
  77. // If we don't use recode and iconv, we'll do it old way.
  78. /* All HTML special characters are 7 bit and can be replaced first */
  79. $string = htmlspecialchars ($string);
  80. /* controls cpu and memory intensive decoding cycles */
  81. if (! isset($agresive_decoding) || $agresive_decoding=="" ) {
  82. $agresive_decoding=false; }
  83. $decode=fixcharset($charset);
  84. $decodefile=SM_PATH . 'functions/decode/' . $decode . '.php';
  85. if (file_exists($decodefile)) {
  86. include_once($decodefile);
  87. $ret = call_user_func('charset_decode_'.$decode, $string);
  88. } else {
  89. $ret = $string;
  90. }
  91. return( $ret );
  92. }
  93. /**
  94. * Converts html string to given charset
  95. * @param string $string
  96. * @param string $charset
  97. * @param boolean $htmlencode keep htmlspecialchars encoding
  98. * @param string
  99. */
  100. function charset_encode($string,$charset,$htmlencode=true) {
  101. global $default_charset;
  102. // Undo html special chars
  103. if (! $htmlencode ) {
  104. $string = str_replace(array('&amp;','&gt;','&lt;','&quot;'),array('&','>','<','"'),$string);
  105. }
  106. $encode=fixcharset($charset);
  107. $encodefile=SM_PATH . 'functions/encode/' . $encode . '.php';
  108. if (file_exists($encodefile)) {
  109. include_once($encodefile);
  110. $ret = call_user_func('charset_encode_'.$encode, $string);
  111. } else {
  112. $ret = $string;
  113. }
  114. return( $ret );
  115. }
  116. /**
  117. * Combined decoding and encoding functions
  118. *
  119. * If conversion is done to charset different that utf-8, unsupported symbols
  120. * will be replaced with question marks.
  121. * @param string $in_charset initial charset
  122. * @param string $string string that has to be converted
  123. * @param string $out_charset final charset
  124. * @param boolean $htmlencode keep htmlspecialchars encoding
  125. * @return string converted string
  126. */
  127. function charset_convert($in_charset,$string,$out_charset,$htmlencode=true) {
  128. $string=charset_decode($in_charset,$string);
  129. $string=charset_encode($string,$out_charset,$htmlencode);
  130. return $string;
  131. }
  132. /**
  133. * Makes charset name suitable for decoding cycles
  134. *
  135. * @param string $charset Name of charset
  136. * @return string $charset Adjusted name of charset
  137. */
  138. function fixcharset($charset) {
  139. // minus removed from function names
  140. $charset=str_replace('-','_',$charset);
  141. // windows-125x and cp125x charsets
  142. $charset=str_replace('windows_','cp',$charset);
  143. // ibm > cp
  144. $charset=str_replace('ibm','cp',$charset);
  145. // iso-8859-8-i -> iso-8859-8
  146. // use same cycle until I'll find differences
  147. $charset=str_replace('iso_8859_8_i','iso_8859_8',$charset);
  148. return $charset;
  149. }
  150. /**
  151. * Set up the language to be output
  152. * if $do_search is true, then scan the browser information
  153. * for a possible language that we know
  154. *
  155. * Function sets system locale environment (LC_ALL, LANG, LANGUAGE),
  156. * gettext translation bindings and html header information.
  157. *
  158. * Function returns error codes, if there is some fatal error.
  159. * 0 = no error,
  160. * 1 = mbstring support is not present,
  161. * 2 = mbstring support is not present, user's translation reverted to en_US.
  162. *
  163. * @param string $sm_language translation used by user's interface
  164. * @param bool $do_search use browser's preferred language detection functions. Defaults to false.
  165. * @param bool $default set $sm_language to $squirrelmail_default_language if language detection fails or language is not set. Defaults to false.
  166. * @return int function execution error codes.
  167. */
  168. function set_up_language($sm_language, $do_search = false, $default = false) {
  169. static $SetupAlready = 0;
  170. global $use_gettext, $languages,
  171. $squirrelmail_language, $squirrelmail_default_language,
  172. $sm_notAlias, $username, $data_dir;
  173. if ($SetupAlready) {
  174. return;
  175. }
  176. $SetupAlready = TRUE;
  177. sqgetGlobalVar('HTTP_ACCEPT_LANGUAGE', $accept_lang, SQ_SERVER);
  178. if ($do_search && ! $sm_language && isset($accept_lang)) {
  179. $sm_language = substr($accept_lang, 0, 2);
  180. }
  181. if ((!$sm_language||$default) && isset($squirrelmail_default_language)) {
  182. $squirrelmail_language = $squirrelmail_default_language;
  183. $sm_language = $squirrelmail_default_language;
  184. }
  185. $sm_notAlias = $sm_language;
  186. // Catching removed translation
  187. // System reverts to English translation if user prefs contain translation
  188. // that is not available in $languages array
  189. if (!isset($languages[$sm_notAlias])) {
  190. $sm_notAlias="en_US";
  191. }
  192. while (isset($languages[$sm_notAlias]['ALIAS'])) {
  193. $sm_notAlias = $languages[$sm_notAlias]['ALIAS'];
  194. }
  195. if ( isset($sm_language) &&
  196. $use_gettext &&
  197. $sm_language != '' &&
  198. isset($languages[$sm_notAlias]['CHARSET']) ) {
  199. bindtextdomain( 'squirrelmail', SM_PATH . 'locale/' );
  200. textdomain( 'squirrelmail' );
  201. if (function_exists('bind_textdomain_codeset')) {
  202. if ($sm_notAlias == 'ja_JP') {
  203. bind_textdomain_codeset ("squirrelmail", 'EUC-JP');
  204. } else {
  205. bind_textdomain_codeset ("squirrelmail", $languages[$sm_notAlias]['CHARSET'] );
  206. }
  207. }
  208. if (isset($languages[$sm_notAlias]['LOCALE'])){
  209. $longlocale=$languages[$sm_notAlias]['LOCALE'];
  210. } else {
  211. $longlocale=$sm_notAlias;
  212. }
  213. if ( !ini_get('safe_mode') &&
  214. getenv( 'LC_ALL' ) != $longlocale ) {
  215. putenv( "LC_ALL=$longlocale" );
  216. putenv( "LANG=$longlocale" );
  217. putenv( "LANGUAGE=$longlocale" );
  218. }
  219. setlocale(LC_ALL, $longlocale);
  220. // Set text direction/alignment variables
  221. if (isset($languages[$sm_notAlias]['DIR']) &&
  222. $languages[$sm_notAlias]['DIR'] == 'rtl') {
  223. /**
  224. * Text direction
  225. * @global string $text_direction
  226. */
  227. $text_direction='rtl';
  228. /**
  229. * Left alignment
  230. * @global string $left_align
  231. */
  232. $left_align='right';
  233. /**
  234. * Right alignment
  235. * @global string $right_align
  236. */
  237. $right_align='left';
  238. } else {
  239. $text_direction='ltr';
  240. $left_align='left';
  241. $right_align='right';
  242. }
  243. $squirrelmail_language = $sm_notAlias;
  244. if ($squirrelmail_language == 'ja_JP') {
  245. header ('Content-Type: text/html; charset=EUC-JP');
  246. if (!function_exists('mb_internal_encoding')) {
  247. // Error messages can't be displayed here
  248. $error = 1;
  249. // Revert to English if possible.
  250. if (function_exists('setPref') && $username!='' && $data_dir!="") {
  251. setPref($data_dir, $username, 'language', "en_US");
  252. $error = 2;
  253. }
  254. // stop further execution in order not to get php errors on mb_internal_encoding().
  255. return $error;
  256. }
  257. if (function_exists('mb_language')) {
  258. mb_language('Japanese');
  259. }
  260. mb_internal_encoding('EUC-JP');
  261. mb_http_output('pass');
  262. } else {
  263. header( 'Content-Type: text/html; charset=' . $languages[$sm_notAlias]['CHARSET'] );
  264. }
  265. }
  266. return 0;
  267. }
  268. /**
  269. * Sets default_charset variable according to the one that is used by user's translations.
  270. *
  271. * Function changes global $default_charset variable in order to be sure, that it
  272. * contains charset used by user's translation. Sanity of $squirrelmail_default_language
  273. * and $default_charset combination provided in SquirrelMail config is also tested.
  274. *
  275. * There can be a $default_charset setting in the
  276. * config.php file, but the user may have a different language
  277. * selected for a user interface. This function checks the
  278. * language selected by the user and tags the outgoing messages
  279. * with the appropriate charset corresponding to the language
  280. * selection. This is "more right" (tm), than just stamping the
  281. * message blindly with the system-wide $default_charset.
  282. */
  283. function set_my_charset(){
  284. global $data_dir, $username, $default_charset, $languages, $squirrelmail_default_language;
  285. $my_language = getPref($data_dir, $username, 'language');
  286. if (!$my_language) {
  287. $my_language = $squirrelmail_default_language ;
  288. }
  289. // Catch removed translation
  290. if (!isset($languages[$my_language])) {
  291. $my_language="en_US";
  292. }
  293. while (isset($languages[$my_language]['ALIAS'])) {
  294. $my_language = $languages[$my_language]['ALIAS'];
  295. }
  296. $my_charset = $languages[$my_language]['CHARSET'];
  297. if ($my_charset) {
  298. $default_charset = $my_charset;
  299. }
  300. }
  301. /* ------------------------------ main --------------------------- */
  302. global $squirrelmail_language, $languages, $use_gettext;
  303. if (! isset($squirrelmail_language)) {
  304. $squirrelmail_language = '';
  305. }
  306. /**
  307. * Array specifies the available translations.
  308. *
  309. * Structure of array:
  310. * $languages['language']['variable'] = 'value'
  311. *
  312. * Possible 'variable' names:
  313. * NAME - Translation name in English
  314. * CHARSET - Encoding used by translation
  315. * ALIAS - used when 'language' is only short name and 'value' should provide long language name
  316. * ALTNAME - Native translation name. Any 8bit symbols must be html encoded.
  317. * LOCALE - Full locale name (in xx_XX.charset format)
  318. * DIR - Text direction. Used to define Right-to-Left languages. Possible values 'rtl' or 'ltr'. If undefined - defaults to 'ltr'
  319. * XTRA_CODE - translation uses special functions. 'value' provides name of that extra function
  320. *
  321. * Each 'language' definition requires NAME+CHARSET or ALIAS variables.
  322. *
  323. * @name $languages
  324. * @global array $languages
  325. */
  326. $languages['bg_BG']['NAME'] = 'Bulgarian';
  327. $languages['bg_BG']['ALTNAME'] = '&#1041;&#1098;&#1083;&#1075;&#1072;&#1088;&#1089;&#1082;&#1080;';
  328. $languages['bg_BG']['CHARSET'] = 'windows-1251';
  329. $languages['bg_BG']['LOCALE'] = 'bg_BG.CP1251';
  330. $languages['bg']['ALIAS'] = 'bg_BG';
  331. $languages['ca_ES']['NAME'] = 'Catalan';
  332. $languages['ca_ES']['CHARSET'] = 'iso-8859-1';
  333. $languages['ca_ES']['LOCALE'] = 'ca_ES.ISO8859-1';
  334. $languages['ca']['ALIAS'] = 'ca_ES';
  335. $languages['cs_CZ']['NAME'] = 'Czech';
  336. $languages['cs_CZ']['ALTNAME'] = '&#268;e&scaron;tina';
  337. $languages['cs_CZ']['CHARSET'] = 'iso-8859-2';
  338. $languages['cs_CZ']['LOCALE'] = 'cs_CZ.ISO8859-2';
  339. $languages['cs']['ALIAS'] = 'cs_CZ';
  340. $languages['cy_GB']['NAME'] = 'Welsh';
  341. $languages['cy_GB']['ALTNAME'] = 'Cymraeg';
  342. $languages['cy_GB']['CHARSET'] = 'iso-8859-1';
  343. $languages['cy_GB']['LOCALE'] = 'cy_GB.ISO8859-1';
  344. $languages['cy']['ALIAS'] = 'cy_GB';
  345. // Danish locale is da_DK.
  346. $languages['da_DK']['NAME'] = 'Danish';
  347. $languages['da_DK']['ALTNAME'] = 'Dansk';
  348. $languages['da_DK']['CHARSET'] = 'iso-8859-1';
  349. $languages['da_DK']['LOCALE'] = 'da_DK.ISO8859-1';
  350. $languages['da']['ALIAS'] = 'da_DK';
  351. $languages['de_DE']['NAME'] = 'German';
  352. $languages['de_DE']['ALTNAME'] = 'Deutsch';
  353. $languages['de_DE']['CHARSET'] = 'iso-8859-1';
  354. $languages['de_DE']['LOCALE'] = 'de_DE.ISO8859-1';
  355. $languages['de']['ALIAS'] = 'de_DE';
  356. $languages['el_GR']['NAME'] = 'Greek';
  357. $languages['el_GR']['ALTNAME'] = '&Epsilon;&lambda;&lambda;&eta;&nu;&iota;&kappa;&#940;';
  358. $languages['el_GR']['CHARSET'] = 'iso-8859-7';
  359. $languages['el_GR']['LOCALE'] = 'el_GR.ISO8859-7';
  360. $languages['el']['ALIAS'] = 'el_GR';
  361. $languages['en_GB']['NAME'] = 'British';
  362. $languages['en_GB']['CHARSET'] = 'iso-8859-15';
  363. $languages['en_GB']['LOCALE'] = 'en_GB.ISO8859-15';
  364. $languages['en_US']['NAME'] = 'English';
  365. $languages['en_US']['CHARSET'] = 'iso-8859-1';
  366. $languages['en_US']['LOCALE'] = 'en_US.ISO8859-1';
  367. $languages['en']['ALIAS'] = 'en_US';
  368. $languages['es_ES']['NAME'] = 'Spanish';
  369. $languages['es_ES']['ALTNAME'] = 'Espa&ntilde;ol';
  370. $languages['es_ES']['CHARSET'] = 'iso-8859-1';
  371. $languages['es_ES']['LOCALE'] = 'es_ES.ISO8859-1';
  372. $languages['es']['ALIAS'] = 'es_ES';
  373. $languages['et_EE']['NAME'] = 'Estonian';
  374. $languages['et_EE']['CHARSET'] = 'iso-8859-15';
  375. $languages['et_EE']['LOCALE'] = 'et_EE.ISO8859-15';
  376. $languages['et']['ALIAS'] = 'et_EE';
  377. $languages['eu_ES']['NAME'] = 'Basque';
  378. $languages['eu_ES']['CHARSET'] = 'iso-8859-1';
  379. $languages['eu_ES']['LOCALE'] = 'eu_ES.ISO8859-1';
  380. $languages['eu']['ALIAS'] = 'eu_ES';
  381. $languages['fo_FO']['NAME'] = 'Faroese';
  382. $languages['fo_FO']['CHARSET'] = 'iso-8859-1';
  383. $languages['fo_FO']['LOCALE'] = 'fo_FO.ISO8859-1';
  384. $languages['fo']['ALIAS'] = 'fo_FO';
  385. $languages['fi_FI']['NAME'] = 'Finnish';
  386. $languages['fi_FI']['ALTNAME'] = 'Suomi';
  387. $languages['fi_FI']['CHARSET'] = 'iso-8859-1';
  388. $languages['fi_FI']['LOCALE'] = 'fi_FI.ISO8859-1';
  389. $languages['fi']['ALIAS'] = 'fi_FI';
  390. $languages['fr_FR']['NAME'] = 'French';
  391. $languages['fr_FR']['ALTNAME'] = 'Fran&#231;ais';
  392. $languages['fr_FR']['CHARSET'] = 'iso-8859-1';
  393. $languages['fr_FR']['LOCALE'] = 'fr_FR.ISO8859-1';
  394. $languages['fr']['ALIAS'] = 'fr_FR';
  395. $languages['hr_HR']['NAME'] = 'Croatian';
  396. $languages['hr_HR']['CHARSET'] = 'iso-8859-2';
  397. $languages['hr_HR']['LOCALE'] = 'hr_HR.ISO8859-2';
  398. $languages['hr']['ALIAS'] = 'hr_HR';
  399. $languages['hu_HU']['NAME'] = 'Hungarian';
  400. $languages['hu_HU']['ALTNAME'] = 'Magyar';
  401. $languages['hu_HU']['CHARSET'] = 'iso-8859-2';
  402. $languages['hu_HU']['LOCALE'] = 'hu_HU.ISO8859-2';
  403. $languages['hu']['ALIAS'] = 'hu_HU';
  404. $languages['id_ID']['NAME'] = 'Indonesian';
  405. $languages['id_ID']['ALTNAME'] = 'Bahasa Indonesia';
  406. $languages['id_ID']['CHARSET'] = 'iso-8859-1';
  407. $languages['id_ID']['LOCALE'] = 'id_ID.ISO8859-1';
  408. $languages['id']['ALIAS'] = 'id_ID';
  409. $languages['is_IS']['NAME'] = 'Icelandic';
  410. $languages['is_IS']['ALTNAME'] = '&Iacute;slenska';
  411. $languages['is_IS']['CHARSET'] = 'iso-8859-1';
  412. $languages['is_IS']['LOCALE'] = 'is_IS.ISO8859-1';
  413. $languages['is']['ALIAS'] = 'is_IS';
  414. $languages['it_IT']['NAME'] = 'Italian';
  415. $languages['it_IT']['CHARSET'] = 'iso-8859-1';
  416. $languages['it_IT']['LOCALE'] = 'it_IT.ISO8859-1';
  417. $languages['it']['ALIAS'] = 'it_IT';
  418. $languages['ja_JP']['NAME'] = 'Japanese';
  419. $languages['ja_JP']['ALTNAME'] = '&#26085;&#26412;&#35486;';
  420. $languages['ja_JP']['CHARSET'] = 'iso-2022-jp';
  421. $languages['ja_JP']['LOCALE'] = 'ja_JP.EUC-JP';
  422. $languages['ja_JP']['XTRA_CODE'] = 'japanese_charset_xtra';
  423. $languages['ja']['ALIAS'] = 'ja_JP';
  424. $languages['ko_KR']['NAME'] = 'Korean';
  425. $languages['ko_KR']['CHARSET'] = 'euc-KR';
  426. $languages['ko_KR']['LOCALE'] = 'ko_KR.EUC-KR';
  427. // Function does not provide all needed options
  428. // $languages['ko_KR']['XTRA_CODE'] = 'korean_charset_xtra';
  429. $languages['ko']['ALIAS'] = 'ko_KR';
  430. $languages['lt_LT']['NAME'] = 'Lithuanian';
  431. $languages['lt_LT']['ALTNAME'] = 'Lietuvi&#371;';
  432. $languages['lt_LT']['CHARSET'] = 'utf-8';
  433. $languages['lt_LT']['LOCALE'] = 'lt_LT.UTF-8';
  434. $languages['lt']['ALIAS'] = 'lt_LT';
  435. $languages['nl_NL']['NAME'] = 'Dutch';
  436. $languages['nl_NL']['ALTNAME'] = 'Nederlands';
  437. $languages['nl_NL']['CHARSET'] = 'iso-8859-1';
  438. $languages['nl_NL']['LOCALE'] = 'nl_NL.ISO8859-1';
  439. $languages['nl']['ALIAS'] = 'nl_NL';
  440. $languages['ms_MY']['NAME'] = 'Malay';
  441. $languages['ms_MY']['ALTNAME'] = 'Bahasa Melayu';
  442. $languages['ms_MY']['CHARSET'] = 'iso-8859-1';
  443. $languages['ms_MY']['LOCALE'] = 'ms_MY.ISO8859-1';
  444. $languages['my']['ALIAS'] = 'ms_MY';
  445. $languages['nb_NO']['NAME'] = 'Norwegian (Bokm&aring;l)';
  446. $languages['nb_NO']['ALTNAME'] = 'Norsk (Bokm&aring;l)';
  447. $languages['nb_NO']['CHARSET'] = 'iso-8859-1';
  448. $languages['nb_NO']['LOCALE'] = 'nb_NO.ISO8859-1';
  449. $languages['nb']['ALIAS'] = 'nb_NO';
  450. $languages['nn_NO']['NAME'] = 'Norwegian (Nynorsk)';
  451. $languages['nn_NO']['ALTNAME'] = 'Norsk (Nynorsk)';
  452. $languages['nn_NO']['CHARSET'] = 'iso-8859-1';
  453. $languages['nn_NO']['LOCALE'] = 'nn_NO.ISO8859-1';
  454. $languages['pl_PL']['NAME'] = 'Polish';
  455. $languages['pl_PL']['ALTNAME'] = 'Polski';
  456. $languages['pl_PL']['CHARSET'] = 'iso-8859-2';
  457. $languages['pl_PL']['LOCALE'] = 'pl_PL.ISO8859-2';
  458. $languages['pl']['ALIAS'] = 'pl_PL';
  459. $languages['pt_PT']['NAME'] = 'Portuguese (Portugal)';
  460. $languages['pt_PT']['CHARSET'] = 'iso-8859-1';
  461. $languages['pt_PT']['LOCALE'] = 'pt_PT.ISO8859-1';
  462. $languages['pt']['ALIAS'] = 'pt_PT';
  463. $languages['pt_BR']['NAME'] = 'Portuguese (Brazil)';
  464. $languages['pt_BR']['ALTNAME'] = 'Portugu&ecirc;s do Brasil';
  465. $languages['pt_BR']['CHARSET'] = 'iso-8859-1';
  466. $languages['pt_BR']['LOCALE'] = 'pt_BR.ISO8859-1';
  467. $languages['ro_RO']['NAME'] = 'Romanian';
  468. $languages['ro_RO']['ALTNAME'] = 'Rom&acirc;n&#259;';
  469. $languages['ro_RO']['CHARSET'] = 'iso-8859-2';
  470. $languages['ro_RO']['LOCALE'] = 'ro_RO.ISO8859-2';
  471. $languages['ro']['ALIAS'] = 'ro_RO';
  472. $languages['ru_RU']['NAME'] = 'Russian';
  473. $languages['ru_RU']['ALTNAME'] = '&#1056;&#1091;&#1089;&#1089;&#1082;&#1080;&#1081;';
  474. $languages['ru_RU']['CHARSET'] = 'utf-8';
  475. $languages['ru_RU']['LOCALE'] = 'ru_RU.UTF-8';
  476. $languages['ru']['ALIAS'] = 'ru_RU';
  477. $languages['sk_SK']['NAME'] = 'Slovak';
  478. $languages['sk_SK']['CHARSET'] = 'iso-8859-2';
  479. $languages['sk_SK']['LOCALE'] = 'sk_SK.ISO8859-2';
  480. $languages['sk']['ALIAS'] = 'sk_SK';
  481. $languages['sl_SI']['NAME'] = 'Slovenian';
  482. $languages['sl_SI']['ALTNAME'] = 'Sloven&scaron;&#269;ina';
  483. $languages['sl_SI']['CHARSET'] = 'iso-8859-2';
  484. $languages['sl_SI']['LOCALE'] = 'sl_SI.ISO8859-2';
  485. $languages['sl']['ALIAS'] = 'sl_SI';
  486. $languages['sr_YU']['NAME'] = 'Serbian';
  487. $languages['sr_YU']['ALTNAME'] = 'Srpski';
  488. $languages['sr_YU']['CHARSET'] = 'iso-8859-2';
  489. $languages['sr_YU']['LOCALE'] = 'sr_YU.ISO8859-2';
  490. $languages['sr']['ALIAS'] = 'sr_YU';
  491. $languages['sv_SE']['NAME'] = 'Swedish';
  492. $languages['sv_SE']['ALTNAME'] = 'Svenska';
  493. $languages['sv_SE']['CHARSET'] = 'iso-8859-1';
  494. $languages['sv_SE']['LOCALE'] = 'sv_SE.ISO8859-1';
  495. $languages['sv']['ALIAS'] = 'sv_SE';
  496. $languages['th_TH']['NAME'] = 'Thai';
  497. $languages['th_TH']['CHARSET'] = 'tis-620';
  498. $languages['th_TH']['LOCALE'] = 'th_TH.TIS-620';
  499. $languages['th']['ALIAS'] = 'th_TH';
  500. $languages['tl_PH']['NAME'] = 'Tagalog';
  501. $languages['tl_PH']['CHARSET'] = 'iso-8859-1';
  502. $languages['tl_PH']['LOCALE'] = 'tl_PH.ISO8859-1';
  503. $languages['tl']['ALIAS'] = 'tl_PH';
  504. $languages['tr_TR']['NAME'] = 'Turkish';
  505. $languages['tr_TR']['CHARSET'] = 'iso-8859-9';
  506. $languages['tr_TR']['LOCALE'] = 'tr_TR.ISO8859-9';
  507. $languages['tr']['ALIAS'] = 'tr_TR';
  508. $languages['zh_TW']['NAME'] = 'Chinese Trad';
  509. $languages['zh_TW']['CHARSET'] = 'big5';
  510. $languages['zh_TW']['LOCALE'] = 'zh_TW.BIG5';
  511. $languages['tw']['ALIAS'] = 'zh_TW';
  512. $languages['zh_CN']['NAME'] = 'Chinese Simp';
  513. $languages['zh_CN']['CHARSET'] = 'gb2312';
  514. $languages['zh_CN']['LOCALE'] = 'zh_CN.GB2312';
  515. $languages['cn']['ALIAS'] = 'zh_CN';
  516. $languages['uk_UA']['NAME'] = 'Ukrainian';
  517. $languages['uk_UA']['CHARSET'] = 'koi8-u';
  518. $languages['uk_UA']['LOCALE'] = 'uk_UA.KOI8-U';
  519. $languages['uk']['ALIAS'] = 'uk_UA';
  520. $languages['ru_UA']['NAME'] = 'Russian (Ukrainian)';
  521. $languages['ru_UA']['CHARSET'] = 'koi8-r';
  522. $languages['ru_UA']['LOCALE'] = 'ru_UA.KOI8-R';
  523. /*
  524. $languages['vi_VN']['NAME'] = 'Vietnamese';
  525. $languages['vi_VN']['CHARSET'] = 'utf-8';
  526. $languages['vi']['ALIAS'] = 'vi_VN';
  527. */
  528. // Right to left languages
  529. $languages['ar']['NAME'] = 'Arabic';
  530. $languages['ar']['CHARSET'] = 'windows-1256';
  531. $languages['ar']['DIR'] = 'rtl';
  532. $languages['fa_IR']['NAME'] = 'Farsi';
  533. $languages['fa_IR']['CHARSET'] = 'utf-8';
  534. $languages['fa_IR']['DIR'] = 'rtl';
  535. $languages['fa_IR']['LOCALE'] = 'fa_IR.UTF-8';
  536. $languages['fa']['ALIAS'] = 'fa_IR';
  537. $languages['he_IL']['NAME'] = 'Hebrew';
  538. $languages['he_IL']['CHARSET'] = 'windows-1255';
  539. $languages['he_IL']['LOCALE'] = 'he_IL.CP1255';
  540. $languages['he_IL']['DIR'] = 'rtl';
  541. $languages['he']['ALIAS'] = 'he_IL';
  542. /* Detect whether gettext is installed. */
  543. $gettext_flags = 0;
  544. if (function_exists('_')) {
  545. $gettext_flags += 1;
  546. }
  547. if (function_exists('bindtextdomain')) {
  548. $gettext_flags += 2;
  549. }
  550. if (function_exists('textdomain')) {
  551. $gettext_flags += 4;
  552. }
  553. /* If gettext is fully loaded, cool */
  554. if ($gettext_flags == 7) {
  555. $use_gettext = true;
  556. }
  557. /* If we can fake gettext, try that */
  558. elseif ($gettext_flags == 0) {
  559. $use_gettext = true;
  560. include_once(SM_PATH . 'functions/gettext.php');
  561. } else {
  562. /* Uh-ho. A weird install */
  563. if (! $gettext_flags & 1) {
  564. /**
  565. * Function is used as replacement in broken installs
  566. * @ignore
  567. */
  568. function _($str) {
  569. return $str;
  570. }
  571. }
  572. if (! $gettext_flags & 2) {
  573. /**
  574. * Function is used as replacement in broken installs
  575. * @ignore
  576. */
  577. function bindtextdomain() {
  578. return;
  579. }
  580. }
  581. if (! $gettext_flags & 4) {
  582. /**
  583. * Function is used as replacemet in broken installs
  584. * @ignore
  585. */
  586. function textdomain() {
  587. return;
  588. }
  589. }
  590. }
  591. /**
  592. * Japanese charset extra function
  593. *
  594. * Action performed by function is defined by first argument.
  595. * Default return value is defined by second argument.
  596. * Use of third argument depends on action.
  597. *
  598. * @param string $action action performed by this function.
  599. * possible values:
  600. * decode - convert returned string to euc-jp. third argument unused
  601. * encode - convert returned string to jis. third argument unused
  602. * strimwidth - third argument=$width. trims string to $width symbols.
  603. * encodeheader - create base64 encoded header in iso-2022-jp. third argument unused
  604. * decodeheader - return human readable string from mime header. string is returned in euc-jp. third argument unused
  605. * downloadfilename - third argument $useragent. Arguments provide browser info. Returns shift-jis or euc-jp encoded file name
  606. * wordwrap - third argument=$wrap. wraps text at $wrap symbols
  607. * utf7-imap_encode - returns string converted from euc-jp to utf7-imap. third argument unused
  608. * utf7-imap_decode - returns string converted from utf7-imap to euc-jp. third argument unused
  609. * @param string $ret default return value
  610. */
  611. function japanese_charset_xtra() {
  612. $ret = func_get_arg(1); /* default return value */
  613. if (function_exists('mb_detect_encoding')) {
  614. switch (func_get_arg(0)) { /* action */
  615. case 'decode':
  616. $detect_encoding = @mb_detect_encoding($ret);
  617. if ($detect_encoding == 'JIS' ||
  618. $detect_encoding == 'EUC-JP' ||
  619. $detect_encoding == 'SJIS' ||
  620. $detect_encoding == 'UTF-8') {
  621. $ret = mb_convert_kana(mb_convert_encoding($ret, 'EUC-JP', 'AUTO'), "KV");
  622. }
  623. break;
  624. case 'encode':
  625. $detect_encoding = @mb_detect_encoding($ret);
  626. if ($detect_encoding == 'JIS' ||
  627. $detect_encoding == 'EUC-JP' ||
  628. $detect_encoding == 'SJIS' ||
  629. $detect_encoding == 'UTF-8') {
  630. $ret = mb_convert_encoding(mb_convert_kana($ret, "KV"), 'JIS', 'AUTO');
  631. }
  632. break;
  633. case 'strimwidth':
  634. $width = func_get_arg(2);
  635. $ret = mb_strimwidth($ret, 0, $width, '...');
  636. break;
  637. case 'encodeheader':
  638. $result = '';
  639. if (strlen($ret) > 0) {
  640. $tmpstr = mb_substr($ret, 0, 1);
  641. $prevcsize = strlen($tmpstr);
  642. for ($i = 1; $i < mb_strlen($ret); $i++) {
  643. $tmp = mb_substr($ret, $i, 1);
  644. if (strlen($tmp) == $prevcsize) {
  645. $tmpstr .= $tmp;
  646. } else {
  647. if ($prevcsize == 1) {
  648. $result .= $tmpstr;
  649. } else {
  650. $result .= str_replace(' ', '',
  651. mb_encode_mimeheader($tmpstr,'iso-2022-jp','B',''));
  652. }
  653. $tmpstr = $tmp;
  654. $prevcsize = strlen($tmp);
  655. }
  656. }
  657. if (strlen($tmpstr)) {
  658. if (strlen(mb_substr($tmpstr, 0, 1)) == 1)
  659. $result .= $tmpstr;
  660. else
  661. $result .= str_replace(' ', '',
  662. mb_encode_mimeheader($tmpstr,'iso-2022-jp','B',''));
  663. }
  664. }
  665. $ret = $result;
  666. break;
  667. case 'decodeheader':
  668. $ret = str_replace("\t", "", $ret);
  669. if (eregi('=\\?([^?]+)\\?(q|b)\\?([^?]+)\\?=', $ret))
  670. $ret = @mb_decode_mimeheader($ret);
  671. $ret = @mb_convert_encoding($ret, 'EUC-JP', 'AUTO');
  672. break;
  673. case 'downloadfilename':
  674. $useragent = func_get_arg(2);
  675. if (strstr($useragent, 'Windows') !== false ||
  676. strstr($useragent, 'Mac_') !== false) {
  677. $ret = mb_convert_encoding($ret, 'SJIS', 'AUTO');
  678. } else {
  679. $ret = mb_convert_encoding($ret, 'EUC-JP', 'AUTO');
  680. }
  681. break;
  682. case 'wordwrap':
  683. $no_begin = "\x21\x25\x29\x2c\x2e\x3a\x3b\x3f\x5d\x7d\xa1\xf1\xa1\xeb\xa1" .
  684. "\xc7\xa1\xc9\xa2\xf3\xa1\xec\xa1\xed\xa1\xee\xa1\xa2\xa1\xa3\xa1\xb9" .
  685. "\xa1\xd3\xa1\xd5\xa1\xd7\xa1\xd9\xa1\xdb\xa1\xcd\xa4\xa1\xa4\xa3\xa4" .
  686. "\xa5\xa4\xa7\xa4\xa9\xa4\xc3\xa4\xe3\xa4\xe5\xa4\xe7\xa4\xee\xa1\xab" .
  687. "\xa1\xac\xa1\xb5\xa1\xb6\xa5\xa1\xa5\xa3\xa5\xa5\xa5\xa7\xa5\xa9\xa5" .
  688. "\xc3\xa5\xe3\xa5\xe5\xa5\xe7\xa5\xee\xa5\xf5\xa5\xf6\xa1\xa6\xa1\xbc" .
  689. "\xa1\xb3\xa1\xb4\xa1\xaa\xa1\xf3\xa1\xcb\xa1\xa4\xa1\xa5\xa1\xa7\xa1" .
  690. "\xa8\xa1\xa9\xa1\xcf\xa1\xd1";
  691. $no_end = "\x5c\x24\x28\x5b\x7b\xa1\xf2\x5c\xa1\xc6\xa1\xc8\xa1\xd2\xa1" .
  692. "\xd4\xa1\xd6\xa1\xd8\xa1\xda\xa1\xcc\xa1\xf0\xa1\xca\xa1\xce\xa1\xd0\xa1\xef";
  693. $wrap = func_get_arg(2);
  694. if (strlen($ret) >= $wrap &&
  695. substr($ret, 0, 1) != '>' &&
  696. strpos($ret, 'http://') === FALSE &&
  697. strpos($ret, 'https://') === FALSE &&
  698. strpos($ret, 'ftp://') === FALSE) {
  699. $ret = mb_convert_kana($ret, "KV");
  700. $line_new = '';
  701. $ptr = 0;
  702. while ($ptr < strlen($ret) - 1) {
  703. $l = mb_strcut($ret, $ptr, $wrap);
  704. $ptr += strlen($l);
  705. $tmp = $l;
  706. $l = mb_strcut($ret, $ptr, 2);
  707. while (strlen($l) != 0 && mb_strpos($no_begin, $l) !== FALSE ) {
  708. $tmp .= $l;
  709. $ptr += strlen($l);
  710. $l = mb_strcut($ret, $ptr, 1);
  711. }
  712. $line_new .= $tmp;
  713. if ($ptr < strlen($ret) - 1)
  714. $line_new .= "\n";
  715. }
  716. $ret = $line_new;
  717. }
  718. break;
  719. case 'utf7-imap_encode':
  720. $ret = mb_convert_encoding($ret, 'UTF7-IMAP', 'EUC-JP');
  721. break;
  722. case 'utf7-imap_decode':
  723. $ret = mb_convert_encoding($ret, 'EUC-JP', 'UTF7-IMAP');
  724. break;
  725. }
  726. }
  727. return $ret;
  728. }
  729. /**
  730. * Korean charset extra functions
  731. *
  732. * Action performed by function is defined by first argument.
  733. * Default return value is defined by second argument.
  734. *
  735. * @param string action performed by this function.
  736. * possible values:
  737. * downloadfilename - Hangul(Korean Character) Attached File Name Fix.
  738. * @param string default return value
  739. */
  740. function korean_charset_xtra() {
  741. $ret = func_get_arg(1); /* default return value */
  742. if (func_get_arg(0) == 'downloadfilename') { /* action */
  743. $ret = str_replace("\x0D\x0A", '', $ret); /* Hanmail's CR/LF Clear */
  744. for ($i=0;$i<strlen($ret);$i++) {
  745. if ($ret[$i] >= "\xA1" && $ret[$i] <= "\xFE") { /* 0xA1 - 0XFE are Valid */
  746. $i++;
  747. continue;
  748. } else if (($ret[$i] >= 'a' && $ret[$i] <= 'z') || /* From Original ereg_replace in download.php */
  749. ($ret[$i] >= 'A' && $ret[$i] <= 'Z') ||
  750. ($ret[$i] == '.') || ($ret[$i] == '-')) {
  751. continue;
  752. } else {
  753. $ret[$i] = '_';
  754. }
  755. }
  756. }
  757. return $ret;
  758. }
  759. /**
  760. * Replaces non-braking spaces inserted by some browsers with regular space
  761. *
  762. * This function can be used to replace non-braking space symbols
  763. * that are inserted in forms by some browsers instead of normal
  764. * space symbol.
  765. *
  766. * @param string $string Text that needs to be cleaned
  767. * @param string $charset Charset used in text
  768. * @return string Cleaned text
  769. */
  770. function cleanup_nbsp($string,$charset) {
  771. // reduce number of case statements
  772. if (stristr('iso-8859-',substr($charset,0,9))){
  773. $output_charset="iso-8859-x";
  774. }
  775. if (stristr('windows-125',substr($charset,0,11))){
  776. $output_charset="cp125x";
  777. }
  778. if (stristr('koi8',substr($charset,0,4))){
  779. $output_charset="koi8-x";
  780. }
  781. if (! isset($output_charset)){
  782. $output_charset=strtolower($charset);
  783. }
  784. // where is non-braking space symbol
  785. switch($output_charset):
  786. case "iso-8859-x":
  787. case "cp125x":
  788. case "iso-2022-jp":
  789. $nbsp="\xA0";
  790. break;
  791. case "koi8-x":
  792. $nbsp="\x9A";
  793. break;
  794. case "utf-8":
  795. $nbsp="\xC2\xA0";
  796. break;
  797. default:
  798. // don't change string if charset is unmatched
  799. return $string;
  800. endswitch;
  801. // return space instead of non-braking space.
  802. return str_replace($nbsp,' ',$string);
  803. }
  804. /**
  805. * Function informs if it is safe to convert given charset to the one that is used by user.
  806. *
  807. * It is safe to use conversion only if user uses utf-8 encoding and when
  808. * converted charset is similar to the one that is used by user.
  809. *
  810. * @param string $input_charset Charset of text that needs to be converted
  811. * @return bool is it possible to convert to user's charset
  812. */
  813. function is_conversion_safe($input_charset) {
  814. global $languages, $sm_notAlias, $default_charset;
  815. // convert to lower case
  816. $input_charset = strtolower($input_charset);
  817. // Is user's locale Unicode based ?
  818. if ( $default_charset == "utf-8" ) {
  819. return true;
  820. }
  821. // Charsets that are similar
  822. switch ($default_charset):
  823. case "windows-1251":
  824. if ( $input_charset == "iso-8859-5" ||
  825. $input_charset == "koi8-r" ||
  826. $input_charset == "koi8-u" ) {
  827. return true;
  828. } else {
  829. return false;
  830. }
  831. case "windows-1257":
  832. if ( $input_charset == "iso-8859-13" ||
  833. $input_charset == "iso-8859-4" ) {
  834. return true;
  835. } else {
  836. return false;
  837. }
  838. case "iso-8859-4":
  839. if ( $input_charset == "iso-8859-13" ||
  840. $input_charset == "windows-1257" ) {
  841. return true;
  842. } else {
  843. return false;
  844. }
  845. case "iso-8859-5":
  846. if ( $input_charset == "windows-1251" ||
  847. $input_charset == "koi8-r" ||
  848. $input_charset == "koi8-u" ) {
  849. return true;
  850. } else {
  851. return false;
  852. }
  853. case "iso-8859-13":
  854. if ( $input_charset == "iso-8859-4" ||
  855. $input_charset == "windows-1257" ) {
  856. return true;
  857. } else {
  858. return false;
  859. }
  860. case "koi8-r":
  861. if ( $input_charset == "windows-1251" ||
  862. $input_charset == "iso-8859-5" ||
  863. $input_charset == "koi8-u" ) {
  864. return true;
  865. } else {
  866. return false;
  867. }
  868. case "koi8-u":
  869. if ( $input_charset == "windows-1251" ||
  870. $input_charset == "iso-8859-5" ||
  871. $input_charset == "koi8-r" ) {
  872. return true;
  873. } else {
  874. return false;
  875. }
  876. default:
  877. return false;
  878. endswitch;
  879. }
  880. ?>