From: <dai...@us...> - 2011-08-08 10:32:47
|
Revision: 4654 http://web-erp.svn.sourceforge.net/web-erp/?rev=4654&view=rev Author: daintree Date: 2011-08-08 10:32:39 +0000 (Mon, 08 Aug 2011) Log Message: ----------- update php-gettext to latest Modified Paths: -------------- trunk/includes/php-gettext/gettext.inc trunk/includes/php-gettext/gettext.php trunk/includes/php-gettext/streams.php Modified: trunk/includes/php-gettext/gettext.inc =================================================================== --- trunk/includes/php-gettext/gettext.inc 2011-08-07 10:17:52 UTC (rev 4653) +++ trunk/includes/php-gettext/gettext.inc 2011-08-08 10:32:39 UTC (rev 4654) @@ -32,7 +32,6 @@ LC_ALL 6 */ - // LC_MESSAGES is not available if php-gettext is not loaded // while the other constants are already available from session extension. if (!defined('LC_MESSAGES')) { @@ -62,6 +61,56 @@ // Utility functions /** + * Return a list of locales to try for any POSIX-style locale specification. + */ +function get_list_of_locales($locale) { + /* Figure out all possible locale names and start with the most + * specific ones. I.e. for sr_CS.UTF-8@latin, look through all of + * sr_CS.UTF-8@latin, sr_CS@latin, sr@latin, sr_CS.UTF-8, sr_CS, sr. + */ + $locale_names = array(); + $lang = NULL; + $country = NULL; + $charset = NULL; + $modifier = NULL; + if ($locale) { + if (preg_match("/^(?P<lang>[a-z]{2,3})" // language code + ."(?:_(?P<country>[A-Z]{2}))?" // country code + ."(?:\.(?P<charset>[-A-Za-z0-9_]+))?" // charset + ."(?:@(?P<modifier>[-A-Za-z0-9_]+))?$/", // @ modifier + $locale, $matches)) { + + if (isset($matches["lang"])) $lang = $matches["lang"]; + if (isset($matches["country"])) $country = $matches["country"]; + if (isset($matches["charset"])) $charset = $matches["charset"]; + if (isset($matches["modifier"])) $modifier = $matches["modifier"]; + + if ($modifier) { + if ($country) { + if ($charset) + array_push($locale_names, "${lang}_$country.$charset@$modifier"); + array_push($locale_names, "${lang}_$country@$modifier"); + } elseif ($charset) + array_push($locale_names, "${lang}.$charset@$modifier"); + array_push($locale_names, "$lang@$modifier"); + } + if ($country) { + if ($charset) + array_push($locale_names, "${lang}_$country.$charset"); + array_push($locale_names, "${lang}_$country"); + } elseif ($charset) + array_push($locale_names, "${lang}.$charset"); + array_push($locale_names, $lang); + } + + // If the locale name doesn't match POSIX style, just include it as-is. + if (!in_array($locale, $locale_names)) + array_push($locale_names, $locale); + } + return $locale_names; +} + +/** * Utility function to get a StreamReader for the given text domain. */ function _get_reader($domain=null, $category=5, $enable_cache=true) { @@ -73,27 +122,8 @@ $bound_path = isset($text_domains[$domain]->path) ? $text_domains[$domain]->path : './'; $subpath = $LC_CATEGORIES[$category] ."/$domain.mo"; - /* Figure out all possible locale names and start with the most - specific ones. I.e. for sr_CS.UTF-8@latin, look through all of - sr_CS.UTF-8@latin, sr_CS@latin, sr@latin, sr_CS.UTF-8, sr_CS, sr. - */ - $locale_names = array(); - if (preg_match("/([a-z]{2,3})" // language code - ."(_([A-Z]{2}))?" // country code - ."(\.([-A-Za-z0-9_]))?" // charset - ."(@([-A-Za-z0-9_]+))?/", // @ modifier - $locale, $matches)) { - list(,$lang,,$country,,$charset,,$modifier) = $matches; - if ($modifier) { - $locale_names = array("${lang}_$country.$charset@$modifier", - "${lang}_$country@$modifier", - "$lang@$modifier"); - } - array_push($locale_names, - "${lang}_$country.$charset", "${lang}_$country", "$lang"); - } - array_push($locale_names, $locale); + $locale_names = get_list_of_locales($locale); $input = null; foreach ($locale_names as $locale) { $full_path = $bound_path . $locale . "/" . $subpath; @@ -124,8 +154,10 @@ /** * Checks if the current locale is supported on this system. */ -function _check_locale() { +function _check_locale_and_function($function=false) { global $EMULATEGETTEXT; + if ($function and !function_exists($function)) + return false; return !$EMULATEGETTEXT; } @@ -153,11 +185,19 @@ } - - // Custom implementation of the standard gettext related functions /** + * Returns passed in $locale, or environment variable $LANG if $locale == ''. + */ +function _get_default_locale($locale) { + if ($locale == '') // emulate variable support + return getenv('LANG'); + else + return $locale; +} + +/** * Sets a requested locale, if needed emulates it. */ function _setlocale($category, $locale) { @@ -170,22 +210,27 @@ // even if we tried to read locale without setting it first return _setlocale($category, $CURRENTLOCALE); } else { - $ret = 0; - if (function_exists('setlocale')) // I don't know if this ever happens ;) - $ret = setlocale($category, $locale); - if (($ret and $locale == '') or ($ret == $locale)) { + if (function_exists('setlocale')) { + $ret = setlocale($category, $locale); + if (($locale == '' and !$ret) or // failed setting it by env + ($locale != '' and $ret != $locale)) { // failed setting it + // Failed setting it according to environment. + $CURRENTLOCALE = _get_default_locale($locale); + $EMULATEGETTEXT = 1; + } else { + $CURRENTLOCALE = $ret; $EMULATEGETTEXT = 0; - $CURRENTLOCALE = $ret; + } } else { - if ($locale == '') // emulate variable support - $CURRENTLOCALE = getenv('LANG'); - else - $CURRENTLOCALE = $locale; - $EMULATEGETTEXT = 1; + // No function setlocale(), emulate it all. + $CURRENTLOCALE = _get_default_locale($locale); + $EMULATEGETTEXT = 1; } // Allow locale to be changed on the go for one translation domain. global $text_domains, $default_domain; - unset($text_domains[$default_domain]->l10n); + if (array_key_exists($default_domain, $text_domains)) { + unset($text_domains[$default_domain]->l10n); + } return $CURRENTLOCALE; } } @@ -196,11 +241,11 @@ function _bindtextdomain($domain, $path) { global $text_domains; // ensure $path ends with a slash ('/' should work for both, but lets still play nice) - if (mb_substr(php_uname(), 0, 7) == "Windows") { - if ($path[mb_strlen($path)-1] != '\\' and $path[mb_strlen($path)-1] != '/') + if (substr(php_uname(), 0, 7) == "Windows") { + if ($path[strlen($path)-1] != '\\' and $path[strlen($path)-1] != '/') $path .= '\\'; } else { - if ($path[mb_strlen($path)-1] != '/') + if ($path[strlen($path)-1] != '/') $path .= '/'; } if (!array_key_exists($domain, $text_domains)) { @@ -231,22 +276,22 @@ */ function _gettext($msgid) { $l10n = _get_reader(); - //return $l10n->translate($msgid); return _encode($l10n->translate($msgid)); } + /** * Alias for gettext. */ function __($msgid) { return _gettext($msgid); } + /** * Plural version of gettext. */ -function _ngettext($single, $plural, $number) { +function _ngettext($singular, $plural, $number) { $l10n = _get_reader(); - //return $l10n->ngettext($single, $plural, $number); - return _encode($l10n->ngettext($single, $plural, $number)); + return _encode($l10n->ngettext($singular, $plural, $number)); } /** @@ -254,16 +299,15 @@ */ function _dgettext($domain, $msgid) { $l10n = _get_reader($domain); - //return $l10n->translate($msgid); return _encode($l10n->translate($msgid)); } + /** * Plural version of dgettext. */ -function _dngettext($domain, $single, $plural, $number) { +function _dngettext($domain, $singular, $plural, $number) { $l10n = _get_reader($domain); - //return $l10n->ngettext($single, $plural, $number); - return _encode($l10n->ngettext($single, $plural, $number)); + return _encode($l10n->ngettext($singular, $plural, $number)); } /** @@ -271,71 +315,169 @@ */ function _dcgettext($domain, $msgid, $category) { $l10n = _get_reader($domain, $category); - //return $l10n->translate($msgid); return _encode($l10n->translate($msgid)); } /** * Plural version of dcgettext. */ -function _dcngettext($domain, $single, $plural, $number, $category) { +function _dcngettext($domain, $singular, $plural, $number, $category) { $l10n = _get_reader($domain, $category); - //return $l10n->ngettext($single, $plural, $number); - return _encode($l10n->ngettext($single, $plural, $number)); + return _encode($l10n->ngettext($singular, $plural, $number)); } +/** + * Context version of gettext. + */ +function _pgettext($context, $msgid) { + $l10n = _get_reader(); + return _encode($l10n->pgettext($context, $msgid)); +} +/** + * Override the current domain in a context gettext call. + */ +function _dpgettext($domain, $context, $msgid) { + $l10n = _get_reader($domain); + return _encode($l10n->pgettext($context, $msgid)); +} -// Wrappers to use if the standard gettext functions are available, but the current locale is not supported by the system. -// Use the standard impl if the current locale is supported, use the custom impl otherwise. +/** + * Overrides the domain and category for a single context-based lookup. + */ +function _dcpgettext($domain, $context, $msgid, $category) { + $l10n = _get_reader($domain, $category); + return _encode($l10n->pgettext($context, $msgid)); +} +/** + * Context version of ngettext. + */ +function _npgettext($context, $singular, $plural) { + $l10n = _get_reader(); + return _encode($l10n->npgettext($context, $singular, $plural)); +} + +/** + * Override the current domain in a context ngettext call. + */ +function _dnpgettext($domain, $context, $singular, $plural) { + $l10n = _get_reader($domain); + return _encode($l10n->npgettext($context, $singular, $plural)); +} + +/** + * Overrides the domain and category for a plural context-based lookup. + */ +function _dcnpgettext($domain, $context, $singular, $plural, $category) { + $l10n = _get_reader($domain, $category); + return _encode($l10n->npgettext($context, $singular, $plural)); +} + + + +// Wrappers to use if the standard gettext functions are available, +// but the current locale is not supported by the system. +// Use the standard impl if the current locale is supported, use the +// custom impl otherwise. + function T_setlocale($category, $locale) { return _setlocale($category, $locale); } function T_bindtextdomain($domain, $path) { - if (_check_locale()) return bindtextdomain($domain, $path); + if (_check_locale_and_function()) return bindtextdomain($domain, $path); else return _bindtextdomain($domain, $path); } function T_bind_textdomain_codeset($domain, $codeset) { // bind_textdomain_codeset is available only in PHP 4.2.0+ - if (_check_locale() and function_exists('bind_textdomain_codeset')) return bind_textdomain_codeset($domain, $codeset); + if (_check_locale_and_function('bind_textdomain_codeset')) + return bind_textdomain_codeset($domain, $codeset); else return _bind_textdomain_codeset($domain, $codeset); } function T_textdomain($domain) { - if (_check_locale()) return textdomain($domain); + if (_check_locale_and_function()) return textdomain($domain); else return _textdomain($domain); } function T_gettext($msgid) { - if (_check_locale()) return gettext($msgid); + if (_check_locale_and_function()) return gettext($msgid); else return _gettext($msgid); } function T_($msgid) { - if (_check_locale()) return _($msgid); + if (_check_locale_and_function()) return _($msgid); return __($msgid); } -function T_ngettext($single, $plural, $number) { - if (_check_locale()) return ngettext($single, $plural, $number); - else return _ngettext($single, $plural, $number); +function T_ngettext($singular, $plural, $number) { + if (_check_locale_and_function()) + return ngettext($singular, $plural, $number); + else return _ngettext($singular, $plural, $number); } function T_dgettext($domain, $msgid) { - if (_check_locale()) return dgettext($domain, $msgid); + if (_check_locale_and_function()) return dgettext($domain, $msgid); else return _dgettext($domain, $msgid); } -function T_dngettext($domain, $single, $plural, $number) { - if (_check_locale()) return dngettext($domain, $single, $plural, $number); - else return _dngettext($domain, $single, $plural, $number); +function T_dngettext($domain, $singular, $plural, $number) { + if (_check_locale_and_function()) + return dngettext($domain, $singular, $plural, $number); + else return _dngettext($domain, $singular, $plural, $number); } function T_dcgettext($domain, $msgid, $category) { - if (_check_locale()) return dcgettext($domain, $msgid, $category); + if (_check_locale_and_function()) + return dcgettext($domain, $msgid, $category); else return _dcgettext($domain, $msgid, $category); } -function T_dcngettext($domain, $single, $plural, $number, $category) { - if (_check_locale()) return dcngettext($domain, $single, $plural, $number, $category); - else return _dcngettext($domain, $single, $plural, $number, $category); +function T_dcngettext($domain, $singular, $plural, $number, $category) { + if (_check_locale_and_function()) + return dcngettext($domain, $singular, $plural, $number, $category); + else return _dcngettext($domain, $singular, $plural, $number, $category); } +function T_pgettext($context, $msgid) { + if (_check_locale_and_function('pgettext')) + return pgettext($context, $msgid); + else + return _pgettext($context, $msgid); +} +function T_dpgettext($domain, $context, $msgid) { + if (_check_locale_and_function('dpgettext')) + return dpgettext($domain, $context, $msgid); + else + return _dpgettext($domain, $context, $msgid); +} +function T_dcpgettext($domain, $context, $msgid, $category) { + if (_check_locale_and_function('dcpgettext')) + return dcpgettext($domain, $context, $msgid, $category); + else + return _dcpgettext($domain, $context, $msgid, $category); +} + +function T_npgettext($context, $singular, $plural, $number) { + if (_check_locale_and_function('npgettext')) + return npgettext($context, $singular, $plural, $number); + else + return _npgettext($context, $singular, $plural, $number); +} + +function T_dnpgettext($domain, $context, $singular, $plural, $number) { + if (_check_locale_and_function('dnpgettext')) + return dnpgettext($domain, $context, $singular, $plural, $number); + else + return _dnpgettext($domain, $context, $singular, $plural, $number); +} + +function T_dcnpgettext($domain, $context, $singular, $plural, + $number, $category) { + if (_check_locale_and_function('dcnpgettext')) + return dcnpgettext($domain, $context, $singular, + $plural, $number, $category); + else + return _dcnpgettext($domain, $context, $singular, + $plural, $number, $category); +} + + + // Wrappers used as a drop in replacement for the standard gettext functions if (!function_exists('gettext')) { @@ -354,21 +496,41 @@ function _($msgid) { return __($msgid); } - function ngettext($single, $plural, $number) { - return _ngettext($single, $plural, $number); + function ngettext($singular, $plural, $number) { + return _ngettext($singular, $plural, $number); } function dgettext($domain, $msgid) { return _dgettext($domain, $msgid); } - function dngettext($domain, $single, $plural, $number) { - return _dngettext($domain, $single, $plural, $number); + function dngettext($domain, $singular, $plural, $number) { + return _dngettext($domain, $singular, $plural, $number); } function dcgettext($domain, $msgid, $category) { return _dcgettext($domain, $msgid, $category); } - function dcngettext($domain, $single, $plural, $number, $category) { - return _dcngettext($domain, $single, $plural, $number, $category); + function dcngettext($domain, $singular, $plural, $number, $category) { + return _dcngettext($domain, $singular, $plural, $number, $category); } + function pgettext($context, $msgid) { + return _pgettext($context, $msgid); + } + function npgettext($context, $singular, $plural, $number) { + return _npgettext($context, $singular, $plural, $number); + } + function dpgettext($domain, $context, $msgid) { + return _dpgettext($domain, $context, $msgid); + } + function dnpgettext($domain, $context, $singular, $plural, $number) { + return _dnpgettext($domain, $context, $singular, $plural, $number); + } + function dcpgettext($domain, $context, $msgid, $category) { + return _dcpgettext($domain, $context, $msgid, $category); + } + function dcnpgettext($domain, $context, $singular, $plural, + $number, $category) { + return _dcnpgettext($domain, $context, $singular, $plural, + $number, $category); + } } ?> Modified: trunk/includes/php-gettext/gettext.php =================================================================== --- trunk/includes/php-gettext/gettext.php 2011-08-07 10:17:52 UTC (rev 4653) +++ trunk/includes/php-gettext/gettext.php 2011-08-08 10:32:39 UTC (rev 4654) @@ -1,6 +1,6 @@ <?php /* - Copyright (c) 2003 Danilo Segan <da...@kv...>. + Copyright (c) 2003, 2009 Danilo Segan <da...@kv...>. Copyright (c) 2005 Nico Kaiser <ni...@si...> This file is part of PHP-gettext. @@ -63,13 +63,19 @@ function readint() { if ($this->BYTEORDER == 0) { // low endian - return array_shift(unpack('V', $this->STREAM->read(4))); + $input=unpack('V', $this->STREAM->read(4)); + return array_shift($input); } else { // big endian - return array_shift(unpack('N', $this->STREAM->read(4))); + $input=unpack('N', $this->STREAM->read(4)); + return array_shift($input); } } + function read($bytes) { + return $this->STREAM->read($bytes); + } + /** * Reads an array of Integers from the Stream * @@ -102,17 +108,15 @@ // Caching can be turned off $this->enable_cache = $enable_cache; - // $MAGIC1 = (int)0x950412de; //bug in PHP 5 - $MAGIC1 = (int) - 1794895138; - // $MAGIC2 = (int)0xde120495; //bug - $MAGIC2 = (int) - 569244523; + $MAGIC1 = "\x95\x04\x12\xde"; + $MAGIC2 = "\xde\x12\x04\x95"; $this->STREAM = $Reader; - $magic = $this->readint(); + $magic = $this->read(4); if ($magic == $MAGIC1) { + $this->BYTEORDER = 1; + } elseif ($magic == $MAGIC2) { $this->BYTEORDER = 0; - } elseif ($magic == $MAGIC2) { - $this->BYTEORDER = 1; } else { $this->error = 1; // not MO file return false; @@ -140,10 +144,14 @@ return; /* get original and translations tables */ - $this->STREAM->seekto($this->originals); - $this->table_originals = $this->readintarray($this->total * 2); - $this->STREAM->seekto($this->translations); - $this->table_translations = $this->readintarray($this->total * 2); + if (!is_array($this->table_originals)) { + $this->STREAM->seekto($this->originals); + $this->table_originals = $this->readintarray($this->total * 2); + } + if (!is_array($this->table_translations)) { + $this->STREAM->seekto($this->translations); + $this->table_translations = $this->readintarray($this->total * 2); + } if ($this->enable_cache) { $this->cache_translations = array (); @@ -262,6 +270,55 @@ } /** + * Sanitize plural form expression for use in PHP eval call. + * + * @access private + * @return string sanitized plural form expression + */ + function sanitize_plural_expression($expr) { + // Get rid of disallowed characters. + $expr = preg_replace('@[^a-zA-Z0-9_:;\(\)\?\|\&=!<>+*/\%-]@', '', $expr); + + // Add parenthesis for tertiary '?' operator. + $expr .= ';'; + $res = ''; + $p = 0; + for ($i = 0; $i < strlen($expr); $i++) { + $ch = $expr[$i]; + switch ($ch) { + case '?': + $res .= ' ? ('; + $p++; + break; + case ':': + $res .= ') : ('; + break; + case ';': + $res .= str_repeat( ')', $p) . ';'; + $p = 0; + break; + default: + $res .= $ch; + } + } + return $res; + } + + /** + * Parse full PO header and extract only plural forms line. + * + * @access private + * @return string verbatim plural form header field + */ + function extract_plural_forms_header_from_po_header($header) { + if (preg_match("/(^|\n)plural-forms: ([^\n]*)\n/i", $header, $regs)) + $expr = $regs[2]; + else + $expr = "nplurals=2; plural=n == 1 ? 0 : 1;"; + return $expr; + } + + /** * Get possible plural forms from MO header * * @access private @@ -279,11 +336,8 @@ } else { $header = $this->get_translation_string(0); } - if (preg_match("plural-forms: ([^\n]*)\n", $header, $regs)) - $expr = $regs[1]; - else - $expr = "nplurals=2; plural=n == 1 ? 0 : 1;"; - $this->pluralheader = $expr; + $expr = $this->extract_plural_forms_header_from_po_header($header); + $this->pluralheader = $this->sanitize_plural_expression($expr); } return $this->pluralheader; } @@ -330,7 +384,7 @@ $select = $this->select_string($number); // this should contains all strings separated by NULLs - $key = $single.chr(0).$plural; + $key = $single . chr(0) . $plural; if ($this->enable_cache) { @@ -353,6 +407,26 @@ } } + function pgettext($context, $msgid) { + $key = $context . chr(4) . $msgid; + $ret = $this->translate($key); + if (strpos($ret, "\004") !== FALSE) { + return $msgid; + } else { + return $ret; + } + } + + function npgettext($context, $singular, $plural, $number) { + $key = $context . chr(4) . $singular; + $ret = $this->ngettext($key, $plural, $number); + if (strpos($ret, "\004") !== FALSE) { + return $singular; + } else { + return $ret; + } + + } } ?> Modified: trunk/includes/php-gettext/streams.php =================================================================== --- trunk/includes/php-gettext/streams.php 2011-08-07 10:17:52 UTC (rev 4653) +++ trunk/includes/php-gettext/streams.php 2011-08-08 10:32:39 UTC (rev 4654) @@ -55,18 +55,18 @@ } function read($bytes) { - $data = mb_substr($this->_str, $this->_pos, $bytes); + $data = substr($this->_str, $this->_pos, $bytes); $this->_pos += $bytes; - if (mb_strlen($this->_str)<$this->_pos) - $this->_pos = mb_strlen($this->_str); + if (strlen($this->_str)<$this->_pos) + $this->_pos = strlen($this->_str); return $data; } function seekto($pos) { $this->_pos = $pos; - if (mb_strlen($this->_str)<$this->_pos) - $this->_pos = mb_strlen($this->_str); + if (strlen($this->_str)<$this->_pos) + $this->_pos = strlen($this->_str); return $this->_pos; } @@ -75,7 +75,7 @@ } function length() { - return mb_strlen($this->_str); + return strlen($this->_str); } }; @@ -112,7 +112,7 @@ while ($bytes > 0) { $chunk = fread($this->_fd, $bytes); $data .= $chunk; - $bytes -= mb_strlen($chunk); + $bytes -= strlen($chunk); } $this->_pos = ftell($this->_fd); This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |