Source for file i18n.php

Documentation is available at i18n.php

  1. <?php
  2.  
  3. /**
  4.  * SquirrelMail internationalization functions
  5.  *
  6.  * This file contains variuos functions that are needed to do
  7.  * internationalization of SquirrelMail.
  8.  *
  9.  * Internally the output character set is used. Other characters are
  10.  * encoded using Unicode entities according to HTML 4.0.
  11.  *
  12.  * @copyright &copy; 1999-2006 The SquirrelMail Project Team
  13.  * @license http://opensource.org/licenses/gpl-license.php GNU Public License
  14.  * @version $Id: i18n.php,v 1.129.2.49 2006/04/30 04:49:34 tokul Exp $
  15.  * @package squirrelmail
  16.  * @subpackage i18n
  17.  */
  18.  
  19. /** @ignore */
  20. if (!defined('SM_PATH')) define('SM_PATH','../');
  21.  
  22. /** Everything uses global.php... */
  23. require_once(SM_PATH . 'functions/global.php');
  24.  
  25. /**
  26.  * php setlocale function wrapper
  27.  *
  28.  * From php 4.3.0 it is possible to use arrays in order to set locale.
  29.  * php gettext extension works only when locale is set. This wrapper
  30.  * function allows to use more than one locale name.
  31.  *
  32.  * @param int $category locale category name. Use php named constants
  33.  *      (LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, LC_NUMERIC, LC_TIME)
  34.  * @param mixed $locale option contains array with possible locales or string with one locale
  35.  * @return string name of set locale or false, if all locales fail.
  36.  * @since 1.5.1 and 1.4.5
  37.  * @see http://www.php.net/setlocale
  38.  */
  39. function sq_setlocale($category,$locale) {
  40.     if (is_string($locale)) {
  41.         // string with only one locale
  42.         $ret = setlocale($category,$locale);
  43.     } elseif (! check_php_version(4,3)) {
  44.         // older php version (second setlocale argument must be string)
  45.         $ret=false;
  46.         $index=0;
  47.         while ( ! $ret && $index<count($locale)) {
  48.             $ret=setlocale($category,$locale[$index]);
  49.             $index++;
  50.         }
  51.     } else {
  52.         // php 4.3.0 or better, use entire array
  53.         $ret=setlocale($category,$locale);
  54.     }
  55.  
  56.     /* safety checks */
  57.     if (preg_match("/^.*\/.*\/.*\/.*\/.*\/.*$/",$ret)) {
  58.         /**
  59.          * Welcome to We-Don't-Follow-Own-Fine-Manual department
  60.          * OpenBSD 3.8, 3.9-current and maybe later versions 
  61.          * return invalid response to setlocale command.
  62.          * SM bug report #1427512.
  63.          */
  64.         $ret = false;
  65.     }
  66.     return $ret;
  67. }
  68.  
  69. /**
  70.  * Converts string from given charset to charset, that can be displayed by user translation.
  71.  *
  72.  * Function by default returns html encoded strings, if translation uses different encoding.
  73.  * If Japanese translation is used - function returns string converted to euc-jp
  74.  * If $charset is not supported - function returns unconverted string.
  75.  *
  76.  * sanitizing of html tags is also done by this function.
  77.  *
  78.  * @param string $charset 
  79.  * @param string $string Text to be decoded
  80.  * @param boolean $force_decode converts string to html without $charset!=$default_charset check.
  81.  *  Argument is available since 1.5.1 and 1.4.5.
  82.  * @param boolean $save_html disables htmlspecialchars() in order to preserve
  83.  *   html formating. Use with care. Available since 1.5.1 and 1.4.6
  84.  * @return string decoded string
  85.  */
  86. function charset_decode ($charset, $string, $force_decode=false, $save_html=false) {
  87.     global $languages, $squirrelmail_language, $default_charset;
  88.  
  89.     if (isset($languages[$squirrelmail_language]['XTRA_CODE']) &&
  90.         function_exists($languages[$squirrelmail_language]['XTRA_CODE'])) {
  91.         $string = $languages[$squirrelmail_language]['XTRA_CODE']('decode', $string);
  92.     }
  93.  
  94.     /* All HTML special characters are 7 bit and can be replaced first */
  95.     if (! $save_html) $string = htmlspecialchars ($string);
  96.     $charset = strtolower($charset);
  97.  
  98.     set_my_charset() ;
  99.  
  100.     // Don't do conversion if charset is the same.
  101.     if ( ! $force_decode && $charset == strtolower($default_charset) )
  102.         return $string;
  103.  
  104.     /* controls cpu and memory intensive decoding cycles */
  105.     global $aggressive_decoding;
  106.     $aggressive_decoding = false;
  107.  
  108.     $decode=fixcharset($charset);
  109.     $decodefile=SM_PATH . 'functions/decode/' . $decode . '.php';
  110.     if (file_exists($decodefile)) {
  111.       include_once($decodefile);
  112.       $ret = call_user_func('charset_decode_'.$decode, $string, $save_html);
  113.     } else {
  114.       $ret = $string;
  115.     }
  116.  
  117.     return( $ret );
  118. }
  119.  
  120. /**
  121.  * Converts html string to given charset
  122.  * @since 1.4.4 and 1.5.1
  123.  * @param string $string 
  124.  * @param string $charset 
  125.  * @param boolean $htmlencode keep htmlspecialchars encoding
  126.  * @param string 
  127.  */
  128. function charset_encode($string,$charset,$htmlencode=true) {
  129.     global $default_charset;
  130.  
  131.     $encode=fixcharset($charset);
  132.     $encodefile=SM_PATH . 'functions/encode/' . $encode . '.php';
  133.     if (file_exists($encodefile)) {
  134.         include_once($encodefile);
  135.         $ret = call_user_func('charset_encode_'.$encode, $string);
  136.     } elseif(file_exists(SM_PATH . 'functions/encode/us_ascii.php')) {
  137.         // function replaces all 8bit html entities with question marks.
  138.         // it is used when other encoding functions are unavailable
  139.         include_once(SM_PATH . 'functions/encode/us_ascii.php');
  140.         $ret = charset_encode_us_ascii($string);
  141.     } else {
  142.         /**
  143.          * fix for yahoo users that remove all us-ascii related things
  144.          */
  145.         $ret = $string;
  146.     }
  147.  
  148.     /**
  149.      * Undo html special chars, some places (like compose form) have
  150.      * own sanitizing functions and don't need html symbols.
  151.      * Undo chars only after encoding in order to prevent conversion of 
  152.      * html entities in plain text emails.
  153.      */
  154.     if (! $htmlencode ) {
  155.         $ret = str_replace(array('&amp;','&gt;','&lt;','&quot;'),array('&','>','<','"'),$ret);
  156.     }
  157.  
  158.     return( $ret );
  159. }
  160.  
  161. /**
  162.  * Combined decoding and encoding functions
  163.  *
  164.  * If conversion is done to charset different that utf-8, unsupported symbols
  165.  * will be replaced with question marks.
  166.  * @since 1.4.4 and 1.5.1
  167.  * @param string $in_charset initial charset
  168.  * @param string $string string that has to be converted
  169.  * @param string $out_charset final charset
  170.  * @param boolean $htmlencode keep htmlspecialchars encoding
  171.  * @return string converted string
  172.  */
  173. function charset_convert($in_charset,$string,$out_charset,$htmlencode=true) {
  174.     $string=charset_decode($in_charset,$string,true);
  175.     $string=charset_encode($string,$out_charset,$htmlencode);
  176.     return $string;
  177. }
  178.  
  179. /**
  180.  * Makes charset name suitable for decoding cycles
  181.  *
  182.  * ks_c_5601_1987, x-euc-* and x-windows-* charsets are supported
  183.  * since 1.5.1/1.4.6
  184.  * @param string $charset Name of charset
  185.  * @return string $charset Adjusted name of charset
  186.  * @since 1.5.1 and 1.4.4
  187.  */
  188. function fixcharset($charset) {
  189.     /* remove minus and characters that might be used in paths from charset
  190.      * name in order to be able to use it in function names and include calls.
  191.      */
  192.     $charset=preg_replace("/[-:.\/\\\]/",'_',$charset);
  193.  
  194.     // OE ks_c_5601_1987 > cp949 
  195.     $charset=str_replace('ks_c_5601_1987','cp949',$charset);
  196.     // Moz x-euc-tw > euc-tw
  197.     $charset=str_replace('x_euc','euc',$charset);
  198.     // Moz x-windows-949 > cp949
  199.     $charset=str_replace('x_windows_','cp',$charset);
  200.     // windows-125x and cp125x charsets
  201.     $charset=str_replace('windows_','cp',$charset);
  202.  
  203.     // ibm > cp
  204.     $charset=str_replace('ibm','cp',$charset);
  205.  
  206.     // iso-8859-8-i -> iso-8859-8
  207.     // use same cycle until I'll find differences
  208.     $charset=str_replace('iso_8859_8_i','iso_8859_8',$charset);
  209.  
  210.     return $charset;
  211. }
  212.  
  213. /*
  214.  * Set up the language to be output
  215.  * if $do_search is true, then scan the browser information
  216.  * for a possible language that we know
  217.  */
  218. function set_up_language($sm_language, $do_search = false, $default = false) {
  219.  
  220.     static $SetupAlready = 0;
  221.     global $use_gettext, $languages,
  222.            $squirrelmail_language, $squirrelmail_default_language, 
  223.            $default_charset, $sm_notAlias;
  224.  
  225.     if ($SetupAlready) {
  226.         return;
  227.     }
  228.  
  229.     $SetupAlready = TRUE;
  230.     sqgetGlobalVar('HTTP_ACCEPT_LANGUAGE',  $accept_lang, SQ_SERVER);
  231.  
  232.     /**
  233.      * detect preferred language from header when SquirrelMail asks for
  234.      * it or when default language is set to empty string.
  235.      */
  236.     if (($do_search || empty($squirrelmail_default_language)) &&
  237.         ! $sm_language &&
  238.         isset($accept_lang)) {
  239.         $sm_language = substr($accept_lang, 0, 2);
  240.     }
  241.  
  242.     /**
  243.      * Use default language when it is not detected or when script
  244.      * asks to use default language.
  245.      */
  246.     if ((!$sm_language||$default) && 
  247.         ! empty($squirrelmail_default_language)) {
  248.         $squirrelmail_language = $squirrelmail_default_language;
  249.         $sm_language = $squirrelmail_default_language;
  250.     }
  251.  
  252.     /** provide failsafe language when detection fails */
  253.     if (! $sm_language) $sm_language='en_US';
  254.  
  255.     $sm_notAlias = $sm_language;
  256.  
  257.     /**
  258.      * Catch removed translation
  259.      * System reverts to English translation if user prefs contain translation
  260.      * that is not available in $languages array
  261.      */
  262.     if (!isset($languages[$sm_notAlias])) {
  263.         $sm_notAlias="en_US";
  264.     }
  265.  
  266.     while (isset($languages[$sm_notAlias]['ALIAS'])) {
  267.         $sm_notAlias = $languages[$sm_notAlias]['ALIAS'];
  268.     }
  269.  
  270.     if ( isset($sm_language) &&
  271.          $use_gettext &&
  272.          $sm_language != '' &&
  273.          isset($languages[$sm_notAlias]['CHARSET']) ) {
  274.         bindtextdomain( 'squirrelmail', SM_PATH . 'locale/' );
  275.         textdomain( 'squirrelmail' );
  276.         if (function_exists('bind_textdomain_codeset')) {
  277.             if ($sm_notAlias == 'ja_JP') {
  278.                 bind_textdomain_codeset ("squirrelmail", 'EUC-JP');
  279.             } else {
  280.                 bind_textdomain_codeset ("squirrelmail", $languages[$sm_notAlias]['CHARSET'] );
  281.             }
  282.         }
  283.  
  284.         // Use LOCALE key, if it is set.
  285.         if (isset($languages[$sm_notAlias]['LOCALE'])){
  286.             $longlocale=$languages[$sm_notAlias]['LOCALE'];
  287.         } else {
  288.             $longlocale=$sm_notAlias;
  289.         }
  290.  
  291.         // try setting locale
  292.         $retlocale=sq_setlocale(LC_ALL, $longlocale);
  293.  
  294.         // check if locale is set and assign that locale to $longlocale
  295.         // in order to use it in putenv calls.
  296.         if (! is_bool($retlocale)) {
  297.             $longlocale=$retlocale;
  298.         } elseif (is_array($longlocale)) {
  299.             // setting of all locales failed.
  300.             // we need string instead of array used in LOCALE key.
  301.             $longlocale=$sm_notAlias;
  302.         }
  303.  
  304.         if ( !((bool)ini_get('safe_mode')) &&
  305.              getenv( 'LC_ALL' ) != $longlocale ) {
  306.             putenv( "LC_ALL=$longlocale" );
  307.             putenv( "LANG=$longlocale" );
  308.             putenv( "LANGUAGE=$longlocale" );
  309.             putenv( "LC_NUMERIC=C" );
  310.             if ($sm_notAlias=='tr_TR') putenv( "LC_CTYPE=C" );
  311.         }
  312.         // Workaround for plugins that use numbers with floating point
  313.         // It might be removed if plugins use correct decimal delimiters
  314.         // according to locale settings.
  315.         setlocale(LC_NUMERIC, 'C');
  316.         // Workaround for specific Turkish strtolower/strtoupper rules.
  317.         // Many functions expect English conversion rules.
  318.         if ($sm_notAlias=='tr_TR') setlocale(LC_CTYPE,'C');
  319.  
  320.         $squirrelmail_language = $sm_notAlias;
  321.         if ($squirrelmail_language == 'ja_JP') {
  322.             header ('Content-Type: text/html; charset=EUC-JP');
  323.             if (!function_exists('mb_internal_encoding')) {
  324.                 echo _("You need to have PHP installed with the multibyte string function enabled (using configure option --enable-mbstring).");
  325.                 // Revert to English link has to be added.
  326.                 // stop further execution in order not to get php errors on mb_internal_encoding().
  327.                 return;
  328.             }
  329.             if (function_exists('mb_language')) {
  330.                 mb_language('Japanese');
  331.             }
  332.             mb_internal_encoding('EUC-JP');
  333.             mb_http_output('pass');
  334.         } elseif ($squirrelmail_language == 'en_US') {
  335.             header( 'Content-Type: text/html; charset=' . $default_charset );
  336.         } else {
  337.             header( 'Content-Type: text/html; charset=' . $languages[$sm_notAlias]['CHARSET'] );
  338.         }
  339.         // mbstring.func_overload<>0 fix. See cvs HEAD comments.
  340.         if ($squirrelmail_language != 'ja_JP' && 
  341.             function_exists('mb_internal_encoding') &&
  342.             check_php_version(4,2,0) &&
  343.             (int)ini_get('mbstring.func_overload')!=0) {
  344.             mb_internal_encoding('pass');
  345.         }
  346.     }
  347. }
  348.  
  349. /**
  350.  * Sets default_charset variable according to the one that is used by user's translations.
  351.  *
  352.  * Function changes global $default_charset variable in order to be sure, that it
  353.  * contains charset used by user's translation. Sanity of $squirrelmail_language
  354.  * and $default_charset combination provided in SquirrelMail config is also tested.
  355.  *
  356.  * There can be a $default_charset setting in the
  357.  * config.php file, but the user may have a different language
  358.  * selected for a user interface. This function checks the
  359.  * language selected by the user and tags the outgoing messages
  360.  * with the appropriate charset corresponding to the language
  361.  * selection. This is "more right" (tm), than just stamping the
  362.  * message blindly with the system-wide $default_charset.
  363.  */
  364. function set_my_charset(){
  365.     global $data_dir, $username, $default_charset, $languages, $squirrelmail_language;
  366.  
  367.     $my_language = getPref($data_dir, $username, 'language');
  368.     if (!$my_language) {
  369.         $my_language = $squirrelmail_language ;
  370.     }
  371.     // Catch removed translation
  372.     if (!isset($languages[$my_language])) {
  373.         $my_language="en_US";
  374.     }
  375.     while (isset($languages[$my_language]['ALIAS'])) {
  376.         $my_language = $languages[$my_language]['ALIAS'];
  377.     }
  378.     $my_charset = $languages[$my_language]['CHARSET'];
  379.     if ($my_language!='en_US') {
  380.         $default_charset = $my_charset;
  381.     }
  382. }
  383.  
  384. /**
  385.  * Function informs if it is safe to convert given charset to the one that is used by user.
  386.  *
  387.  * It is safe to use conversion only if user uses utf-8 encoding and when
  388.  * converted charset is similar to the one that is used by user.
  389.  *
  390.  * @param string $input_charset Charset of text that needs to be converted
  391.  * @return bool is it possible to convert to user's charset
  392.  */
  393. function is_conversion_safe($input_charset) {
  394.     global $languages, $sm_notAlias, $default_charset, $lossy_encoding;
  395.  
  396.     if (isset($lossy_encoding) && $lossy_encoding )
  397.         return true;
  398.  
  399.     // convert to lower case
  400.     $input_charset = strtolower($input_charset);
  401.  
  402.     // Is user's locale Unicode based ?
  403.     if ( $default_charset == "utf-8" ) {
  404.         return true;
  405.     }
  406.  
  407.     // Charsets that are similar
  408.     switch ($default_charset) {
  409.     case "windows-1251":
  410.         if ( $input_charset == "iso-8859-5" ||
  411.            $input_charset == "koi8-r" ||
  412.            $input_charset == "koi8-u" ) {
  413.         return true;
  414.         } else {
  415.             return false;
  416.         }
  417.     case "windows-1257":
  418.         if ( $input_charset == "iso-8859-13" ||
  419.              $input_charset == "iso-8859-4" ) {
  420.             return true;
  421.         } else {
  422.             return false;
  423.         }
  424.     case "iso-8859-4":
  425.         if ( $input_charset == "iso-8859-13" ||
  426.              $input_charset == "windows-1257" ) {
  427.             return true;
  428.         } else {
  429.             return false;
  430.         }
  431.     case "iso-8859-5":
  432.         if ( $input_charset == "windows-1251" ||
  433.              $input_charset == "koi8-r" ||
  434.              $input_charset == "koi8-u" ) {
  435.             return true;
  436.         } else {
  437.             return false;
  438.         }
  439.     case "iso-8859-13":
  440.         if ( $input_charset == "iso-8859-4" ||
  441.              $input_charset == "windows-1257" ) {
  442.             return true;
  443.         } else {
  444.             return false;
  445.         }
  446.     case "koi8-r":
  447.         if ( $input_charset == "windows-1251" ||
  448.              $input_charset == "iso-8859-5" ||
  449.              $input_charset == "koi8-u" ) {
  450.             return true;
  451.         } else {
  452.             return false;
  453.         }
  454.     case "koi8-u":
  455.         if ( $input_charset == "windows-1251" ||
  456.              $input_charset == "iso-8859-5" ||
  457.              $input_charset == "koi8-r" ) {
  458.             return true;
  459.         } else {
  460.             return false;
  461.         }
  462.     default:
  463.         return false;
  464.     }
  465. }
  466.  
  467. /* ---- extra code functions ----*/
  468. /**
  469.  * Japanese charset extra function
  470.  */
  471. function japanese_charset_xtra() {
  472.     $ret = func_get_arg(1);  /* default return value */
  473.     if (function_exists('mb_detect_encoding')) {
  474.         switch (func_get_arg(0)) { /* action */
  475.         case 'decode':
  476.             $detect_encoding = @mb_detect_encoding($ret);
  477.             if ($detect_encoding == 'JIS' ||
  478.                 $detect_encoding == 'EUC-JP' ||
  479.                 $detect_encoding == 'SJIS' ||
  480.                 $detect_encoding == 'UTF-8') {
  481.  
  482.                 $ret = mb_convert_kana(mb_convert_encoding($ret, 'EUC-JP', 'AUTO'), "KV");
  483.             }
  484.             break;
  485.         case 'encode':
  486.             $detect_encoding = @mb_detect_encoding($ret);
  487.             if ($detect_encoding == 'JIS' ||
  488.                 $detect_encoding == 'EUC-JP' ||
  489.                 $detect_encoding == 'SJIS' ||
  490.                 $detect_encoding == 'UTF-8') {
  491.  
  492.                 $ret = mb_convert_encoding(mb_convert_kana($ret, "KV"), 'JIS', 'AUTO');
  493.             }
  494.             break;
  495.         case 'strimwidth':
  496.             $width = func_get_arg(2);
  497.             $ret = mb_strimwidth($ret, 0, $width, '...');
  498.             break;
  499.         case 'encodeheader':
  500.             $result = '';
  501.             if (strlen($ret) > 0) {
  502.                 $tmpstr = mb_substr($ret, 0, 1);
  503.                 $prevcsize = strlen($tmpstr);
  504.                 for ($i = 1; $i < mb_strlen($ret); $i++) {
  505.                     $tmp = mb_substr($ret, $i, 1);
  506.                     if (strlen($tmp) == $prevcsize) {
  507.                         $tmpstr .= $tmp;
  508.                     } else {
  509.                         if ($prevcsize == 1) {
  510.                             $result .= $tmpstr;
  511.                         } else {
  512.                             $result .= str_replace(' ', '',
  513.                                                    mb_encode_mimeheader($tmpstr,'iso-2022-jp','B',''));
  514.                         }
  515.                         $tmpstr = $tmp;
  516.                         $prevcsize = strlen($tmp);
  517.                     }
  518.                 }
  519.                 if (strlen($tmpstr)) {
  520.                     if (strlen(mb_substr($tmpstr, 0, 1)) == 1)
  521.                         $result .= $tmpstr;
  522.                     else
  523.                         $result .= str_replace(' ', '',
  524.                                                mb_encode_mimeheader($tmpstr,'iso-2022-jp','B',''));
  525.                 }
  526.             }
  527.             $ret = $result;
  528.             break;
  529.         case 'decodeheader':
  530.             $ret = str_replace("\t", "", $ret);
  531.             if (eregi('=\\?([^?]+)\\?(q|b)\\?([^?]+)\\?=', $ret))
  532.                 $ret = @mb_decode_mimeheader($ret);
  533.             $ret = @mb_convert_encoding($ret, 'EUC-JP', 'AUTO');
  534.             break;
  535.         case 'downloadfilename':
  536.             $useragent = func_get_arg(2);
  537.             if (strstr($useragent, 'Windows') !== false ||
  538.                 strstr($useragent, 'Mac_') !== false) {
  539.                 $ret = mb_convert_encoding($ret, 'SJIS', 'AUTO');
  540.             } else {
  541.                 $ret = mb_convert_encoding($ret, 'EUC-JP', 'AUTO');
  542. }
  543.             break;
  544.         case 'wordwrap':
  545.             $no_begin = "\x21\x25\x29\x2c\x2e\x3a\x3b\x3f\x5d\x7d\xa1\xf1\xa1\xeb\xa1" .
  546.                 "\xc7\xa1\xc9\xa2\xf3\xa1\xec\xa1\xed\xa1\xee\xa1\xa2\xa1\xa3\xa1\xb9" .
  547.                 "\xa1\xd3\xa1\xd5\xa1\xd7\xa1\xd9\xa1\xdb\xa1\xcd\xa4\xa1\xa4\xa3\xa4" .
  548.                 "\xa5\xa4\xa7\xa4\xa9\xa4\xc3\xa4\xe3\xa4\xe5\xa4\xe7\xa4\xee\xa1\xab" .
  549.                 "\xa1\xac\xa1\xb5\xa1\xb6\xa5\xa1\xa5\xa3\xa5\xa5\xa5\xa7\xa5\xa9\xa5" .
  550.                 "\xc3\xa5\xe3\xa5\xe5\xa5\xe7\xa5\xee\xa5\xf5\xa5\xf6\xa1\xa6\xa1\xbc" .
  551.                 "\xa1\xb3\xa1\xb4\xa1\xaa\xa1\xf3\xa1\xcb\xa1\xa4\xa1\xa5\xa1\xa7\xa1" .
  552.                 "\xa8\xa1\xa9\xa1\xcf\xa1\xd1";
  553.             $no_end = "\x5c\x24\x28\x5b\x7b\xa1\xf2\x5c\xa1\xc6\xa1\xc8\xa1\xd2\xa1" .
  554.                 "\xd4\xa1\xd6\xa1\xd8\xa1\xda\xa1\xcc\xa1\xf0\xa1\xca\xa1\xce\xa1\xd0\xa1\xef";
  555.             $wrap = func_get_arg(2);
  556.  
  557.             if (strlen($ret) >= $wrap &&
  558.                 substr($ret, 0, 1) != '>' &&
  559.                 strpos($ret, 'http://') === FALSE &&
  560.                 strpos($ret, 'https://') === FALSE &&
  561.                 strpos($ret, 'ftp://') === FALSE) {
  562.  
  563.                 $ret = mb_convert_kana($ret, "KV");
  564.  
  565.                 $line_new = '';
  566.                 $ptr = 0;
  567.  
  568.                 while ($ptr < strlen($ret) - 1) {
  569.                     $l = mb_strcut($ret, $ptr, $wrap);
  570.                     $ptr += strlen($l);
  571.                     $tmp = $l;
  572.  
  573.                     $l = mb_strcut($ret, $ptr, 2);
  574.                     while (strlen($l) != 0 && mb_strpos($no_begin, $l) !== FALSE ) {
  575.                         $tmp .= $l;
  576.                         $ptr += strlen($l);
  577.                         $l = mb_strcut($ret, $ptr, 1);
  578.                     }
  579.                     $line_new .= $tmp;
  580.                     if ($ptr < strlen($ret) - 1)
  581.                         $line_new .= "\n";
  582.                 }
  583.                 $ret = $line_new;
  584.             }
  585.             break;
  586.         case 'utf7-imap_encode':
  587.             $ret = mb_convert_encoding($ret, 'UTF7-IMAP', 'EUC-JP');
  588.             break;
  589.         case 'utf7-imap_decode':
  590.             $ret = mb_convert_encoding($ret, 'EUC-JP', 'UTF7-IMAP');
  591.             break;
  592.         }
  593.     }
  594.     return $ret;
  595. }
  596.  
  597.  
  598. /*
  599.  * Korean charset extra function
  600.  * Hangul(Korean Character) Attached File Name Fix.
  601.  */
  602. function korean_charset_xtra() {
  603.  
  604.     $ret = func_get_arg(1);  /* default return value */
  605.     if (func_get_arg(0) == 'downloadfilename') { /* action */
  606.         $ret = str_replace("\x0D\x0A", '', $ret);  /* Hanmail's CR/LF Clear */
  607.         for ($i=0;$i<strlen($ret);$i++) {
  608.             if ($ret[$i] >= "\xA1" && $ret[$i] <= "\xFE") {   /* 0xA1 - 0XFE are Valid */
  609.                 $i++;
  610.                 continue;
  611.             } else if (($ret[$i] >= 'a' && $ret[$i] <= 'z') || /* From Original ereg_replace in download.php */
  612.                        ($ret[$i] >= 'A' && $ret[$i] <= 'Z') ||
  613.                        ($ret[$i] == '.') || ($ret[$i] == '-')) {
  614.                 continue;
  615.             } else {
  616.                 $ret[$i] = '_';
  617.             }
  618.         }
  619.  
  620.     }
  621.  
  622.     return $ret;
  623. }
  624.  
  625.  
  626. /* ------------------------------ main --------------------------- */
  627.  
  628. global $squirrelmail_language, $languages, $use_gettext;
  629.  
  630. if (! sqgetGlobalVar('squirrelmail_language',$squirrelmail_language,SQ_COOKIE)) {
  631.     $squirrelmail_language = '';
  632. }
  633.  
  634. /* This array specifies the available languages. */
  635.  
  636. $languages['bg_BG']['NAME']    = 'Bulgarian';
  637. $languages['bg_BG']['CHARSET'] = 'windows-1251';
  638. $languages['bg_BG']['LOCALE']  = 'bg_BG.CP1251';
  639. $languages['bg']['ALIAS']      = 'bg_BG';
  640.  
  641. $languages['bn_IN']['NAME']    = 'Bengali';
  642. $languages['bn_IN']['CHARSET'] = 'utf-8';
  643. $languages['bn_IN']['LOCALE']  = 'bn_IN.UTF-8';
  644. $languages['bn_BD']['ALIAS'] = 'bn_IN';
  645. $languages['bn']['ALIAS'] = 'bn_IN';
  646.  
  647. $languages['ca_ES']['NAME']    = 'Catalan';
  648. $languages['ca_ES']['CHARSET'] = 'iso-8859-1';
  649. $languages['ca_ES']['LOCALE']  = array('ca_ES.ISO8859-1','ca_ES.ISO-8859-1','ca_ES');
  650. $languages['ca']['ALIAS']      = 'ca_ES';
  651.  
  652. $languages['cs_CZ']['NAME']    = 'Czech';
  653. $languages['cs_CZ']['CHARSET'] = 'iso-8859-2';
  654. $languages['cs_CZ']['LOCALE']  = array('cs_CZ.ISO8859-2','cs_CZ.ISO-8859-2','cs_CZ');
  655. $languages['cs']['ALIAS']      = 'cs_CZ';
  656.  
  657. $languages['cy_GB']['NAME']    = 'Welsh';
  658. $languages['cy_GB']['CHARSET'] = 'iso-8859-1';
  659. $languages['cy_GB']['LOCALE']  = array('cy_GB.ISO8859-1','cy_GB.ISO-8859-1','cy_GB');
  660. $languages['cy']['ALIAS'] = 'cy_GB';
  661.  
  662. $languages['da_DK']['NAME']    = 'Danish';
  663. $languages['da_DK']['CHARSET'] = 'iso-8859-1';
  664. $languages['da_DK']['LOCALE']  = array('da_DK.ISO8859-1','da_DK.ISO-8859-1','da_DK');
  665. $languages['da']['ALIAS']      = 'da_DK';
  666.  
  667. $languages['de_DE']['NAME']    = 'Deutsch';
  668. $languages['de_DE']['CHARSET'] = 'iso-8859-1';
  669. $languages['de_DE']['LOCALE']  = array('de_DE.ISO8859-1','de_DE.ISO-8859-1','de_DE');
  670. $languages['de']['ALIAS']      = 'de_DE';
  671.  
  672. $languages['el_GR']['NAME']    = 'Greek';
  673. $languages['el_GR']['CHARSET'] = 'iso-8859-7';
  674. $languages['el_GR']['LOCALE']  = array('el_GR.ISO8859-7','el_GR.ISO-8859-7','el_GR');
  675. $languages['el']['ALIAS']      = 'el_GR';
  676.  
  677. $languages['en_GB']['NAME']    = 'British';
  678. $languages['en_GB']['CHARSET'] = 'iso-8859-15';
  679. $languages['en_GB']['LOCALE']  = array('en_GB.ISO8859-15','en_GB.ISO-8859-15','en_GB');
  680.  
  681. $languages['en_US']['NAME']    = 'English';
  682. $languages['en_US']['CHARSET'] = 'iso-8859-1';
  683. $languages['en_US']['LOCALE']  = 'en_US.ISO8859-1';
  684. $languages['en']['ALIAS']      = 'en_US';
  685.  
  686. $languages['es_ES']['NAME']    = 'Spanish';
  687. $languages['es_ES']['CHARSET'] = 'iso-8859-1';
  688. $languages['es_ES']['LOCALE']  = array('es_ES.ISO8859-1','es_ES.ISO-8859-1','es_ES');
  689. $languages['es']['ALIAS']      = 'es_ES';
  690.  
  691. $languages['et_EE']['NAME']    = 'Estonian';
  692. $languages['et_EE']['CHARSET'] = 'iso-8859-15';
  693. $languages['et_EE']['LOCALE']  = array('et_EE.ISO8859-15','et_EE.ISO-8859-15','et_EE');
  694. $languages['et']['ALIAS']      = 'et_EE';
  695.  
  696. $languages['eu_ES']['NAME']    = 'Basque';
  697. $languages['eu_ES']['CHARSET'] = 'iso-8859-1';
  698. $languages['eu_ES']['LOCALE']  = array('eu_ES.ISO8859-1','eu_ES.ISO-8859-1','eu_ES');
  699. $languages['eu']['ALIAS']      = 'eu_ES';
  700.  
  701. $languages['fi_FI']['NAME']    = 'Finnish';
  702. $languages['fi_FI']['CHARSET'] = 'iso-8859-1';
  703. $languages['fi_FI']['LOCALE']  = array('fi_FI.ISO8859-1','fi_FI.ISO-8859-1','fi_FI');
  704. $languages['fi']['ALIAS']      = 'fi_FI';
  705.  
  706. $languages['fo_FO']['NAME']    = 'Faroese';
  707. $languages['fo_FO']['CHARSET'] = 'iso-8859-1';
  708. $languages['fo_FO']['LOCALE']  = array('fo_FO.ISO8859-1','fo_FO.ISO-8859-1','fo_FO');
  709. $languages['fo']['ALIAS']      = 'fo_FO';
  710.  
  711. $languages['fr_FR']['NAME']    = 'French';
  712. $languages['fr_FR']['CHARSET'] = 'iso-8859-1';
  713. $languages['fr_FR']['LOCALE']  = array('fr_FR.ISO8859-1','fr_FR.ISO-8859-1','fr_FR');
  714. $languages['fr']['ALIAS']      = 'fr_FR';
  715.  
  716. $languages['hr_HR']['NAME']    = 'Croatian';
  717. $languages['hr_HR']['CHARSET'] = 'iso-8859-2';
  718. $languages['hr_HR']['LOCALE']  = array('hr_HR.ISO8859-2','hr_HR.ISO-8859-2','hr_HR');
  719. $languages['hr']['ALIAS']      = 'hr_HR';
  720.  
  721. $languages['hu_HU']['NAME']    = 'Hungarian';
  722. $languages['hu_HU']['CHARSET'] = 'iso-8859-2';
  723. $languages['hu_HU']['LOCALE']  = array('hu_HU.ISO8859-2','hu_HU.ISO-8859-2','hu_HU');
  724. $languages['hu']['ALIAS']      = 'hu_HU';
  725.  
  726. $languages['id_ID']['NAME']    = 'Bahasa Indonesia';
  727. $languages['id_ID']['CHARSET'] = 'iso-8859-1';
  728. $languages['id_ID']['LOCALE']  = array('id_ID.ISO8859-1','id_ID.ISO-8859-1','id_ID');
  729. $languages['id']['ALIAS']      = 'id_ID';
  730.  
  731. $languages['is_IS']['NAME']    = 'Icelandic';
  732. $languages['is_IS']['CHARSET'] = 'iso-8859-1';
  733. $languages['is_IS']['LOCALE']  = array('is_IS.ISO8859-1','is_IS.ISO-8859-1','is_IS');
  734. $languages['is']['ALIAS']      = 'is_IS';
  735.  
  736. $languages['it_IT']['NAME']    = 'Italian';
  737. $languages['it_IT']['CHARSET'] = 'iso-8859-1';
  738. $languages['it_IT']['LOCALE']  = array('it_IT.ISO8859-1','it_IT.ISO-8859-1','it_IT');
  739. $languages['it']['ALIAS']      = 'it_IT';
  740.  
  741. $languages['ja_JP']['NAME']    = 'Japanese';
  742. $languages['ja_JP']['CHARSET'] = 'iso-2022-jp';
  743. $languages['ja_JP']['XTRA_CODE'] = 'japanese_charset_xtra';
  744. $languages['ja']['ALIAS']      = 'ja_JP';
  745.  
  746. $languages['ka']['NAME']       = 'Georgian';
  747. $languages['ka']['CHARSET']    = 'utf-8';
  748. $languages['ka']['LOCALE']     = array('ka_GE.UTF-8','ka_GE','ka');
  749. $languages['ka_GE']['ALIAS']   = 'ka';
  750.  
  751. $languages['ko_KR']['NAME']    = 'Korean';
  752. $languages['ko_KR']['CHARSET'] = 'euc-KR';
  753. // Function does not provide all needed options
  754. // $languages['ko_KR']['XTRA_CODE'] = 'korean_charset_xtra';
  755. $languages['ko']['ALIAS']      = 'ko_KR';
  756.  
  757. $languages['lt_LT']['NAME']    = 'Lithuanian';
  758. $languages['lt_LT']['CHARSET'] = 'utf-8';
  759. $languages['lt_LT']['LOCALE']  = 'lt_LT.UTF-8';
  760. $languages['lt']['ALIAS']      = 'lt_LT';
  761.  
  762. $languages['ms_MY']['NAME']    = 'Bahasa Melayu';
  763. $languages['ms_MY']['CHARSET'] = 'iso-8859-1';
  764. $languages['ms_MY']['LOCALE']  = array('ms_MY.ISO8859-1','ms_MY.ISO-8859-1','ms_MY');
  765. $languages['my']['ALIAS'] = 'ms_MY';
  766.  
  767. $languages['nl_NL']['NAME']    = 'Dutch';
  768. $languages['nl_NL']['CHARSET'] = 'iso-8859-1';
  769. $languages['nl_NL']['LOCALE']  = array('nl_NL.ISO8859-1','nl_NL.ISO-8859-1','nl_NL');
  770. $languages['nl']['ALIAS']      = 'nl_NL';
  771.  
  772. $languages['nb_NO']['NAME']    = 'Norwegian (Bokm&aring;l)';
  773. $languages['nb_NO']['CHARSET'] = 'iso-8859-1';
  774. $languages['nb_NO']['LOCALE']  = array('nb_NO.ISO8859-1','nb_NO.ISO-8859-1','nb_NO');
  775. $languages['nb']['ALIAS']      = 'nb_NO';
  776.  
  777. $languages['nn_NO']['NAME']    = 'Norwegian (Nynorsk)';
  778. $languages['nn_NO']['CHARSET'] = 'iso-8859-1';
  779. $languages['nn_NO']['LOCALE']  = array('nn_NO.ISO8859-1','nn_NO.ISO-8859-1','nn_NO');
  780.  
  781. $languages['pl_PL']['NAME']    = 'Polish';
  782. $languages['pl_PL']['CHARSET'] = 'iso-8859-2';
  783. $languages['pl_PL']['LOCALE']  = array('pl_PL.ISO8859-2','pl_PL.ISO-8859-2','pl_PL');
  784. $languages['pl']['ALIAS']      = 'pl_PL';
  785.  
  786. $languages['pt_PT']['NAME'] = 'Portuguese (Portugal)';
  787. $languages['pt_PT']['CHARSET'] = 'iso-8859-1';
  788. $languages['pt_PT']['LOCALE']  = array('pt_PT.ISO8859-1','pt_PT.ISO-8859-1','pt_PT');
  789. $languages['pt']['ALIAS']      = 'pt_PT';
  790.  
  791. $languages['pt_BR']['NAME']    = 'Portuguese (Brazil)';
  792. $languages['pt_BR']['CHARSET'] = 'iso-8859-1';
  793. $languages['pt_BR']['LOCALE']  = array('pt_BR.ISO8859-1','pt_BR.ISO-8859-1','pt_BR');
  794.  
  795. $languages['ro_RO']['NAME']    = 'Romanian';
  796. $languages['ro_RO']['CHARSET'] = 'iso-8859-2';
  797. $languages['ro_RO']['LOCALE']  = array('ro_RO.ISO8859-2','ro_RO.ISO-8859-2','ro_RO');
  798. $languages['ro']['ALIAS']      = 'ro_RO';
  799.  
  800. $languages['ru_RU']['NAME']    = 'Russian';
  801. $languages['ru_RU']['CHARSET'] = 'utf-8';
  802. $languages['ru_RU']['LOCALE']  = 'ru_RU.UTF-8';
  803. $languages['ru']['ALIAS']      = 'ru_RU';
  804.  
  805. $languages['sk_SK']['NAME']     = 'Slovak';
  806. $languages['sk_SK']['CHARSET']  = 'iso-8859-2';
  807. $languages['sk_SK']['LOCALE']   = array('sk_SK.ISO8859-2','sk_SK.ISO-8859-2','sk_SK');
  808. $languages['sk']['ALIAS']       = 'sk_SK';
  809.  
  810. $languages['sl_SI']['NAME']    = 'Slovenian';
  811. $languages['sl_SI']['CHARSET'] = 'iso-8859-2';
  812. $languages['sl_SI']['LOCALE']  = array('sl_SI.ISO8859-2','sl_SI.ISO-8859-2','sl_SI');
  813. $languages['sl']['ALIAS']      = 'sl_SI';
  814.  
  815. $languages['sr_YU']['NAME']    = 'Serbian';
  816. $languages['sr_YU']['CHARSET'] = 'iso-8859-2';
  817. $languages['sr_YU']['LOCALE']  = array('sr_YU.ISO8859-2','sr_YU.ISO-8859-2','sr_YU');
  818. $languages['sr']['ALIAS']      = 'sr_YU';
  819.  
  820. $languages['sv_SE']['NAME']    = 'Swedish';
  821. $languages['sv_SE']['CHARSET'] = 'iso-8859-1';
  822. $languages['sv_SE']['LOCALE']  = array('sv_SE.ISO8859-1','sv_SE.ISO-8859-1','sv_SE');
  823. $languages['sv']['ALIAS']      = 'sv_SE';
  824.  
  825. /* translation is disabled because it contains less than 50%
  826.  * translated strings
  827. $languages['th_TH']['NAME']    = 'Thai';
  828. $languages['th_TH']['CHARSET'] = 'tis-620';
  829. $languages['th_TH']['LOCALE']  = 'th_TH.TIS-620';
  830. $languages['th']['ALIAS'] = 'th_TH';
  831. */
  832.  
  833. $languages['tr_TR']['NAME']    = 'Turkish';
  834. $languages['tr_TR']['CHARSET'] = 'iso-8859-9';
  835. $languages['tr_TR']['LOCALE']  = array('tr_TR.ISO8859-9','tr_TR.ISO-8859-9','tr_TR');
  836. $languages['tr']['ALIAS']      = 'tr_TR';
  837.  
  838. $languages['zh_TW']['NAME']    = 'Chinese Trad';
  839. $languages['zh_TW']['CHARSET'] = 'big5';
  840. $languages['zh_TW']['LOCALE']  = 'zh_TW.BIG5';
  841. $languages['tw']['ALIAS']      = 'zh_TW';
  842.  
  843. $languages['zh_CN']['NAME']    = 'Chinese Simp';
  844. $languages['zh_CN']['CHARSET'] = 'gb2312';
  845. $languages['zh_CN']['LOCALE']  = 'zh_CN.GB2312';
  846. $languages['cn']['ALIAS']      = 'zh_CN';
  847.  
  848. $languages['uk_UA']['NAME']    = 'Ukrainian';
  849. $languages['uk_UA']['CHARSET'] = 'utf-8';
  850. $languages['uk_UA']['LOCALE']  = array('uk_UA.UTF-8','uk_UA','uk');
  851. $languages['uk']['ALIAS'] = 'uk_UA';
  852.  
  853. /*
  854. $languages['vi_VN']['NAME']    = 'Vietnamese';
  855. $languages['vi_VN']['CHARSET'] = 'utf-8';
  856. $languages['vi']['ALIAS'] = 'vi_VN';
  857. */
  858.  
  859. // Right to left languages
  860.  
  861. $languages['ar']['NAME']    = 'Arabic';
  862. $languages['ar']['CHARSET'] = 'windows-1256';
  863. $languages['ar']['DIR']     = 'rtl';
  864.  
  865. $languages['fa_IR']['NAME']    = 'Farsi';
  866. $languages['fa_IR']['CHARSET'] = 'utf-8';
  867. $languages['fa_IR']['DIR']     = 'rtl';
  868. $languages['fa_IR']['LOCALE']  = 'fa_IR.UTF-8';
  869. $languages['fa']['ALIAS']      = 'fa_IR';
  870.  
  871. $languages['he_IL']['NAME']    = 'Hebrew';
  872. $languages['he_IL']['CHARSET'] = 'windows-1255';
  873. $languages['he_IL']['DIR']     = 'rtl';
  874. $languages['he']['ALIAS']      = 'he_IL';
  875.  
  876. $languages['ug']['NAME']    = 'Uighur';
  877. $languages['ug']['CHARSET'] = 'utf-8';
  878. $languages['ug']['DIR']     = 'rtl';
  879.  
  880. /* Detect whether gettext is installed. */
  881. $gettext_flags = 0;
  882. if (function_exists('_')) {
  883.     $gettext_flags += 1;
  884. }
  885. if (function_exists('bindtextdomain')) {
  886.     $gettext_flags += 2;
  887. }
  888. if (function_exists('textdomain')) {
  889.     $gettext_flags += 4;
  890. }
  891.  
  892. /* If gettext is fully loaded, cool */
  893. if ($gettext_flags == 7) {
  894.     $use_gettext = true;
  895. }
  896. /* If we can fake gettext, try that */
  897. elseif ($gettext_flags == 0) {
  898.     $use_gettext = true;
  899.     include_once(SM_PATH . 'functions/gettext.php');
  900. } else {
  901.     /* Uh-ho.  A weird install */
  902.     if (! $gettext_flags & 1) {
  903.         function _($str) {
  904.             return $str;
  905.         }
  906.     }
  907.     if (! $gettext_flags & 2) {
  908.         function bindtextdomain() {
  909.             return;
  910.         }
  911.     }
  912.     if (! $gettext_flags & 4) {
  913.         function textdomain() {
  914.             return;
  915.         }
  916.     }
  917. }
  918. ?>

Documentation generated on Sat, 07 Oct 2006 16:31:33 +0300 by phpDocumentor 1.3.0RC6