From 3b84e1b10d0800d858a68283bce298d15677ce58 Mon Sep 17 00:00:00 2001 From: tokul Date: Mon, 4 Oct 2004 14:14:48 +0000 Subject: [PATCH] changing SM internal gettext functions to use php-gettext classes. Fix for bug. 1019007. git-svn-id: https://svn.code.sf.net/p/squirrelmail/code/trunk/squirrelmail@8138 7612ce4b-ef26-0410-bec9-ea0150e637f0 --- functions/gettext.php | 224 ++++------------------------------------- functions/i18n.php | 209 ++++++++++++++++++++++++-------------- functions/ngettext.php | 34 +++++++ 3 files changed, 192 insertions(+), 275 deletions(-) create mode 100644 functions/ngettext.php diff --git a/functions/gettext.php b/functions/gettext.php index f11f13f4..4295a68b 100644 --- a/functions/gettext.php +++ b/functions/gettext.php @@ -2,16 +2,11 @@ /** * SquirrelMail internal gettext functions * - * Copyright (c) 1999-2004 The SquirrelMail Project Team - * Licensed under the GNU GPL. For full terms see the file COPYING. - * - * Alternate to the system's built-in gettext. - * relies on .po files (can't read .mo easily). - * Uses the session for caching (speed increase) - * Possible use in other PHP scripts? The only SM-specific thing is - * $sm_language, I think - * + * Uses php-gettext classes + * @copyright (c) 1999-2004 The SquirrelMail Project Team + * @license http://opensource.org/licenses/gpl-license.php GNU Public Licens * @link http://www.php.net/gettext Original php gettext manual + * @link http://savannah.nongnu.org/projects/php-gettext php-gettext classes * @version $Id$ * @package squirrelmail * @subpackage i18n @@ -20,135 +15,9 @@ /** Almost everything requires global.php... */ require_once(SM_PATH . 'functions/global.php'); -global $gettext_php_domain, $gettext_php_dir, $gettext_php_loaded, - $gettext_php_translateStrings, $gettext_php_loaded_language, - $gettext_php_short_circuit; - -if (! isset($gettext_php_loaded)) { - $gettext_php_loaded = false; - sqsession_register($gettext_php_loaded, 'gettext_php_loaded'); -} -if (! isset($gettext_php_domain)) { - $gettext_php_domain = ''; - sqsession_register($gettext_php_domain, 'gettext_php_domain'); -} -if (! isset($gettext_php_dir)) { - $gettext_php_dir = ''; - sqsession_register($gettext_php_dir, 'gettext_php_dir'); -} -if (! isset($gettext_php_translateStrings)) { - $gettext_php_translateStrings = array(); - sqsession_register($gettext_php_translateStrings, 'gettext_php_translateStrings'); -} -if (! isset($gettext_php_loaded_language)) { - $gettext_php_loaded_language = ''; - sqsession_register($gettext_php_loaded_language, 'gettext_php_loaded_language'); -} -if (! isset($gettext_php_short_circuit)) { - $gettext_php_short_circuit = false; - sqsession_register($gettext_php_short_circuit, 'gettext_php_short_circuit'); -} - -/** - * Converts .po file into array and stores it in session. - * - * Used internally by _($str) function - * - * @internal function is used internally by functions/gettext.php code - */ -function gettext_php_load_strings() { - global $squirrelmail_language, $gettext_php_translateStrings, - $gettext_php_domain, $gettext_php_dir, $gettext_php_loaded, - $gettext_php_loaded_language, $gettext_php_short_circuit; - - /* - * $squirrelmail_language gives 'en' for English, 'de' for German, - * etc. I didn't wanna use getenv or similar, but you easily could - * change my code to do that. - */ - - $gettext_php_translateStrings = array(); - - $gettext_php_short_circuit = false; /* initialization */ - - $filename = $gettext_php_dir; - if (substr($filename, -1) != '/') - $filename .= '/'; - $filename .= $squirrelmail_language . '/LC_MESSAGES/' . - $gettext_php_domain . '.po'; - - $file = @fopen($filename, 'r'); - if ($file == false) { - /* Uh-ho -- we can't load the file. Just fake it. :-) - This is also for English, which doesn't use translations */ - $gettext_php_loaded = true; - $gettext_php_loaded_language = $squirrelmail_language; - /* Avoid fuzzy matching when we didn't load strings */ - $gettext_php_short_circuit = true; - return; - } - - $key = ''; - $SkipRead = false; - while (! feof($file)) { - if (! $SkipRead) { - $line = trim(fgets($file, 4096)); - } else { - $SkipRead = false; - } - - if (ereg('^msgid "(.*)"$', $line, $match)) { - if ($match[1] == '') { - /* - * Potential multi-line - * msgid "" - * "string string " - * "string string" - */ - $key = ''; - $line = trim(fgets($file, 4096)); - while (ereg('^[ ]*"(.*)"[ ]*$', $line, $match)) { - $key .= $match[1]; - $line = trim(fgets($file, 4096)); - } - $SkipRead = true; - } else { - /* msgid "string string" */ - $key = $match[1]; - } - } elseif (ereg('^msgstr "(.*)"$', $line, $match)) { - if ($match[1] == '') { - /* - * Potential multi-line - * msgstr "" - * "string string " - * "string string" - */ - $gettext_php_translateStrings[$key] = ''; - $line = trim(fgets($file, 4096)); - while (ereg('^[ ]*"(.*)"[ ]*$', $line, $match)) { - $gettext_php_translateStrings[$key] .= $match[1]; - $line = trim(fgets($file, 4096)); - } - $SkipRead = true; - } else { - /* msgstr "string string" */ - $gettext_php_translateStrings[$key] = $match[1]; - } - $gettext_php_translateStrings[$key] = - stripslashes($gettext_php_translateStrings[$key]); - /* If there is no translation, just use the untranslated string */ - if ($gettext_php_translateStrings[$key] == '') { - $gettext_php_translateStrings[$key] = $key; - } - $key = ''; - } - } - fclose($file); - - $gettext_php_loaded = true; - $gettext_php_loaded_language = $squirrelmail_language; -} +/** Load classes and other functions */ +include_once(SM_PATH . 'class/l10n.class.php'); +include_once(SM_PATH . 'functions/ngettext.php'); /** * Alternative php gettext function (short form) @@ -159,49 +28,9 @@ function gettext_php_load_strings() { * @return string translated string */ function _($str) { - global $gettext_php_loaded, $gettext_php_translateStrings, - $squirrelmail_language, $gettext_php_loaded_language, - $gettext_php_short_circuit; - - if (! $gettext_php_loaded || - $gettext_php_loaded_language != $squirrelmail_language) { - gettext_php_load_strings(); - } - - /* Try finding the exact string */ - if (isset($gettext_php_translateStrings[$str])) { - return $gettext_php_translateStrings[$str]; - } - - /* See if we should short-circuit */ - if ($gettext_php_short_circuit) { - $gettext_php_translateStrings[$str] = $str; - return $str; - } - - /* Look for a string that is very close to the one we want - Very computationally expensive */ - $oldPercent = 0; - $oldStr = ''; - $newPercent = 0; - foreach ($gettext_php_translateStrings as $k => $v) { - similar_text($str, $k, $newPercent); - if ($newPercent > $oldPercent) { - $oldStr = $v; - $oldPercent = $newPercent; - } - } - /* Require 80% match or better - Adjust to suit your needs */ - if ($oldPercent > 80) { - /* Remember this so we don't need to search again */ - $gettext_php_translateStrings[$str] = $oldStr; - return $oldStr; - } - - /* Remember this so we don't need to search again */ - $gettext_php_translateStrings[$str] = $str; - return $str; + global $l10n, $gettext_domain; + if ($l10n[$gettext_domain]->error==1) return $str; + return $l10n[$gettext_domain]->translate($str); } /** @@ -210,22 +39,18 @@ function _($str) { * Sets path to directory containing domain translations * * @link http://www.php.net/function.bindtextdomain - * @param string $name gettext domain name + * @param string $domain gettext domain name * @param string $dir directory that contains all translations * @return string path to translation directory */ -function bindtextdomain($name, $dir) { - global $gettext_php_domain, $gettext_php_dir, $gettext_php_loaded; - - if ($gettext_php_domain != $name) { - $gettext_php_domain = $name; - $gettext_php_loaded = false; - } - if ($gettext_php_dir != $dir) { - $gettext_php_dir = $dir; - $gettext_php_loaded = false; - } - +function bindtextdomain($domain, $dir) { + global $l10n, $sm_notAlias; + if (substr($dir, -1) != '/') $dir .= '/'; + $mofile=$dir . $sm_notAlias . '/LC_MESSAGES/' . $domain . '.mo'; + + $input = new FileReader($mofile); + $l10n[$domain] = new gettext_reader($input); + return $dir; } @@ -239,13 +64,8 @@ function bindtextdomain($name, $dir) { * @return string gettext domain name */ function textdomain($name = false) { - global $gettext_php_domain, $gettext_php_loaded; - - if ($name != false && $gettext_php_domain != $name) { - $gettext_php_domain = $name; - $gettext_php_loaded = false; - } - - return $gettext_php_domain; + global $gettext_domain; + if ($name) $gettext_domain=$name; + return $gettext_domain; } ?> \ No newline at end of file diff --git a/functions/i18n.php b/functions/i18n.php index 6f604a3f..ef58e18f 100644 --- a/functions/i18n.php +++ b/functions/i18n.php @@ -20,6 +20,44 @@ /** Everything uses global.php... */ require_once(SM_PATH . 'functions/global.php'); +/** + * Gettext bindtextdomain wrapper. + * + * Wrapper solves differences between php versions in order to provide + * ngettext support. Should be used if translation uses ngettext + * functions. + * @param string $domain gettext domain name + * @param string $dir directory that contains all translations + * @return string path to translation directory + */ +function sq_bindtextdomain($domain,$dir) { + global $l10n, $gettext_flags, $sm_notAlias; + + if ($gettext_flags==7) { + // gettext extension without ngettext + if (substr($dir, -1) != '/') $dir .= '/'; + $mofile=$dir . $sm_notAlias . '/LC_MESSAGES/' . $domain . '.mo'; + $input = new FileReader($mofile); + $l10n[$domain] = new gettext_reader($input); + } + + $dir=bindtextdomain($domain,$dir); + + return $dir; +} + +/** + * Gettext textdomain wrapper. + * Makes sure that gettext_domain global is modified. + * @param string $name gettext domain name + * @return string gettext domain name + */ +function sq_textdomain($domain) { + global $gettext_domain; + $gettext_domain=textdomain($domain); + return $gettext_domain; +} + /** * Converts string from given charset to charset, that can be displayed by user translation. * @@ -49,17 +87,17 @@ function charset_decode ($charset, $string) { // Variables that allow to use functions without function_exist() calls if (! isset($use_php_recode) || $use_php_recode=="" ) { - $use_php_recode=false; } + $use_php_recode=false; } if (! isset($use_php_iconv) || $use_php_iconv=="" ) { - $use_php_iconv=false; } + $use_php_iconv=false; } // Don't do conversion if charset is the same. if ( $charset == strtolower($default_charset) ) - return htmlspecialchars($string); + return htmlspecialchars($string); // catch iso-8859-8-i thing if ( $charset == "iso-8859-8-i" ) - $charset = "iso-8859-8"; + $charset = "iso-8859-8"; /* * Recode converts html special characters automatically if you use @@ -67,23 +105,23 @@ function charset_decode ($charset, $string) { * into php recode function call. */ if ( $use_php_recode ) { - if ( $default_charset == "utf-8" ) { - // other charsets can be converted to utf-8 without loss. - // and output string is smaller - $string = recode_string($charset . "..utf-8",$string); - return htmlspecialchars($string); - } else { - $string = recode_string($charset . "..html",$string); - // recode does not convert single quote, htmlspecialchars does. - $string = str_replace("'", ''', $string); - return $string; - } + if ( $default_charset == "utf-8" ) { + // other charsets can be converted to utf-8 without loss. + // and output string is smaller + $string = recode_string($charset . "..utf-8",$string); + return htmlspecialchars($string); + } else { + $string = recode_string($charset . "..html",$string); + // recode does not convert single quote, htmlspecialchars does. + $string = str_replace("'", ''', $string); + return $string; + } } // iconv functions does not have html target and can be used only with utf-8 if ( $use_php_iconv && $default_charset=='utf-8') { - $string = iconv($charset,$default_charset,$string); - return htmlspecialchars($string); + $string = iconv($charset,$default_charset,$string); + return htmlspecialchars($string); } // If we don't use recode and iconv, we'll do it old way. @@ -94,15 +132,15 @@ function charset_decode ($charset, $string) { /* controls cpu and memory intensive decoding cycles */ if (! isset($aggressive_decoding) || $aggressive_decoding=="" ) { - $aggressive_decoding=false; } + $aggressive_decoding=false; } $decode=fixcharset($charset); $decodefile=SM_PATH . 'functions/decode/' . $decode . '.php'; if (file_exists($decodefile)) { - include_once($decodefile); - $ret = call_user_func('charset_decode_'.$decode, $string); + include_once($decodefile); + $ret = call_user_func('charset_decode_'.$decode, $string); } else { - $ret = $string; + $ret = $string; } return( $ret ); } @@ -115,23 +153,23 @@ function charset_decode ($charset, $string) { * @param string */ function charset_encode($string,$charset,$htmlencode=true) { - global $default_charset; + global $default_charset; - // Undo html special chars - if (! $htmlencode ) { - $string = str_replace(array('&','>','<','"'),array('&','>','<','"'),$string); - } + // Undo html special chars + if (! $htmlencode ) { + $string = str_replace(array('&','>','<','"'),array('&','>','<','"'),$string); + } - $encode=fixcharset($charset); - $encodefile=SM_PATH . 'functions/encode/' . $encode . '.php'; - if (file_exists($encodefile)) { - include_once($encodefile); - $ret = call_user_func('charset_encode_'.$encode, $string); - } else { - include_once(SM_PATH . 'functions/encode/us_ascii.php'); - $ret = charset_encode_us_ascii($string); - } - return( $ret ); + $encode=fixcharset($charset); + $encodefile=SM_PATH . 'functions/encode/' . $encode . '.php'; + if (file_exists($encodefile)) { + include_once($encodefile); + $ret = call_user_func('charset_encode_'.$encode, $string); + } else { + include_once(SM_PATH . 'functions/encode/us_ascii.php'); + $ret = charset_encode_us_ascii($string); + } + return( $ret ); } /** @@ -220,7 +258,7 @@ function set_up_language($sm_language, $do_search = false, $default = false) { // System reverts to English translation if user prefs contain translation // that is not available in $languages array if (!isset($languages[$sm_notAlias])) { - $sm_notAlias="en_US"; + $sm_notAlias="en_US"; } while (isset($languages[$sm_notAlias]['ALIAS'])) { @@ -231,19 +269,19 @@ function set_up_language($sm_language, $do_search = false, $default = false) { $use_gettext && $sm_language != '' && isset($languages[$sm_notAlias]['CHARSET']) ) { - bindtextdomain( 'squirrelmail', SM_PATH . 'locale/' ); - textdomain( 'squirrelmail' ); + sq_bindtextdomain( 'squirrelmail', SM_PATH . 'locale/' ); + sq_textdomain( 'squirrelmail' ); if (function_exists('bind_textdomain_codeset')) { - if ($sm_notAlias == 'ja_JP') { - bind_textdomain_codeset ("squirrelmail", 'EUC-JP'); + if ($sm_notAlias == 'ja_JP') { + bind_textdomain_codeset ("squirrelmail", 'EUC-JP'); } else { - bind_textdomain_codeset ("squirrelmail", $languages[$sm_notAlias]['CHARSET'] ); + bind_textdomain_codeset ("squirrelmail", $languages[$sm_notAlias]['CHARSET'] ); } } if (isset($languages[$sm_notAlias]['LOCALE'])){ - $longlocale=$languages[$sm_notAlias]['LOCALE']; + $longlocale=$languages[$sm_notAlias]['LOCALE']; } else { - $longlocale=$sm_notAlias; + $longlocale=$sm_notAlias; } if ( !ini_get('safe_mode') && getenv( 'LC_ALL' ) != $longlocale ) { @@ -258,40 +296,40 @@ function set_up_language($sm_language, $do_search = false, $default = false) { // Set text direction/alignment variables if (isset($languages[$sm_notAlias]['DIR']) && $languages[$sm_notAlias]['DIR'] == 'rtl') { - /** - * Text direction - * @global string $text_direction - */ - $text_direction='rtl'; - /** - * Left alignment - * @global string $left_align - */ - $left_align='right'; - /** - * Right alignment - * @global string $right_align - */ - $right_align='left'; + /** + * Text direction + * @global string $text_direction + */ + $text_direction='rtl'; + /** + * Left alignment + * @global string $left_align + */ + $left_align='right'; + /** + * Right alignment + * @global string $right_align + */ + $right_align='left'; } else { - $text_direction='ltr'; - $left_align='left'; - $right_align='right'; + $text_direction='ltr'; + $left_align='left'; + $right_align='right'; } $squirrelmail_language = $sm_notAlias; if ($squirrelmail_language == 'ja_JP') { header ('Content-Type: text/html; charset=EUC-JP'); if (!function_exists('mb_internal_encoding')) { - // Error messages can't be displayed here - $error = 1; - // Revert to English if possible. - if (function_exists('setPref') && $username!='' && $data_dir!="") { - setPref($data_dir, $username, 'language', "en_US"); - $error = 2; - } - // stop further execution in order not to get php errors on mb_internal_encoding(). - return $error; + // Error messages can't be displayed here + $error = 1; + // Revert to English if possible. + if (function_exists('setPref') && $username!='' && $data_dir!="") { + setPref($data_dir, $username, 'language', "en_US"); + $error = 2; + } + // stop further execution in order not to get php errors on mb_internal_encoding(). + return $error; } if (function_exists('mb_language')) { mb_language('Japanese'); @@ -331,7 +369,7 @@ function set_my_charset(){ } // Catch removed translation if (!isset($languages[$my_language])) { - $my_language="en_US"; + $my_language="en_US"; } while (isset($languages[$my_language]['ALIAS'])) { $my_language = $languages[$my_language]['ALIAS']; @@ -652,11 +690,23 @@ if (function_exists('bindtextdomain')) { if (function_exists('textdomain')) { $gettext_flags += 4; } +if (function_exists('ngettext')) { + $gettext_flags += 8; +} /* If gettext is fully loaded, cool */ -if ($gettext_flags == 7) { +if ($gettext_flags == 15) { $use_gettext = true; } + +/* If ngettext support is missing, load it */ +elseif ($gettext_flags == 7) { + $use_gettext = true; + // load internal ngettext functions + include_once(SM_PATH . 'class/l10n.class.php'); + include_once(SM_PATH . 'functions/ngettext.php'); +} + /* If we can fake gettext, try that */ elseif ($gettext_flags == 0) { $use_gettext = true; @@ -690,6 +740,19 @@ elseif ($gettext_flags == 0) { return; } } + if (! $gettext_flags & 8) { + /** + * Function is used as replacemet in broken installs + * @ignore + */ + function ngettext($str,$str2,$number) { + if ($number>1) { + return $str2; + } else { + return $str; + } + } + } } diff --git a/functions/ngettext.php b/functions/ngettext.php new file mode 100644 index 00000000..bcf690cd --- /dev/null +++ b/functions/ngettext.php @@ -0,0 +1,34 @@ +error==1) return $single; + return $l10n[$gettext_domain]->ngettext($single, $plural, $number); +} +?> \ No newline at end of file -- 2.25.1