File indexing completed on 2024-12-22 05:37:11
0001 <?php 0002 /** 0003 * Zend Framework 0004 * 0005 * LICENSE 0006 * 0007 * This source file is subject to the new BSD license that is bundled 0008 * with this package in the file LICENSE.txt. 0009 * It is also available through the world-wide-web at this URL: 0010 * http://framework.zend.com/license/new-bsd 0011 * If you did not receive a copy of the license and are unable to 0012 * obtain it through the world-wide-web, please send an email 0013 * to license@zend.com so we can send you a copy immediately. 0014 * 0015 * @category Zend 0016 * @package Zend_Translate 0017 * @subpackage Zend_Translate_Adapter 0018 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0019 * @license http://framework.zend.com/license/new-bsd New BSD License 0020 * @version $Id$ 0021 */ 0022 0023 /** 0024 * @see Zend_Locale 0025 */ 0026 // require_once 'Zend/Locale.php'; 0027 0028 /** 0029 * @see Zend_Translate_Plural 0030 */ 0031 // require_once 'Zend/Translate/Plural.php'; 0032 0033 /** 0034 * Basic adapter class for each translation source adapter 0035 * 0036 * @category Zend 0037 * @package Zend_Translate 0038 * @subpackage Zend_Translate_Adapter 0039 * @copyright Copyright (c) 2005-2015 Zend Technologies USA Inc. (http://www.zend.com) 0040 * @license http://framework.zend.com/license/new-bsd New BSD License 0041 */ 0042 abstract class Zend_Translate_Adapter { 0043 /** 0044 * Shows if locale detection is in automatic level 0045 * @var boolean 0046 */ 0047 private $_automatic = true; 0048 0049 /** 0050 * Internal value to see already routed languages 0051 * @var array() 0052 */ 0053 private $_routed = array(); 0054 0055 /** 0056 * Internal cache for all adapters 0057 * @var Zend_Cache_Core 0058 */ 0059 protected static $_cache = null; 0060 0061 /** 0062 * Internal value to remember if cache supports tags 0063 * 0064 * @var boolean 0065 */ 0066 private static $_cacheTags = false; 0067 0068 /** 0069 * Scans for the locale within the name of the directory 0070 * @constant integer 0071 */ 0072 const LOCALE_DIRECTORY = 'directory'; 0073 0074 /** 0075 * Scans for the locale within the name of the file 0076 * @constant integer 0077 */ 0078 const LOCALE_FILENAME = 'filename'; 0079 0080 /** 0081 * Array with all options, each adapter can have own additional options 0082 * 'clear' => when true, clears already loaded translations when adding new files 0083 * 'content' => content to translate or file or directory with content 0084 * 'disableNotices' => when true, omits notices from being displayed 0085 * 'ignore' => a prefix for files and directories which are not being added 0086 * 'locale' => the actual set locale to use 0087 * 'log' => a instance of Zend_Log where logs are written to 0088 * 'logMessage' => message to be logged 0089 * 'logPriority' => priority which is used to write the log message 0090 * 'logUntranslated' => when true, untranslated messages are not logged 0091 * 'reload' => reloads the cache by reading the content again 0092 * 'scan' => searches for translation files using the LOCALE constants 0093 * 'tag' => tag to use for the cache 0094 * 0095 * @var array 0096 */ 0097 protected $_options = array( 0098 'clear' => false, 0099 'content' => null, 0100 'disableNotices' => false, 0101 'ignore' => '.', 0102 'locale' => 'auto', 0103 'log' => null, 0104 'logMessage' => "Untranslated message within '%locale%': %message%", 0105 'logPriority' => 5, 0106 'logUntranslated' => false, 0107 'reload' => false, 0108 'route' => null, 0109 'scan' => null, 0110 'tag' => 'Zend_Translate' 0111 ); 0112 0113 /** 0114 * Translation table 0115 * @var array 0116 */ 0117 protected $_translate = array(); 0118 0119 /** 0120 * Generates the adapter 0121 * 0122 * @param string|array|Zend_Config $options Translation options for this adapter 0123 * @param string|array [$content] 0124 * @param string|Zend_Locale [$locale] 0125 * @throws Zend_Translate_Exception 0126 * @return void 0127 */ 0128 public function __construct($options = array()) 0129 { 0130 if ($options instanceof Zend_Config) { 0131 $options = $options->toArray(); 0132 } else if (func_num_args() > 1) { 0133 $args = func_get_args(); 0134 $options = array(); 0135 $options['content'] = array_shift($args); 0136 0137 if (!empty($args)) { 0138 $options['locale'] = array_shift($args); 0139 } 0140 0141 if (!empty($args)) { 0142 $opt = array_shift($args); 0143 $options = array_merge($opt, $options); 0144 } 0145 } else if (!is_array($options)) { 0146 $options = array('content' => $options); 0147 } 0148 0149 if (array_key_exists('cache', $options)) { 0150 self::setCache($options['cache']); 0151 unset($options['cache']); 0152 } 0153 0154 if (isset(self::$_cache)) { 0155 $id = 'Zend_Translate_' . $this->toString() . '_Options'; 0156 $result = self::$_cache->load($id); 0157 if ($result) { 0158 $this->_options = $result; 0159 } 0160 } 0161 0162 if (empty($options['locale']) || ($options['locale'] === "auto")) { 0163 $this->_automatic = true; 0164 } else { 0165 $this->_automatic = false; 0166 } 0167 0168 $locale = null; 0169 if (!empty($options['locale'])) { 0170 $locale = $options['locale']; 0171 unset($options['locale']); 0172 } 0173 0174 $this->setOptions($options); 0175 $options['locale'] = $locale; 0176 0177 if (!empty($options['content'])) { 0178 $this->addTranslation($options); 0179 } 0180 0181 if ($this->getLocale() !== (string) $options['locale']) { 0182 $this->setLocale($options['locale']); 0183 } 0184 } 0185 0186 /** 0187 * Add translations 0188 * 0189 * This may be a new language or additional content for an existing language 0190 * If the key 'clear' is true, then translations for the specified 0191 * language will be replaced and added otherwise 0192 * 0193 * @param array|Zend_Config $options Options and translations to be added 0194 * @throws Zend_Translate_Exception 0195 * @return Zend_Translate_Adapter Provides fluent interface 0196 */ 0197 public function addTranslation($options = array()) 0198 { 0199 if ($options instanceof Zend_Config) { 0200 $options = $options->toArray(); 0201 } else if (func_num_args() > 1) { 0202 $args = func_get_args(); 0203 $options = array(); 0204 $options['content'] = array_shift($args); 0205 0206 if (!empty($args)) { 0207 $options['locale'] = array_shift($args); 0208 } 0209 0210 if (!empty($args)) { 0211 $opt = array_shift($args); 0212 $options = array_merge($opt, $options); 0213 } 0214 } else if (!is_array($options)) { 0215 $options = array('content' => $options); 0216 } 0217 0218 if (!isset($options['content']) || empty($options['content'])) { 0219 // require_once 'Zend/Translate/Exception.php'; 0220 throw new Zend_Translate_Exception("Required option 'content' is missing"); 0221 } 0222 0223 $originate = null; 0224 if (!empty($options['locale'])) { 0225 $originate = (string) $options['locale']; 0226 } 0227 0228 if ((array_key_exists('log', $options)) && !($options['log'] instanceof Zend_Log)) { 0229 // require_once 'Zend/Translate/Exception.php'; 0230 throw new Zend_Translate_Exception('Instance of Zend_Log expected for option log'); 0231 } 0232 0233 try { 0234 if (!($options['content'] instanceof Zend_Translate) && !($options['content'] instanceof Zend_Translate_Adapter)) { 0235 if (empty($options['locale'])) { 0236 $options['locale'] = null; 0237 } 0238 0239 $options['locale'] = Zend_Locale::findLocale($options['locale']); 0240 } 0241 } catch (Zend_Locale_Exception $e) { 0242 // require_once 'Zend/Translate/Exception.php'; 0243 throw new Zend_Translate_Exception("The given Language '{$options['locale']}' does not exist", 0, $e); 0244 } 0245 0246 $options = $options + $this->_options; 0247 if (is_string($options['content']) and is_dir($options['content'])) { 0248 $options['content'] = realpath($options['content']); 0249 $prev = ''; 0250 $iterator = new RecursiveIteratorIterator( 0251 new RecursiveRegexIterator( 0252 new RecursiveDirectoryIterator($options['content'], RecursiveDirectoryIterator::KEY_AS_PATHNAME), 0253 '/^(?!.*(\.svn|\.cvs)).*$/', RecursiveRegexIterator::MATCH 0254 ), 0255 RecursiveIteratorIterator::SELF_FIRST 0256 ); 0257 0258 foreach ($iterator as $directory => $info) { 0259 $file = $info->getFilename(); 0260 if (is_array($options['ignore'])) { 0261 foreach ($options['ignore'] as $key => $ignore) { 0262 if (strpos($key, 'regex') !== false) { 0263 if (preg_match($ignore, $directory)) { 0264 // ignore files matching the given regex from option 'ignore' and all files below 0265 continue 2; 0266 } 0267 } else if (strpos($directory, DIRECTORY_SEPARATOR . $ignore) !== false) { 0268 // ignore files matching first characters from option 'ignore' and all files below 0269 continue 2; 0270 } 0271 } 0272 } else { 0273 if (strpos($directory, DIRECTORY_SEPARATOR . $options['ignore']) !== false) { 0274 // ignore files matching first characters from option 'ignore' and all files below 0275 continue; 0276 } 0277 } 0278 0279 if ($info->isDir()) { 0280 // pathname as locale 0281 if (($options['scan'] === self::LOCALE_DIRECTORY) and (Zend_Locale::isLocale($file, true, false))) { 0282 $options['locale'] = $file; 0283 $prev = (string) $options['locale']; 0284 } 0285 } else if ($info->isFile()) { 0286 // filename as locale 0287 if ($options['scan'] === self::LOCALE_FILENAME) { 0288 $filename = explode('.', $file); 0289 array_pop($filename); 0290 $filename = implode('.', $filename); 0291 if (Zend_Locale::isLocale((string) $filename, true, false)) { 0292 $options['locale'] = (string) $filename; 0293 } else { 0294 $parts = explode('.', $file); 0295 $parts2 = array(); 0296 foreach($parts as $token) { 0297 $parts2 += explode('_', $token); 0298 } 0299 $parts = array_merge($parts, $parts2); 0300 $parts2 = array(); 0301 foreach($parts as $token) { 0302 $parts2 += explode('-', $token); 0303 } 0304 $parts = array_merge($parts, $parts2); 0305 $parts = array_unique($parts); 0306 $prev = ''; 0307 foreach($parts as $token) { 0308 if (Zend_Locale::isLocale($token, true, false)) { 0309 if (strlen($prev) <= strlen($token)) { 0310 $options['locale'] = $token; 0311 $prev = $token; 0312 } 0313 } 0314 } 0315 } 0316 } 0317 0318 try { 0319 $options['content'] = $info->getPathname(); 0320 $this->_addTranslationData($options); 0321 } catch (Zend_Translate_Exception $e) { 0322 // ignore failed sources while scanning 0323 } 0324 } 0325 } 0326 0327 unset($iterator); 0328 } else { 0329 $this->_addTranslationData($options); 0330 } 0331 0332 if ((isset($this->_translate[$originate]) === true) and (count($this->_translate[$originate]) > 0)) { 0333 $this->setLocale($originate); 0334 } 0335 0336 return $this; 0337 } 0338 0339 /** 0340 * Sets new adapter options 0341 * 0342 * @param array $options Adapter options 0343 * @throws Zend_Translate_Exception 0344 * @return Zend_Translate_Adapter Provides fluent interface 0345 */ 0346 public function setOptions(array $options = array()) 0347 { 0348 $change = false; 0349 $locale = null; 0350 foreach ($options as $key => $option) { 0351 if ($key == 'locale') { 0352 $locale = $option; 0353 } else if ((isset($this->_options[$key]) and ($this->_options[$key] != $option)) or 0354 !isset($this->_options[$key])) { 0355 if (($key == 'log') && !($option instanceof Zend_Log)) { 0356 // require_once 'Zend/Translate/Exception.php'; 0357 throw new Zend_Translate_Exception('Instance of Zend_Log expected for option log'); 0358 } 0359 0360 if ($key == 'cache') { 0361 self::setCache($option); 0362 continue; 0363 } 0364 0365 $this->_options[$key] = $option; 0366 $change = true; 0367 } 0368 } 0369 0370 if ($locale !== null) { 0371 $this->setLocale($locale); 0372 } 0373 0374 if (isset(self::$_cache) and ($change == true)) { 0375 $id = 'Zend_Translate_' . $this->toString() . '_Options'; 0376 if (self::$_cacheTags) { 0377 self::$_cache->save($this->_options, $id, array($this->_options['tag'])); 0378 } else { 0379 self::$_cache->save($this->_options, $id); 0380 } 0381 } 0382 0383 return $this; 0384 } 0385 0386 /** 0387 * Returns the adapters name and it's options 0388 * 0389 * @param string|null $optionKey String returns this option 0390 * null returns all options 0391 * @return integer|string|array|null 0392 */ 0393 public function getOptions($optionKey = null) 0394 { 0395 if ($optionKey === null) { 0396 return $this->_options; 0397 } 0398 0399 if (isset($this->_options[$optionKey]) === true) { 0400 return $this->_options[$optionKey]; 0401 } 0402 0403 return null; 0404 } 0405 0406 /** 0407 * Gets locale 0408 * 0409 * @return Zend_Locale|string|null 0410 */ 0411 public function getLocale() 0412 { 0413 return $this->_options['locale']; 0414 } 0415 0416 /** 0417 * Sets locale 0418 * 0419 * @param string|Zend_Locale $locale Locale to set 0420 * @throws Zend_Translate_Exception 0421 * @return Zend_Translate_Adapter Provides fluent interface 0422 */ 0423 public function setLocale($locale) 0424 { 0425 if (($locale === "auto") or ($locale === null)) { 0426 $this->_automatic = true; 0427 } else { 0428 $this->_automatic = false; 0429 } 0430 0431 try { 0432 $locale = Zend_Locale::findLocale($locale); 0433 } catch (Zend_Locale_Exception $e) { 0434 // require_once 'Zend/Translate/Exception.php'; 0435 throw new Zend_Translate_Exception("The given Language ({$locale}) does not exist", 0, $e); 0436 } 0437 0438 if (!isset($this->_translate[$locale])) { 0439 $temp = explode('_', $locale); 0440 if (!isset($this->_translate[$temp[0]]) and !isset($this->_translate[$locale])) { 0441 if (!$this->_options['disableNotices']) { 0442 if ($this->_options['log']) { 0443 $this->_options['log']->log("The language '{$locale}' has to be added before it can be used.", $this->_options['logPriority']); 0444 } else { 0445 trigger_error("The language '{$locale}' has to be added before it can be used.", E_USER_NOTICE); 0446 } 0447 } 0448 } 0449 0450 $locale = $temp[0]; 0451 } 0452 0453 if (empty($this->_translate[$locale])) { 0454 if (!$this->_options['disableNotices']) { 0455 if ($this->_options['log']) { 0456 $this->_options['log']->log("No translation for the language '{$locale}' available.", $this->_options['logPriority']); 0457 } else { 0458 trigger_error("No translation for the language '{$locale}' available.", E_USER_NOTICE); 0459 } 0460 } 0461 } 0462 0463 if ($this->_options['locale'] != $locale) { 0464 $this->_options['locale'] = $locale; 0465 0466 if (isset(self::$_cache)) { 0467 $id = 'Zend_Translate_' . $this->toString() . '_Options'; 0468 if (self::$_cacheTags) { 0469 self::$_cache->save($this->_options, $id, array($this->_options['tag'])); 0470 } else { 0471 self::$_cache->save($this->_options, $id); 0472 } 0473 } 0474 } 0475 0476 return $this; 0477 } 0478 0479 /** 0480 * Returns the available languages from this adapter 0481 * 0482 * @return array|null 0483 */ 0484 public function getList() 0485 { 0486 $list = array_keys($this->_translate); 0487 $result = null; 0488 foreach($list as $value) { 0489 if (!empty($this->_translate[$value])) { 0490 $result[$value] = $value; 0491 } 0492 } 0493 return $result; 0494 } 0495 0496 /** 0497 * Returns the message id for a given translation 0498 * If no locale is given, the actual language will be used 0499 * 0500 * @param string $message Message to get the key for 0501 * @param string|Zend_Locale $locale (optional) Language to return the message ids from 0502 * @return string|array|false 0503 */ 0504 public function getMessageId($message, $locale = null) 0505 { 0506 if (empty($locale) or !$this->isAvailable($locale)) { 0507 $locale = $this->_options['locale']; 0508 } 0509 0510 return array_search($message, $this->_translate[(string) $locale]); 0511 } 0512 0513 /** 0514 * Returns all available message ids from this adapter 0515 * If no locale is given, the actual language will be used 0516 * 0517 * @param string|Zend_Locale $locale (optional) Language to return the message ids from 0518 * @return array 0519 */ 0520 public function getMessageIds($locale = null) 0521 { 0522 if (empty($locale) or !$this->isAvailable($locale)) { 0523 $locale = $this->_options['locale']; 0524 } 0525 0526 return array_keys($this->_translate[(string) $locale]); 0527 } 0528 0529 /** 0530 * Returns all available translations from this adapter 0531 * If no locale is given, the actual language will be used 0532 * If 'all' is given the complete translation dictionary will be returned 0533 * 0534 * @param string|Zend_Locale $locale (optional) Language to return the messages from 0535 * @return array 0536 */ 0537 public function getMessages($locale = null) 0538 { 0539 if ($locale === 'all') { 0540 return $this->_translate; 0541 } 0542 0543 if ((empty($locale) === true) or ($this->isAvailable($locale) === false)) { 0544 $locale = $this->_options['locale']; 0545 } 0546 0547 return $this->_translate[(string) $locale]; 0548 } 0549 0550 /** 0551 * Is the wished language available ? 0552 * 0553 * @see Zend_Locale 0554 * @param string|Zend_Locale $locale Language to search for, identical with locale identifier, 0555 * @see Zend_Locale for more information 0556 * @return boolean 0557 */ 0558 public function isAvailable($locale) 0559 { 0560 $return = isset($this->_translate[(string) $locale]); 0561 return $return; 0562 } 0563 0564 /** 0565 * Load translation data 0566 * 0567 * @param mixed $data 0568 * @param string|Zend_Locale $locale 0569 * @param array $options (optional) 0570 * @return array 0571 */ 0572 abstract protected function _loadTranslationData($data, $locale, array $options = array()); 0573 0574 /** 0575 * Internal function for adding translation data 0576 * 0577 * This may be a new language or additional data for an existing language 0578 * If the options 'clear' is true, then the translation data for the specified 0579 * language is replaced and added otherwise 0580 * 0581 * @see Zend_Locale 0582 * @param array|Zend_Config $content Translation data to add 0583 * @throws Zend_Translate_Exception 0584 * @return Zend_Translate_Adapter Provides fluent interface 0585 */ 0586 private function _addTranslationData($options = array()) 0587 { 0588 if ($options instanceof Zend_Config) { 0589 $options = $options->toArray(); 0590 } else if (func_num_args() > 1) { 0591 $args = func_get_args(); 0592 $options['content'] = array_shift($args); 0593 0594 if (!empty($args)) { 0595 $options['locale'] = array_shift($args); 0596 } 0597 0598 if (!empty($args)) { 0599 $options += array_shift($args); 0600 } 0601 } 0602 0603 if (($options['content'] instanceof Zend_Translate) || ($options['content'] instanceof Zend_Translate_Adapter)) { 0604 $options['usetranslateadapter'] = true; 0605 if (!empty($options['locale']) && ($options['locale'] !== 'auto')) { 0606 $options['content'] = $options['content']->getMessages($options['locale']); 0607 } else { 0608 $content = $options['content']; 0609 $locales = $content->getList(); 0610 foreach ($locales as $locale) { 0611 $options['locale'] = $locale; 0612 $options['content'] = $content->getMessages($locale); 0613 $this->_addTranslationData($options); 0614 } 0615 0616 return $this; 0617 } 0618 } 0619 0620 try { 0621 $options['locale'] = Zend_Locale::findLocale($options['locale']); 0622 } catch (Zend_Locale_Exception $e) { 0623 // require_once 'Zend/Translate/Exception.php'; 0624 throw new Zend_Translate_Exception("The given Language '{$options['locale']}' does not exist", 0, $e); 0625 } 0626 0627 if ($options['clear'] || !isset($this->_translate[$options['locale']])) { 0628 $this->_translate[$options['locale']] = array(); 0629 } 0630 0631 $read = true; 0632 if (isset(self::$_cache)) { 0633 $id = 'Zend_Translate_' . md5(serialize($options['content'])) . '_' . $this->toString(); 0634 $temp = self::$_cache->load($id); 0635 if ($temp) { 0636 $read = false; 0637 } 0638 } 0639 0640 if ($options['reload']) { 0641 $read = true; 0642 } 0643 0644 if ($read) { 0645 if (!empty($options['usetranslateadapter'])) { 0646 $temp = array($options['locale'] => $options['content']); 0647 } else { 0648 $temp = $this->_loadTranslationData($options['content'], $options['locale'], $options); 0649 } 0650 } 0651 0652 if (empty($temp)) { 0653 $temp = array(); 0654 } 0655 0656 $keys = array_keys($temp); 0657 foreach($keys as $key) { 0658 if (!isset($this->_translate[$key])) { 0659 $this->_translate[$key] = array(); 0660 } 0661 0662 if (array_key_exists($key, $temp) && is_array($temp[$key])) { 0663 $this->_translate[$key] = $temp[$key] + $this->_translate[$key]; 0664 } 0665 } 0666 0667 if ($this->_automatic === true) { 0668 $find = new Zend_Locale($options['locale']); 0669 $browser = $find->getEnvironment() + $find->getBrowser(); 0670 arsort($browser); 0671 foreach($browser as $language => $quality) { 0672 if (isset($this->_translate[$language])) { 0673 $this->_options['locale'] = $language; 0674 break; 0675 } 0676 } 0677 } 0678 0679 if (($read) and (isset(self::$_cache))) { 0680 $id = 'Zend_Translate_' . md5(serialize($options['content'])) . '_' . $this->toString(); 0681 if (self::$_cacheTags) { 0682 self::$_cache->save($temp, $id, array($this->_options['tag'])); 0683 } else { 0684 self::$_cache->save($temp, $id); 0685 } 0686 } 0687 0688 return $this; 0689 } 0690 0691 /** 0692 * Translates the given string 0693 * returns the translation 0694 * 0695 * @see Zend_Locale 0696 * @param string|array $messageId Translation string, or Array for plural translations 0697 * @param string|Zend_Locale $locale (optional) Locale/Language to use, identical with 0698 * locale identifier, @see Zend_Locale for more information 0699 * @return string 0700 */ 0701 public function translate($messageId, $locale = null) 0702 { 0703 if ($locale === null) { 0704 $locale = $this->_options['locale']; 0705 } 0706 0707 $plural = null; 0708 if (is_array($messageId)) { 0709 if (count($messageId) > 2) { 0710 $number = array_pop($messageId); 0711 if (!is_numeric($number)) { 0712 $plocale = $number; 0713 $number = array_pop($messageId); 0714 } else { 0715 $plocale = 'en'; 0716 } 0717 0718 $plural = $messageId; 0719 $messageId = $messageId[0]; 0720 } else { 0721 $messageId = $messageId[0]; 0722 } 0723 } 0724 0725 if (!Zend_Locale::isLocale($locale, true, false)) { 0726 if (!Zend_Locale::isLocale($locale, false, false)) { 0727 // language does not exist, return original string 0728 $this->_log($messageId, $locale); 0729 // use rerouting when enabled 0730 if (!empty($this->_options['route'])) { 0731 if (array_key_exists($locale, $this->_options['route']) && 0732 !array_key_exists($locale, $this->_routed)) { 0733 $this->_routed[$locale] = true; 0734 return $this->translate($messageId, $this->_options['route'][$locale]); 0735 } 0736 } 0737 0738 $this->_routed = array(); 0739 if ($plural === null) { 0740 return $messageId; 0741 } 0742 0743 $rule = Zend_Translate_Plural::getPlural($number, $plocale); 0744 if (!isset($plural[$rule])) { 0745 $rule = 0; 0746 } 0747 0748 return $plural[$rule]; 0749 } 0750 0751 $locale = new Zend_Locale($locale); 0752 } 0753 0754 $locale = (string) $locale; 0755 if ((is_string($messageId) || is_int($messageId)) && isset($this->_translate[$locale][$messageId])) { 0756 // return original translation 0757 if ($plural === null) { 0758 $this->_routed = array(); 0759 return $this->_translate[$locale][$messageId]; 0760 } 0761 0762 $rule = Zend_Translate_Plural::getPlural($number, $locale); 0763 if (isset($this->_translate[$locale][$plural[0]][$rule])) { 0764 $this->_routed = array(); 0765 return $this->_translate[$locale][$plural[0]][$rule]; 0766 } 0767 } else if (strlen($locale) != 2) { 0768 // faster than creating a new locale and separate the leading part 0769 $locale = substr($locale, 0, -strlen(strrchr($locale, '_'))); 0770 0771 if ((is_string($messageId) || is_int($messageId)) && isset($this->_translate[$locale][$messageId])) { 0772 // return regionless translation (en_US -> en) 0773 if ($plural === null) { 0774 $this->_routed = array(); 0775 return $this->_translate[$locale][$messageId]; 0776 } 0777 0778 $rule = Zend_Translate_Plural::getPlural($number, $locale); 0779 if (isset($this->_translate[$locale][$plural[0]][$rule])) { 0780 $this->_routed = array(); 0781 return $this->_translate[$locale][$plural[0]][$rule]; 0782 } 0783 } 0784 } 0785 0786 $this->_log($messageId, $locale); 0787 // use rerouting when enabled 0788 if (!empty($this->_options['route'])) { 0789 if (array_key_exists($locale, $this->_options['route']) && 0790 !array_key_exists($locale, $this->_routed)) { 0791 $this->_routed[$locale] = true; 0792 return $this->translate($messageId, $this->_options['route'][$locale]); 0793 } 0794 } 0795 0796 $this->_routed = array(); 0797 if ($plural === null) { 0798 return $messageId; 0799 } 0800 0801 $rule = Zend_Translate_Plural::getPlural($number, $plocale); 0802 if (!isset($plural[$rule])) { 0803 $rule = 0; 0804 } 0805 0806 return $plural[$rule]; 0807 } 0808 0809 /** 0810 * Translates the given string using plural notations 0811 * Returns the translated string 0812 * 0813 * @see Zend_Locale 0814 * @param string $singular Singular translation string 0815 * @param string $plural Plural translation string 0816 * @param integer $number Number for detecting the correct plural 0817 * @param string|Zend_Locale $locale (Optional) Locale/Language to use, identical with 0818 * locale identifier, @see Zend_Locale for more information 0819 * @return string 0820 */ 0821 public function plural($singular, $plural, $number, $locale = null) 0822 { 0823 return $this->translate(array($singular, $plural, $number), $locale); 0824 } 0825 0826 /** 0827 * Logs a message when the log option is set 0828 * 0829 * @param string $message Message to log 0830 * @param String $locale Locale to log 0831 */ 0832 protected function _log($message, $locale) { 0833 if ($this->_options['logUntranslated']) { 0834 $message = str_replace('%message%', $message, $this->_options['logMessage']); 0835 $message = str_replace('%locale%', $locale, $message); 0836 if ($this->_options['log']) { 0837 $this->_options['log']->log($message, $this->_options['logPriority']); 0838 } else { 0839 trigger_error($message, E_USER_NOTICE); 0840 } 0841 } 0842 } 0843 0844 /** 0845 * Translates the given string 0846 * returns the translation 0847 * 0848 * @param string $messageId Translation string 0849 * @param string|Zend_Locale $locale (optional) Locale/Language to use, identical with locale 0850 * identifier, @see Zend_Locale for more information 0851 * @return string 0852 */ 0853 public function _($messageId, $locale = null) 0854 { 0855 return $this->translate($messageId, $locale); 0856 } 0857 0858 /** 0859 * Checks if a string is translated within the source or not 0860 * returns boolean 0861 * 0862 * @param string $messageId Translation string 0863 * @param boolean $original (optional) Allow translation only for original language 0864 * when true, a translation for 'en_US' would give false when it can 0865 * be translated with 'en' only 0866 * @param string|Zend_Locale $locale (optional) Locale/Language to use, identical with locale identifier, 0867 * see Zend_Locale for more information 0868 * @return boolean 0869 */ 0870 public function isTranslated($messageId, $original = false, $locale = null) 0871 { 0872 if (($original !== false) and ($original !== true)) { 0873 $locale = $original; 0874 $original = false; 0875 } 0876 0877 if ($locale === null) { 0878 $locale = $this->_options['locale']; 0879 } 0880 0881 if (!Zend_Locale::isLocale($locale, true, false)) { 0882 if (!Zend_Locale::isLocale($locale, false, false)) { 0883 // language does not exist, return original string 0884 return false; 0885 } 0886 0887 $locale = new Zend_Locale($locale); 0888 } 0889 0890 $locale = (string) $locale; 0891 if ((is_string($messageId) || is_int($messageId)) && isset($this->_translate[$locale][$messageId])) { 0892 // return original translation 0893 return true; 0894 } else if ((strlen($locale) != 2) and ($original === false)) { 0895 // faster than creating a new locale and separate the leading part 0896 $locale = substr($locale, 0, -strlen(strrchr($locale, '_'))); 0897 0898 if ((is_string($messageId) || is_int($messageId)) && isset($this->_translate[$locale][$messageId])) { 0899 // return regionless translation (en_US -> en) 0900 return true; 0901 } 0902 } 0903 0904 // No translation found, return original 0905 return false; 0906 } 0907 0908 /** 0909 * Returns the set cache 0910 * 0911 * @return Zend_Cache_Core The set cache 0912 */ 0913 public static function getCache() 0914 { 0915 return self::$_cache; 0916 } 0917 0918 /** 0919 * Sets a cache for all Zend_Translate_Adapters 0920 * 0921 * @param Zend_Cache_Core $cache Cache to store to 0922 */ 0923 public static function setCache(Zend_Cache_Core $cache) 0924 { 0925 self::$_cache = $cache; 0926 self::_getTagSupportForCache(); 0927 } 0928 0929 /** 0930 * Returns true when a cache is set 0931 * 0932 * @return boolean 0933 */ 0934 public static function hasCache() 0935 { 0936 if (self::$_cache !== null) { 0937 return true; 0938 } 0939 0940 return false; 0941 } 0942 0943 /** 0944 * Removes any set cache 0945 * 0946 * @return void 0947 */ 0948 public static function removeCache() 0949 { 0950 self::$_cache = null; 0951 } 0952 0953 /** 0954 * Clears all set cache data 0955 * 0956 * @param string $tag Tag to clear when the default tag name is not used 0957 * @return void 0958 */ 0959 public static function clearCache($tag = null) 0960 { 0961 // require_once 'Zend/Cache.php'; 0962 if (self::$_cacheTags) { 0963 if ($tag == null) { 0964 $tag = 'Zend_Translate'; 0965 } 0966 0967 self::$_cache->clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG, array($tag)); 0968 } else { 0969 self::$_cache->clean(Zend_Cache::CLEANING_MODE_ALL); 0970 } 0971 } 0972 0973 /** 0974 * Returns the adapter name 0975 * 0976 * @return string 0977 */ 0978 abstract public function toString(); 0979 0980 /** 0981 * Internal method to check if the given cache supports tags 0982 * 0983 * @param Zend_Cache $cache 0984 */ 0985 private static function _getTagSupportForCache() 0986 { 0987 $backend = self::$_cache->getBackend(); 0988 if ($backend instanceof Zend_Cache_Backend_ExtendedInterface) { 0989 $cacheOptions = $backend->getCapabilities(); 0990 self::$_cacheTags = $cacheOptions['tags']; 0991 } else { 0992 self::$_cacheTags = false; 0993 } 0994 0995 return self::$_cacheTags; 0996 } 0997 }