diff --git a/cake/basics.php b/cake/basics.php index 1cfec071f..fce730c89 100644 --- a/cake/basics.php +++ b/cake/basics.php @@ -1041,11 +1041,11 @@ * * Returns a translated string if one is found, or the submitted message if not found. * - * @param string $msg + * @param string $singular * @param boolean $return * @return translated string if $return is false string will be echoed */ - function __($msg, $return = false) { + function __($singular, $return = false) { if(!class_exists('I18n')) { uses('i18n'); } @@ -1053,23 +1053,23 @@ $dir = dirname($calledFrom[0]['file']); if($return === false) { - echo I18n::translate($msg, null, null, null, null, $dir); + echo I18n::translate($singular, null, null, 5, null, $dir); } else { - return I18n::translate($msg, null, null, null, null, $dir); + return I18n::translate($singular, null, null, 5, null, $dir); } } /** * - * Returns correct plural form of message identified by $msg1 and $msg2 for count $count. + * Returns correct plural form of message identified by $singular and $plural for count $count. * Some languages have more than one form for plural messages dependent on the count. * - * @param string $msg1 - * @param string $msg2 + * @param string $singular + * @param string $plural * @param integer $count * @param boolean $return * @return plural form of translated string if $return is false string will be echoed */ - function __n($msg1, $msg2, $count, $return = false) { + function __n($singular, $plural, $count, $return = false) { if(!class_exists('I18n')) { uses('i18n'); } @@ -1077,25 +1077,25 @@ $dir = dirname($calledFrom[0]['file']); if($return === false) { - echo I18n::translate($msg1, $msg2, null, null, $count, $dir); + echo I18n::translate($singular, $plural, null, 5, $count, $dir); } else { - return I18n::translate($msg1, $msg2, null, null, $count, $dir); + return I18n::translate($singular, $plural, null, 5, $count, $dir); } } /** * * Allows you to override the current domain for a single plural message lookup - * Returns correct plural form of message identified by $msg1 and $msg2 for count $count + * Returns correct plural form of message identified by $singular and $plural for count $count * from domain $domain * * @param string $domain - * @param string $msg1 - * @param string $msg2 + * @param string $singular + * @param string $plural * @param integer $count * @param boolean $return * @return plural form of translated string if $return is false string will be echoed */ - function __dn($domain, $msg1, $msg2, $count, $return = false) { + function __dn($domain, $singular, $plural, $count, $return = false) { if(!class_exists('I18n')) { uses('i18n'); } @@ -1103,16 +1103,16 @@ $dir = dirname($calledFrom[0]['file']); if($return === false) { - echo I18n::translate($msg1, $msg2, $domain, null, $count, $dir);; + echo I18n::translate($singular, $plural, $domain, 5, $count, $dir);; } else { - return I18n::translate($msg1, $msg2, $domain, null, $count, $dir); + return I18n::translate($singular, $plural, $domain, 5, $count, $dir); } } /** * * Allows you to override the current domain for a single plural message lookup. * It also allows you to specify a category. - * Returns correct plural form of message identified by $msg1 and $msg2 for count $count + * Returns correct plural form of message identified by $singular and $plural for count $count * from domain $domain * * The category argument allows a specific category of the locale settings to be used for fetching a message. @@ -1128,14 +1128,14 @@ * LC_ALL 6 * * @param string $domain - * @param string $msg1 - * @param string $msg2 + * @param string $singular + * @param string $plural * @param integer $count * @param string $category * @param boolean $return * @return plural form of translated string if $return is false string will be echoed */ - function __dcn($domain, $msg1, $msg2, $count, $category, $return = false) { + function __dcn($domain, $singular, $plural, $count, $category, $return = false) { if(!class_exists('I18n')) { uses('i18n'); } @@ -1143,9 +1143,9 @@ $dir = dirname($calledFrom[0]['file']); if($return === false) { - echo I18n::translate($msg1, $msg2, $domain, $category, $count, $dir); + echo I18n::translate($singular, $plural, $domain, $category, $count, $dir); } else { - return I18n::translate($msg1, $msg2, $domain, $category, $count, $dir); + return I18n::translate($singular, $plural, $domain, $category, $count, $dir); } } /** @@ -1188,12 +1188,12 @@ * * Allows you to override the current domain for a single message lookup. * - * @param unknown_type $domain - * @param unknown_type $msg - * @param unknown_type $return - * @return unknown + * @param string $domain + * @param string $msg + * @param string $return + * @return translated string if $return is false string will be echoed */ - function __d($domain, $msg, $return = false) { + function __d($domain, $msg, $return = false) { if(!class_exists('I18n')) { uses('i18n'); } @@ -1201,9 +1201,41 @@ $dir = dirname($calledFrom[0]['file']); if($return === false) { - echo I18n::translate($msg, null, $domain, null, null, $dir); + echo I18n::translate($msg, null, $domain, 5, null, $dir); } else { - return I18n::translate($msg, null, $domain, null, null, $dir); + return I18n::translate($msg, null, $domain, 5, null, $dir); + } + } +/** + * + * The category argument allows a specific category of the locale settings to be used for fetching a message. + * Valid categories are: LC_CTYPE, LC_NUMERIC, LC_TIME, LC_COLLATE, LC_MONETARY, LC_MESSAGES and LC_ALL. + * + * Note that the category must be specified with a numeric value, instead of the constant name. The values are: + * LC_CTYPE 0 + * LC_NUMERIC 1 + * LC_TIME 2 + * LC_COLLATE 3 + * LC_MONETARY 4 + * LC_MESSAGES 5 + * LC_ALL 6 + * + * @param string $domain + * @param string $msg + * @param string $return + * @return translated string if $return is false string will be echoed + */ + function __c($category, $msg, $return = false) { + if(!class_exists('I18n')) { + uses('i18n'); + } + $calledFrom = debug_backtrace(); + $dir = dirname($calledFrom[0]['file']); + + if($return === false) { + echo I18n::translate($msg, null, null, $category, null, $dir); + } else { + return I18n::translate($msg, null, null, $category, null, $dir); } } /** diff --git a/cake/libs/i18n.php b/cake/libs/i18n.php index c999903e0..0e7d3dccf 100644 --- a/cake/libs/i18n.php +++ b/cake/libs/i18n.php @@ -40,37 +40,47 @@ uses('l10n'); */ class I18n extends Object { /** - * Enter description here... + * Instance of the I10n class for localization * - * @var unknown_type + * @var object * @access private */ var $__l10n = null; /** - * Enter description here... + * The locale for current translation * - * @var unknown_type + * @var string * @access public */ var $locale = null; /** - * Enter description here... + * Translation strings for a specific domain read from the .mo or .po files * - * @var unknown_type + * @var array * @access private */ var $__domains = array(); /** - * Enter description here... + * Set to true when I18N::__bindTextDomain() is called for the first time. + * If a translation file is found it is set to false again * - * @var unknown_type + * @var boolean * @access private */ - var $__noLocal = null; + var $__noLocale = false; /** - * Enter description here... + * Set to true when I18N::__bindTextDomain() is called for the first time. + * If a translation file is found it is set to false again * - * @return unknown + * @var array + * @access private + */ + var $__categories = array('LC_CTYPE', 'LC_NUMERIC', 'LC_TIME', 'LC_COLLATE', 'LC_MONETARY', 'LC_MESSAGES', 'LC_ALL'); +/** + * Return a static instance of the I18n class + * + * @return object I18n + * @access public */ function &getInstance() { static $instance = array(); @@ -81,18 +91,22 @@ class I18n extends Object { return $instance[0]; } /** - * Enter description here... * - * @param unknown_type $message - * @param unknown_type $message2 - * @param unknown_type $domain - * @param unknown_type $category - * @param unknown_type $count - * @param unknown_type $directory - * @return unknown + * Used by the translation functions in basics.php + * Can also be used like I18n::translate(); but only if the uses('i18n'); has been used to load the class. + * + * @param string $singular + * @param string $plural + * @param string $domain + * @param string $category + * @param integer $count + * @param string $directory + * @return translated strings. + * @access public */ - function translate($message, $message2 = null, $domain = null, $category = null, $count = null, $directory) { + function translate($singular, $plural = null, $domain = null, $category, $count = null, $directory) { $_this =& I18n::getInstance(); + $_this->category = $_this->__categories[$category]; if(is_null($domain) && $_this->__l10n->found === false) { $language = Configure::read('Config.language'); @@ -107,25 +121,28 @@ class I18n extends Object { if(is_null($domain)) { if (preg_match('/views{0,1}\\'.DS.'([^\/]*)/', $directory, $regs)) { $domain = $regs[1]; + $directory = null; } elseif (preg_match('/controllers{0,1}\\'.DS.'([^\/]*)/', $directory, $regs)) { $domain = ($regs[1]); + $directory = null; } if(isset($domain) && $domain == 'templates') { if (preg_match('/templates{0,1}\\'.DS.'([^\/]*)/', $directory, $regs)) { $domain = ($regs[1]); + $directory = null; } } } - if(!isset($_this->__domains[$domain])) { - $_this->__bindTextDomain($domain); + if(!isset($_this->__domains[$_this->category][$domain])) { + $_this->__bindTextDomain($domain, $directory); } if (!isset($count)) { $pli = 0; - } elseif (!empty($_this->__domains[$domain]["%plural-c"]) && is_null($_this->__noLocal)) { - $ph = $_this->__domains[$domain]["%plural-c"]; + } elseif (!empty($_this->__domains[$_this->category][$domain]["%plural-c"]) && $_this->__noLocale === false) { + $ph = $_this->__domains[$_this->category][$domain]["%plural-c"]; $pli = $_this->__pluralGuess($ph, $count); } else { if ($count != 1) { @@ -135,8 +152,8 @@ class I18n extends Object { } } - if(!empty($_this->__domains[$domain][$message])) { - if (($trans = $_this->__domains[$domain][$message]) || ($pli) && ($trans = $_this->__domains[$domain][$message2])) { + if(!empty($_this->__domains[$_this->category][$domain][$singular])) { + if (($trans = $_this->__domains[$_this->category][$domain][$singular]) || ($pli) && ($trans = $_this->__domains[$_this->category][$domain][$plural])) { if (is_array($trans)) { if (!isset($trans[$pli])) { $pli = 0; @@ -144,23 +161,23 @@ class I18n extends Object { $trans = $trans[$pli]; } if (strlen($trans)) { - $message = $trans; - return $message; + $singular = $trans; + return $singular; } } } if(!empty($pli)) { - return($message2); + return($plural); } - return($message); + return($singular); } /** - * Enter description here... + * Attempts to find the plural form of a string. * - * @param unknown_type $type - * @param unknown_type $n - * @return unknown + * @param string $type + * @param integrer $n + * @return plural match * @access private */ function __pluralGuess(&$type, $n) { @@ -283,76 +300,81 @@ class I18n extends Object { return(0); } /** - * Enter description here... + * Binds the given domain to a file in the specified directory. + * If directory is null, will attempt to search default locations. * - * @param unknown_type $domain - * @return unknown + * @param string $domain + * @return string * @access private */ - function __bindTextDomain($domain) { + function __bindTextDomain($domain, $directory = null) { $_this =& I18n::getInstance(); - $_this->__noLocal = true; - - $searchPath[] = APP . 'locale'; - $searchPath[] = CAKE_CORE_INCLUDE_PATH . DS . 'cake' . DS . 'locale'; + $_this->__noLocale = true; + if(is_null($directory)) { + $searchPath[] = APP . 'locale'; + $searchPath[] = CAKE_CORE_INCLUDE_PATH . DS . 'cake' . DS . 'locale'; + } else { + $searchPath[] = $directory; + } foreach ($searchPath as $directory) { foreach ($_this->__l10n->languagePath as $lang) { - $file = $directory . DS . $lang . DS . 'LC_MESSAGES' . DS . $domain; - $default = APP . 'locale'. DS . $lang . DS . 'LC_MESSAGES' . DS . 'default'; - $core = CAKE_CORE_INCLUDE_PATH . DS . 'cake' . DS . 'locale'. DS . $lang . DS . 'LC_MESSAGES' . DS . 'core'; + $file = $directory . DS . $lang . DS . $_this->category . DS . $domain; + $default = APP . 'locale'. DS . $lang . DS . $_this->category . DS . 'default'; + $core = CAKE_CORE_INCLUDE_PATH . DS . 'cake' . DS . 'locale'. DS . $lang . DS . $_this->category . DS . 'core'; if (file_exists($fn = "$file.mo") && ($f = fopen($fn, "rb"))) { $_this->__loadMo($f, $domain); - $_this->__noLocal = null; + $_this->__noLocale = false; break 2; } elseif (file_exists($fn = "$default.mo") && ($f = fopen($fn, "rb"))) { $_this->__loadMo($f, $domain); - $_this->__noLocal = null; + $_this->__noLocale = false; break 2; } elseif (file_exists($fn = "$file.po") && ($f = fopen($fn, "r"))) { $_this->__loadPo($f, $domain); - $_this->__noLocal = null; + $_this->__noLocale = false; break 2; } elseif (file_exists($fn = "$default.po") && ($f = fopen($fn, "r"))) { $_this->__loadPo($f, $domain); - $_this->__noLocal = null; + $_this->__noLocale = false; break 2; } elseif (file_exists($fn = "$core.mo") && ($f = fopen($fn, "rb"))) { $_this->__loadMo($f, $domain); - $_this->__noLocal = null; + $_this->__noLocale = false; break 2; } elseif (file_exists($fn = "$core.po") && ($f = fopen($fn, "r"))) { $_this->__loadPo($f, $domain); - $_this->__noLocal = null; + $_this->__noLocale = false; break 2; } } } - if(empty($_this->__domains[$domain])) { + if(empty($_this->__domains[$_this->category][$domain])) { return($domain); } - if ($head = $_this->__domains[$domain][""]) { + if ($head = $_this->__domains[$_this->category][$domain][""]) { foreach (explode("\n", $head) as $line) { $header = strtok($line,":"); $line = trim(strtok("\n")); - $_this->__domains[$domain]["%po-header"][strtolower($header)] = $line; + $_this->__domains[$_this->category][$domain]["%po-header"][strtolower($header)] = $line; } - if(isset($_this->__domains[$domain]["%po-header"]["plural-forms"])) { - $switch = preg_replace("/[(){}\\[\\]^\\s*\\]]+/", "", $_this->__domains[$domain]["%po-header"]["plural-forms"]); - $_this->__domains[$domain]["%plural-c"] = $switch; + if(isset($_this->__domains[$_this->category][$domain]["%po-header"]["plural-forms"])) { + $switch = preg_replace("/[(){}\\[\\]^\\s*\\]]+/", "", $_this->__domains[$_this->category][$domain]["%po-header"]["plural-forms"]); + $_this->__domains[$_this->category][$domain]["%plural-c"] = $switch; } } return($domain); } /** - * Enter description here... * - * @param unknown_type $file - * @param unknown_type $domain + * Loads the binary .mo file for translation and sets the values for this translation in the var I18n::__domains + * + * @param resource $file + * @param string $domain * @access private */ function __loadMo($file, $domain) { @@ -380,20 +402,20 @@ class I18n extends Object { if (strpos($msgstr, "\000")) { $msgstr = explode("\000", $msgstr); } - $_this->__domains[$domain][$msgid] = $msgstr; + $_this->__domains[$_this->category][$domain][$msgid] = $msgstr; if (isset($msgid_plural)) { - $_this->__domains[$domain][$msgid_plural] = &$_this->__domains[$domain][$msgid]; + $_this->__domains[$_this->category][$domain][$msgid_plural] = &$_this->__domains[$_this->category][$domain][$msgid]; } } } } } /** - * Enter description here... + * Loads the text .po file for translation and sets the values for this translation in the var I18n::__domains * - * @param unknown_type $file - * @param unknown_type $domain + * @param resource $file + * @param string $domain * @return unknown * @access private */ @@ -459,18 +481,18 @@ class I18n extends Object { fclose($file); $merge[""] = $header; - return $_this->__domains[$domain] = array_merge($merge ,$translations); + return $_this->__domains[$_this->category][$domain] = array_merge($merge ,$translations); } /** - * Enter description here... + * Not implemented * - * @param unknown_type $domain - * @param unknown_type $codeset + * @param string $domain + * @param string $codeset * @return unknown * @access private * @todo Not implemented */ - function __bindTextDomainCodeset($domain, $codeset) { + function __bindTextDomainCodeset($domain, $codeset = null) { return($domain); } } diff --git a/cake/libs/l10n.php b/cake/libs/l10n.php index aebfe918e..ba873ffe1 100644 --- a/cake/libs/l10n.php +++ b/cake/libs/l10n.php @@ -36,56 +36,58 @@ */ class L10n extends Object { /** - * Enter description here... + * The language for current locale * * @var string * @access public */ var $language = 'English (United States)'; /** - * Enter description here... + * Locale search paths * * @var array * @access public */ var $languagePath = array('eng'); /** - * Enter description here... + * ISO 639-3 for current locale * * @var string * @access public */ var $lang = 'eng'; /** - * Enter description here... + * Locale * * @var string * @access public */ var $locale = 'en_us'; /** - * Enter description here... + * Default ISO 639-3 language. + * + * DEFAULT_LANGUAGE is defined in an application this will be set as a fall back * * @var string * @access public */ var $default = null; /** - * Enter description here... + * Encoding used for current locale * * @var string * @access public */ var $charset = 'utf-8'; /** - * Enter description here... + * Set to true if a locale is found * * @var string * @access public */ var $found = false; /** - * Enter description here... + * Maps ISO 639-3 to I10n::__l10nCatalog * * @var array * @access private @@ -168,9 +170,11 @@ class L10n extends Object { /* Yiddish */ 'yid' => 'yi', /* Zulu */ 'zul' => 'zu'); /** - * Enter description here... + * HTTP_ACCEPT_LANGUAGE catalog * - * @var unknown_type + * holds all information related to a language + * + * @var array * @access private */ var $__l10nCatalog = array('af' => array('language' => 'Afrikaans', 'locale' => 'afr', 'localeFallback' => 'afr', 'charset' => 'utf-8'), @@ -312,8 +316,7 @@ class L10n extends Object { 'zh-tw' => array('language' => 'Chinese (Taiwan)', 'locale' => 'zh_tw', 'localeFallback' => 'chi', 'charset' => 'utf-8'), 'zu' => array('language' => 'Zulu', 'locale' => 'zul', 'localeFallback' => 'zul', 'charset' => 'utf-8')); /** - * Enter description here... - * + * Class constructor */ function __construct() { if (defined('DEFAULT_LANGUAGE')) { @@ -322,10 +325,12 @@ class L10n extends Object { parent::__construct(); } /** - * Enter description here... + * Gets the settings for $language. + * If $language is null it attempt to get settings from I10n::__autoLanguage(); if this fails + * the method will get the settings from I10n::__setLanguage(); * * @param string $language - * @return unknown + * @return void * @access private */ function get($language = null) { @@ -336,7 +341,8 @@ class L10n extends Object { } } /** - * Enter description here... + * Sets the class vars to correct values for $language. + * If $language is null it will use the DEFAULT_LANGUAGE if defined * * @param string $language * @access private @@ -375,7 +381,7 @@ class L10n extends Object { Configure::write('charset', $this->charset); } /** - * Enter description here... + * Attempts to find the locale settings based on the HTTP_ACCEPT_LANGUAGE variable * @access private */ function __autoLanguage() {