i18n.php 31 KB

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