i18n.php 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801
  1. <?php
  2. /**
  3. * SquirrelMail internationalization functions
  4. *
  5. * This file contains variuos functions that are needed to do
  6. * internationalization of SquirrelMail.
  7. *
  8. * Internally the output character set is used. Other characters are
  9. * encoded using Unicode entities according to HTML 4.0.
  10. *
  11. * @copyright &copy; 1999-2005 The SquirrelMail Project Team
  12. * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  13. * @version $Id$
  14. * @package squirrelmail
  15. * @subpackage i18n
  16. */
  17. /** @ignore */
  18. if (! defined('SM_PATH')) define('SM_PATH','../');
  19. /** Everything uses global.php... */
  20. require_once(SM_PATH . 'functions/global.php');
  21. /**
  22. * Gettext bindtextdomain wrapper.
  23. *
  24. * Wrapper solves differences between php versions in order to provide
  25. * ngettext support. Should be used if translation uses ngettext
  26. * functions.
  27. * @since 1.5.1
  28. * @param string $domain gettext domain name
  29. * @param string $dir directory that contains all translations
  30. * @return string path to translation directory
  31. */
  32. function sq_bindtextdomain($domain,$dir) {
  33. global $l10n, $gettext_flags, $sm_notAlias;
  34. if ($gettext_flags==7) {
  35. // gettext extension without ngettext
  36. if (substr($dir, -1) != '/') $dir .= '/';
  37. $mofile=$dir . $sm_notAlias . '/LC_MESSAGES/' . $domain . '.mo';
  38. $input = new FileReader($mofile);
  39. $l10n[$domain] = new gettext_reader($input);
  40. }
  41. $dir=bindtextdomain($domain,$dir);
  42. return $dir;
  43. }
  44. /**
  45. * Gettext textdomain wrapper.
  46. * Makes sure that gettext_domain global is modified.
  47. * @since 1.5.1
  48. * @param string $name gettext domain name
  49. * @return string gettext domain name
  50. */
  51. function sq_textdomain($domain) {
  52. global $gettext_domain;
  53. $gettext_domain=textdomain($domain);
  54. return $gettext_domain;
  55. }
  56. /**
  57. * php setlocale function wrapper
  58. *
  59. * From php 4.3.0 it is possible to use arrays in order to set locale.
  60. * php gettext extension works only when locale is set. This wrapper
  61. * function allows to use more than one locale name.
  62. *
  63. * @param int $category locale category name. Use php named constants
  64. * (LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME)
  65. * @param mixed $locale option contains array with possible locales or string with one locale
  66. * @return string name of set locale or false, if all locales fail.
  67. * @since 1.5.1 and 1.4.5
  68. * @see http://www.php.net/setlocale
  69. */
  70. function sq_setlocale($category,$locale) {
  71. // string with only one locale
  72. if (is_string($locale))
  73. return setlocale($category,$locale);
  74. if (! check_php_version(4,3)) {
  75. $ret=false;
  76. $index=0;
  77. while ( ! $ret && $index<count($locale)) {
  78. $ret=setlocale($category,$locale[$index]);
  79. $index++;
  80. }
  81. } else {
  82. // php 4.3.0 or better, use entire array
  83. $ret=setlocale($category,$locale);
  84. }
  85. return $ret;
  86. }
  87. /**
  88. * Converts string from given charset to charset, that can be displayed by user translation.
  89. *
  90. * Function by default returns html encoded strings, if translation uses different encoding.
  91. * If Japanese translation is used - function returns string converted to euc-jp
  92. * If iconv or recode functions are enabled and translation uses utf-8 - function returns utf-8 encoded string.
  93. * If $charset is not supported - function returns unconverted string.
  94. *
  95. * sanitizing of html tags is also done by this function.
  96. *
  97. * @param string $charset
  98. * @param string $string Text to be decoded
  99. * @param boolean $force_decode converts string to html without $charset!=$default_charset check.
  100. * Argument is available since 1.5.1 and 1.4.5.
  101. * @param boolean $save_html disables htmlspecialchars() in order to preserve
  102. * html formating. Use with care. Available since 1.5.1
  103. * @return string decoded string
  104. */
  105. function charset_decode ($charset, $string, $force_decode=false, $save_html=false) {
  106. global $languages, $squirrelmail_language, $default_charset;
  107. global $use_php_recode, $use_php_iconv, $aggressive_decoding;
  108. if (isset($languages[$squirrelmail_language]['XTRA_CODE']) &&
  109. function_exists($languages[$squirrelmail_language]['XTRA_CODE'] . '_decode')) {
  110. $string = call_user_func($languages[$squirrelmail_language]['XTRA_CODE'] . '_decode', $string);
  111. }
  112. $charset = strtolower($charset);
  113. set_my_charset();
  114. // Variables that allow to use functions without function_exist() calls
  115. if (! isset($use_php_recode) || $use_php_recode=="" ) {
  116. $use_php_recode=false; }
  117. if (! isset($use_php_iconv) || $use_php_iconv=="" ) {
  118. $use_php_iconv=false; }
  119. // Don't do conversion if charset is the same.
  120. if ( ! $force_decode && $charset == strtolower($default_charset) )
  121. return ($save_html ? $string : htmlspecialchars($string));
  122. // catch iso-8859-8-i thing
  123. if ( $charset == "iso-8859-8-i" )
  124. $charset = "iso-8859-8";
  125. /*
  126. * Recode converts html special characters automatically if you use
  127. * 'charset..html' decoding. There is no documented way to put -d option
  128. * into php recode function call.
  129. */
  130. if ( $use_php_recode ) {
  131. if ( $default_charset == "utf-8" ) {
  132. // other charsets can be converted to utf-8 without loss.
  133. // and output string is smaller
  134. $string = recode_string($charset . "..utf-8",$string);
  135. return ($save_html ? $string : htmlspecialchars($string));
  136. } else {
  137. $string = recode_string($charset . "..html",$string);
  138. // recode does not convert single quote, htmlspecialchars does.
  139. $string = str_replace("'", '&#039;', $string);
  140. // undo html specialchars
  141. if ($save_html)
  142. $string=str_replace(array('&amp;','&quot;','&lt;','&gt;'),
  143. array('&','"','<','>'),$string);
  144. return $string;
  145. }
  146. }
  147. // iconv functions does not have html target and can be used only with utf-8
  148. if ( $use_php_iconv && $default_charset=='utf-8') {
  149. $string = iconv($charset,$default_charset,$string);
  150. return ($save_html ? $string : htmlspecialchars($string));
  151. }
  152. // If we don't use recode and iconv, we'll do it old way.
  153. /* All HTML special characters are 7 bit and can be replaced first */
  154. if (! $save_html) $string = htmlspecialchars ($string);
  155. /* controls cpu and memory intensive decoding cycles */
  156. if (! isset($aggressive_decoding) || $aggressive_decoding=="" ) {
  157. $aggressive_decoding=false; }
  158. $decode=fixcharset($charset);
  159. $decodefile=SM_PATH . 'functions/decode/' . $decode . '.php';
  160. if (file_exists($decodefile)) {
  161. include_once($decodefile);
  162. // send $save_html argument to decoding function. needed for iso-2022-xx decoding.
  163. $ret = call_user_func('charset_decode_'.$decode, $string, $save_html);
  164. } else {
  165. $ret = $string;
  166. }
  167. return( $ret );
  168. }
  169. /**
  170. * Converts html string to given charset
  171. * @since 1.5.1 and 1.4.4
  172. * @param string $string
  173. * @param string $charset
  174. * @param boolean $htmlencode keep htmlspecialchars encoding
  175. * @param string
  176. */
  177. function charset_encode($string,$charset,$htmlencode=true) {
  178. global $default_charset;
  179. $encode=fixcharset($charset);
  180. $encodefile=SM_PATH . 'functions/encode/' . $encode . '.php';
  181. if (file_exists($encodefile)) {
  182. include_once($encodefile);
  183. $ret = call_user_func('charset_encode_'.$encode, $string);
  184. } elseif(file_exists(SM_PATH . 'functions/encode/us_ascii.php')) {
  185. // function replaces all 8bit html entities with question marks.
  186. // it is used when other encoding functions are unavailable
  187. include_once(SM_PATH . 'functions/encode/us_ascii.php');
  188. $ret = charset_encode_us_ascii($string);
  189. } else {
  190. /**
  191. * fix for yahoo users that remove all us-ascii related things
  192. */
  193. $ret = $string;
  194. }
  195. /**
  196. * Undo html special chars, some places (like compose form) have
  197. * own sanitizing functions and don't need html symbols.
  198. * Undo chars only after encoding in order to prevent conversion of
  199. * html entities in plain text emails.
  200. */
  201. if (! $htmlencode ) {
  202. $ret = str_replace(array('&amp;','&gt;','&lt;','&quot;'),array('&','>','<','"'),$ret);
  203. }
  204. return( $ret );
  205. }
  206. /**
  207. * Combined decoding and encoding functions
  208. *
  209. * If conversion is done to charset different that utf-8, unsupported symbols
  210. * will be replaced with question marks.
  211. * @since 1.5.1 and 1.4.4
  212. * @param string $in_charset initial charset
  213. * @param string $string string that has to be converted
  214. * @param string $out_charset final charset
  215. * @param boolean $htmlencode keep htmlspecialchars encoding
  216. * @return string converted string
  217. */
  218. function charset_convert($in_charset,$string,$out_charset,$htmlencode=true) {
  219. $string=charset_decode($in_charset,$string,true);
  220. $string=charset_encode($string,$out_charset,$htmlencode);
  221. return $string;
  222. }
  223. /**
  224. * Makes charset name suitable for decoding cycles
  225. *
  226. * @since 1.5.0 and 1.4.4
  227. * @param string $charset Name of charset
  228. * @return string $charset Adjusted name of charset
  229. */
  230. function fixcharset($charset) {
  231. /* remove minus and characters that might be used in paths from charset
  232. * name in order to be able to use it in function names and include calls.
  233. */
  234. $charset=preg_replace("/[-:.\/\\\]/",'_',$charset);
  235. // windows-125x and cp125x charsets
  236. $charset=str_replace('windows_','cp',$charset);
  237. // ibm > cp
  238. $charset=str_replace('ibm','cp',$charset);
  239. // iso-8859-8-i -> iso-8859-8
  240. // use same cycle until I'll find differences
  241. $charset=str_replace('iso_8859_8_i','iso_8859_8',$charset);
  242. return $charset;
  243. }
  244. /**
  245. * Set up the language to be output
  246. * if $do_search is true, then scan the browser information
  247. * for a possible language that we know
  248. *
  249. * Function sets system locale environment (LC_ALL, LANG, LANGUAGE),
  250. * gettext translation bindings and html header information.
  251. *
  252. * Function returns error codes, if there is some fatal error.
  253. * 0 = no error,
  254. * 1 = mbstring support is not present,
  255. * 2 = mbstring support is not present, user's translation reverted to en_US.
  256. *
  257. * @param string $sm_language translation used by user's interface
  258. * @param bool $do_search use browser's preferred language detection functions. Defaults to false.
  259. * @param bool $default set $sm_language to $squirrelmail_default_language if language detection fails or language is not set. Defaults to false.
  260. * @return int function execution error codes.
  261. */
  262. function set_up_language($sm_language, $do_search = false, $default = false) {
  263. static $SetupAlready = 0;
  264. global $use_gettext, $languages,
  265. $squirrelmail_language, $squirrelmail_default_language, $default_charset,
  266. $sm_notAlias, $username, $data_dir;
  267. if ($SetupAlready) {
  268. return;
  269. }
  270. $SetupAlready = TRUE;
  271. sqgetGlobalVar('HTTP_ACCEPT_LANGUAGE', $accept_lang, SQ_SERVER);
  272. /**
  273. * If function is asked to detect preferred language
  274. * OR squirrelmail default language is set to empty string
  275. * AND
  276. * squirrelmail language ($sm_language) is empty string
  277. * (not set in user's prefs and no cookie with language info)
  278. * AND
  279. * browser provides list of preferred languages
  280. * THEN
  281. * get preferred language from HTTP_ACCEPT_LANGUAGE header
  282. */
  283. if (($do_search || empty($squirrelmail_default_language)) &&
  284. ! $sm_language &&
  285. isset($accept_lang)) {
  286. // TODO: use more than one language, if first language is not available
  287. // FIXME: function assumes that string contains two or more characters.
  288. // FIXME: some languages use 5 chars
  289. $sm_language = substr($accept_lang, 0, 2);
  290. }
  291. /**
  292. * If language preference is not set OR script asks to use default language
  293. * AND
  294. * default squirrelmail language is not set to empty string
  295. * THEN
  296. * use default squirrelmail language value from configuration.
  297. */
  298. if ((!$sm_language||$default) &&
  299. ! empty($squirrelmail_default_language)) {
  300. $squirrelmail_language = $squirrelmail_default_language;
  301. $sm_language = $squirrelmail_default_language;
  302. }
  303. /** provide failsafe language when detection fails */
  304. if (! $sm_language) $sm_language='en_US';
  305. $sm_notAlias = $sm_language;
  306. // Catching removed translation
  307. // System reverts to English translation if user prefs contain translation
  308. // that is not available in $languages array
  309. if (!isset($languages[$sm_notAlias])) {
  310. $sm_notAlias="en_US";
  311. }
  312. while (isset($languages[$sm_notAlias]['ALIAS'])) {
  313. $sm_notAlias = $languages[$sm_notAlias]['ALIAS'];
  314. }
  315. if ( isset($sm_language) &&
  316. $use_gettext &&
  317. $sm_language != '' &&
  318. isset($languages[$sm_notAlias]['CHARSET']) ) {
  319. sq_bindtextdomain( 'squirrelmail', SM_PATH . 'locale/' );
  320. sq_textdomain( 'squirrelmail' );
  321. // set codeset in order to avoid gettext charset conversions
  322. if (function_exists('bind_textdomain_codeset')) {
  323. // Japanese translation uses different internal charset
  324. if ($sm_notAlias == 'ja_JP') {
  325. bind_textdomain_codeset ('squirrelmail', 'EUC-JP');
  326. } else {
  327. bind_textdomain_codeset ('squirrelmail', $languages[$sm_notAlias]['CHARSET'] );
  328. }
  329. }
  330. // Use LOCALE key, if it is set.
  331. if (isset($languages[$sm_notAlias]['LOCALE'])){
  332. $longlocale=$languages[$sm_notAlias]['LOCALE'];
  333. } else {
  334. $longlocale=$sm_notAlias;
  335. }
  336. // try setting locale
  337. $retlocale=sq_setlocale(LC_ALL, $longlocale);
  338. // check if locale is set and assign that locale to $longlocale
  339. // in order to use it in putenv calls.
  340. if (! is_bool($retlocale)) {
  341. $longlocale=$retlocale;
  342. } elseif (is_array($longlocale)) {
  343. // setting of all locales failed.
  344. // we need string instead of array used in LOCALE key.
  345. $longlocale=$sm_notAlias;
  346. }
  347. if ( !((bool)ini_get('safe_mode')) &&
  348. getenv( 'LC_ALL' ) != $longlocale ) {
  349. putenv( "LC_ALL=$longlocale" );
  350. putenv( "LANG=$longlocale" );
  351. putenv( "LANGUAGE=$longlocale" );
  352. putenv( "LC_NUMERIC=C" );
  353. if ($sm_notAlias=='tr_TR') putenv( "LC_CTYPE=C" );
  354. }
  355. // Workaround for plugins that use numbers with floating point
  356. // It might be removed if plugins use correct decimal delimiters
  357. // according to locale settings.
  358. setlocale(LC_NUMERIC, 'C');
  359. // Workaround for specific Turkish strtolower/strtoupper rules.
  360. // Many functions expect English conversion rules.
  361. if ($sm_notAlias=='tr_TR') setlocale(LC_CTYPE,'C');
  362. // Set text direction/alignment variables
  363. // These don't appear to be used... are they safe to remove?
  364. if (isset($languages[$sm_notAlias]['DIR']) &&
  365. $languages[$sm_notAlias]['DIR'] == 'rtl') {
  366. /**
  367. * Text direction
  368. * @global string $text_direction
  369. */
  370. $text_direction='rtl';
  371. /**
  372. * Left alignment
  373. * @global string $left_align
  374. */
  375. $left_align='right';
  376. /**
  377. * Right alignment
  378. * @global string $right_align
  379. */
  380. $right_align='left';
  381. } else {
  382. $text_direction='ltr';
  383. $left_align='left';
  384. $right_align='right';
  385. }
  386. $squirrelmail_language = $sm_notAlias;
  387. if ($squirrelmail_language == 'ja_JP') {
  388. header ('Content-Type: text/html; charset=EUC-JP');
  389. if (!function_exists('mb_internal_encoding')) {
  390. // Error messages can't be displayed here
  391. $error = 1;
  392. // Revert to English if possible.
  393. if (function_exists('setPref') && $username!='' && $data_dir!="") {
  394. setPref($data_dir, $username, 'language', "en_US");
  395. $error = 2;
  396. }
  397. // stop further execution in order not to get php errors on mb_internal_encoding().
  398. return $error;
  399. }
  400. if (function_exists('mb_language')) {
  401. mb_language('Japanese');
  402. }
  403. mb_internal_encoding('EUC-JP');
  404. mb_http_output('pass');
  405. } elseif ($squirrelmail_language == 'en_US') {
  406. header( 'Content-Type: text/html; charset=' . $default_charset );
  407. } else {
  408. header( 'Content-Type: text/html; charset=' . $languages[$sm_notAlias]['CHARSET'] );
  409. }
  410. /**
  411. * mbstring.func_overload fix (#929644).
  412. *
  413. * php mbstring extension can replace standard string functions with their multibyte
  414. * equivalents. See http://www.php.net/ref.mbstring#mbstring.overload. This feature
  415. * was added in php v.4.2.0
  416. *
  417. * Some SquirrelMail functions work with 8bit strings in bytes. If interface is forced
  418. * to use mbstring functions and mbstring internal encoding is set to multibyte charset,
  419. * interface can't trust regular string functions. Due to mbstring overloading design
  420. * limits php scripts can't control this setting.
  421. *
  422. * This hack should fix some issues related to 8bit strings in passwords. Correct fix is
  423. * to disable mbstring overloading. Japanese translation uses different internal encoding.
  424. */
  425. if ($squirrelmail_language != 'ja_JP' &&
  426. function_exists('mb_internal_encoding') &&
  427. check_php_version(4,2,0) &&
  428. (int)ini_get('mbstring.func_overload')!=0) {
  429. mb_internal_encoding('pass');
  430. }
  431. }
  432. return 0;
  433. }
  434. /**
  435. * Sets default_charset variable according to the one that is used by user's translations.
  436. *
  437. * Function changes global $default_charset variable in order to be sure, that it
  438. * contains charset used by user's translation. Sanity of $squirrelmail_language
  439. * and $default_charset combination is also tested.
  440. *
  441. * There can be a $default_charset setting in the
  442. * config.php file, but the user may have a different language
  443. * selected for a user interface. This function checks the
  444. * language selected by the user and tags the outgoing messages
  445. * with the appropriate charset corresponding to the language
  446. * selection. This is "more right" (tm), than just stamping the
  447. * message blindly with the system-wide $default_charset.
  448. */
  449. function set_my_charset(){
  450. global $data_dir, $username, $default_charset, $languages, $squirrelmail_language;
  451. $my_language = getPref($data_dir, $username, 'language');
  452. if (!$my_language) {
  453. $my_language = $squirrelmail_language ;
  454. }
  455. // Catch removed translation
  456. if (!isset($languages[$my_language])) {
  457. $my_language="en_US";
  458. }
  459. while (isset($languages[$my_language]['ALIAS'])) {
  460. $my_language = $languages[$my_language]['ALIAS'];
  461. }
  462. $my_charset = $languages[$my_language]['CHARSET'];
  463. if ($my_language!='en_US') {
  464. $default_charset = $my_charset;
  465. }
  466. }
  467. /**
  468. * Replaces non-braking spaces inserted by some browsers with regular space
  469. *
  470. * This function can be used to replace non-braking space symbols
  471. * that are inserted in forms by some browsers instead of normal
  472. * space symbol.
  473. *
  474. * @param string $string Text that needs to be cleaned
  475. * @param string $charset Charset used in text
  476. * @return string Cleaned text
  477. */
  478. function cleanup_nbsp($string,$charset) {
  479. // reduce number of case statements
  480. if (stristr('iso-8859-',substr($charset,0,9))){
  481. $output_charset="iso-8859-x";
  482. }
  483. if (stristr('windows-125',substr($charset,0,11))){
  484. $output_charset="cp125x";
  485. }
  486. if (stristr('koi8',substr($charset,0,4))){
  487. $output_charset="koi8-x";
  488. }
  489. if (! isset($output_charset)){
  490. $output_charset=strtolower($charset);
  491. }
  492. // where is non-braking space symbol
  493. switch($output_charset):
  494. case "iso-8859-x":
  495. case "cp125x":
  496. case "iso-2022-jp":
  497. $nbsp="\xA0";
  498. break;
  499. case "koi8-x":
  500. $nbsp="\x9A";
  501. break;
  502. case "utf-8":
  503. $nbsp="\xC2\xA0";
  504. break;
  505. default:
  506. // don't change string if charset is unmatched
  507. return $string;
  508. endswitch;
  509. // return space instead of non-braking space.
  510. return str_replace($nbsp,' ',$string);
  511. }
  512. /**
  513. * Function informs if it is safe to convert given charset to the one that is used by user.
  514. *
  515. * It is safe to use conversion only if user uses utf-8 encoding and when
  516. * converted charset is similar to the one that is used by user.
  517. *
  518. * @param string $input_charset Charset of text that needs to be converted
  519. * @return bool is it possible to convert to user's charset
  520. */
  521. function is_conversion_safe($input_charset) {
  522. global $languages, $sm_notAlias, $default_charset, $lossy_encoding;
  523. if (isset($lossy_encoding) && $lossy_encoding )
  524. return true;
  525. // convert to lower case
  526. $input_charset = strtolower($input_charset);
  527. // Is user's locale Unicode based ?
  528. if ( $default_charset == "utf-8" ) {
  529. return true;
  530. }
  531. // Charsets that are similar
  532. switch ($default_charset):
  533. case "windows-1251":
  534. if ( $input_charset == "iso-8859-5" ||
  535. $input_charset == "koi8-r" ||
  536. $input_charset == "koi8-u" ) {
  537. return true;
  538. } else {
  539. return false;
  540. }
  541. case "windows-1257":
  542. if ( $input_charset == "iso-8859-13" ||
  543. $input_charset == "iso-8859-4" ) {
  544. return true;
  545. } else {
  546. return false;
  547. }
  548. case "iso-8859-4":
  549. if ( $input_charset == "iso-8859-13" ||
  550. $input_charset == "windows-1257" ) {
  551. return true;
  552. } else {
  553. return false;
  554. }
  555. case "iso-8859-5":
  556. if ( $input_charset == "windows-1251" ||
  557. $input_charset == "koi8-r" ||
  558. $input_charset == "koi8-u" ) {
  559. return true;
  560. } else {
  561. return false;
  562. }
  563. case "iso-8859-13":
  564. if ( $input_charset == "iso-8859-4" ||
  565. $input_charset == "windows-1257" ) {
  566. return true;
  567. } else {
  568. return false;
  569. }
  570. case "koi8-r":
  571. if ( $input_charset == "windows-1251" ||
  572. $input_charset == "iso-8859-5" ||
  573. $input_charset == "koi8-u" ) {
  574. return true;
  575. } else {
  576. return false;
  577. }
  578. case "koi8-u":
  579. if ( $input_charset == "windows-1251" ||
  580. $input_charset == "iso-8859-5" ||
  581. $input_charset == "koi8-r" ) {
  582. return true;
  583. } else {
  584. return false;
  585. }
  586. default:
  587. return false;
  588. endswitch;
  589. }
  590. /* ------------------------------ main --------------------------- */
  591. global $squirrelmail_language, $languages, $use_gettext;
  592. if (! sqgetGlobalVar('squirrelmail_language',$squirrelmail_language,SQ_COOKIE)) {
  593. $squirrelmail_language = '';
  594. }
  595. /**
  596. * Array specifies the available translations.
  597. *
  598. * Structure of array:
  599. * $languages['language']['variable'] = 'value'
  600. *
  601. * Possible 'variable' names:
  602. * NAME - Translation name in English
  603. * CHARSET - Encoding used by translation
  604. * ALIAS - used when 'language' is only short name and 'value' should provide long language name
  605. * ALTNAME - Native translation name. Any 8bit symbols must be html encoded.
  606. * LOCALE - Full locale name (in xx_XX.charset format). It can use array with more than one locale name since 1.4.5 and 1.5.1
  607. * DIR - Text direction. Used to define Right-to-Left languages. Possible values 'rtl' or 'ltr'. If undefined - defaults to 'ltr'
  608. * XTRA_CODE - translation uses special functions. See doc/i18n.txt
  609. *
  610. * Each 'language' definition requires NAME+CHARSET or ALIAS variables.
  611. *
  612. * @name $languages
  613. * @global array $languages
  614. */
  615. $languages['en_US']['NAME'] = 'English';
  616. $languages['en_US']['CHARSET'] = 'iso-8859-1';
  617. $languages['en_US']['LOCALE'] = 'en_US.ISO8859-1';
  618. $languages['en']['ALIAS'] = 'en_US';
  619. /**
  620. * Automatic translation loading from setup.php files.
  621. * Solution for bug. 1240889.
  622. * setup.php file can contain $languages array entries and XTRA_CODE functions.
  623. */
  624. if (is_dir(SM_PATH . 'locale') &&
  625. is_readable(SM_PATH . 'locale')) {
  626. $localedir = dir(SM_PATH . 'locale');
  627. while($lang_dir=$localedir->read()) {
  628. // remove trailing slash, if present
  629. if (substr($lang_dir,-1)=='/') {
  630. $lang_dir = substr($lang_dir,0,-1);
  631. }
  632. if ($lang_dir != '..' && $lang_dir != '.' && $lang_dir != 'CVS' &&
  633. is_dir(SM_PATH.'locale/'.$lang_dir) &&
  634. file_exists(SM_PATH.'locale/'.$lang_dir.'/setup.php')) {
  635. include_once(SM_PATH.'locale/'.$lang_dir.'/setup.php');
  636. }
  637. }
  638. $localedir->close();
  639. }
  640. /* Detect whether gettext is installed. */
  641. $gettext_flags = 0;
  642. if (function_exists('_')) {
  643. $gettext_flags += 1;
  644. }
  645. if (function_exists('bindtextdomain')) {
  646. $gettext_flags += 2;
  647. }
  648. if (function_exists('textdomain')) {
  649. $gettext_flags += 4;
  650. }
  651. if (function_exists('ngettext')) {
  652. $gettext_flags += 8;
  653. }
  654. /* If gettext is fully loaded, cool */
  655. if ($gettext_flags == 15) {
  656. $use_gettext = true;
  657. }
  658. /* If ngettext support is missing, load it */
  659. elseif ($gettext_flags == 7) {
  660. $use_gettext = true;
  661. // load internal ngettext functions
  662. include_once(SM_PATH . 'class/l10n.class.php');
  663. include_once(SM_PATH . 'functions/ngettext.php');
  664. }
  665. /* If we can fake gettext, try that */
  666. elseif ($gettext_flags == 0) {
  667. $use_gettext = true;
  668. include_once(SM_PATH . 'functions/gettext.php');
  669. } else {
  670. /* Uh-ho. A weird install */
  671. if (! $gettext_flags & 1) {
  672. /**
  673. * Function is used as replacement in broken installs
  674. * @ignore
  675. */
  676. function _($str) {
  677. return $str;
  678. }
  679. }
  680. if (! $gettext_flags & 2) {
  681. /**
  682. * Function is used as replacement in broken installs
  683. * @ignore
  684. */
  685. function bindtextdomain() {
  686. return;
  687. }
  688. }
  689. if (! $gettext_flags & 4) {
  690. /**
  691. * Function is used as replacemet in broken installs
  692. * @ignore
  693. */
  694. function textdomain() {
  695. return;
  696. }
  697. }
  698. if (! $gettext_flags & 8) {
  699. /**
  700. * Function is used as replacemet in broken installs
  701. * @ignore
  702. */
  703. function ngettext($str,$str2,$number) {
  704. if ($number>1) {
  705. return $str2;
  706. } else {
  707. return $str;
  708. }
  709. }
  710. }
  711. if (! function_exists('dgettext')) {
  712. /**
  713. * Replacement for broken setups.
  714. * @ignore
  715. */
  716. function dgettext($domain,$str) {
  717. return $str;
  718. }
  719. }
  720. if (! function_exists('dngettext')) {
  721. /**
  722. * Replacement for broken setups
  723. * @ignore
  724. */
  725. function dngettext($domain,$str1,$strn,$number) {
  726. return ($number==1 ? $str1 : $strn);
  727. }
  728. }
  729. }
  730. ?>