*prechod na novsiu verziu ZF
[sport-group.git] / library / Zend / Translate / Adapter.php
blob60a17e335691e63480f823bbdeb25487bbbb1326
1 <?php
2 /**
3 * Zend Framework
5 * LICENSE
7 * This source file is subject to the new BSD license that is bundled
8 * with this package in the file LICENSE.txt.
9 * It is also available through the world-wide-web at this URL:
10 * http://framework.zend.com/license/new-bsd
11 * If you did not receive a copy of the license and are unable to
12 * obtain it through the world-wide-web, please send an email
13 * to license@zend.com so we can send you a copy immediately.
15 * @category Zend
16 * @package Zend_Translate
17 * @subpackage Zend_Translate_Adapter
18 * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
19 * @license http://framework.zend.com/license/new-bsd New BSD License
20 * @version $Id: Adapter.php 17761 2009-08-22 22:23:12Z thomas $
23 /**
24 * @see Zend_Locale
26 require_once 'Zend/Locale.php';
28 /**
29 * @see Zend_Translate_Plural
31 require_once 'Zend/Translate/Plural.php';
33 /**
34 * Basic adapter class for each translation source adapter
36 * @category Zend
37 * @package Zend_Translate
38 * @subpackage Zend_Translate_Adapter
39 * @copyright Copyright (c) 2005-2009 Zend Technologies USA Inc. (http://www.zend.com)
40 * @license http://framework.zend.com/license/new-bsd New BSD License
42 abstract class Zend_Translate_Adapter {
43 /**
44 * Shows if locale detection is in automatic level
45 * @var boolean
47 private $_automatic = true;
49 /**
50 * Internal cache for all adapters
51 * @var Zend_Cache_Core
53 protected static $_cache = null;
55 /**
56 * Scans for the locale within the name of the directory
57 * @constant integer
59 const LOCALE_DIRECTORY = 'directory';
61 /**
62 * Scans for the locale within the name of the file
63 * @constant integer
65 const LOCALE_FILENAME = 'filename';
67 /**
68 * Array with all options, each adapter can have own additional options
69 * 'clear' => clears already loaded data when adding new files
70 * 'scan' => searches for translation files using the LOCALE constants
71 * 'locale' => the actual set locale to use
72 * @var array
74 protected $_options = array(
75 'clear' => false,
76 'disableNotices' => false,
77 'ignore' => '.',
78 'locale' => 'auto',
79 'log' => null,
80 'logMessage' => "Untranslated message within '%locale%': %message%",
81 'logUntranslated' => false,
82 'scan' => null
85 /**
86 * Translation table
87 * @var array
89 protected $_translate = array();
91 /**
92 * Generates the adapter
94 * @param string|array $data Translation data or filename for this adapter
95 * @param string|Zend_Locale $locale (optional) Locale/Language to set, identical with Locale
96 * identifiers see Zend_Locale for more information
97 * @param array $options (optional) Options for the adaptor
98 * @throws Zend_Translate_Exception
99 * @return void
101 public function __construct($data, $locale = null, array $options = array())
103 if (isset(self::$_cache)) {
104 $id = 'Zend_Translate_' . $this->toString() . '_Options';
105 $result = self::$_cache->load($id);
106 if ($result) {
107 $this->_options = unserialize($result);
111 if (($locale === "auto") or ($locale === null)) {
112 $this->_automatic = true;
113 } else {
114 $this->_automatic = false;
117 $this->addTranslation($data, $locale, $options);
118 if ($this->getLocale() !== (string) $locale) {
119 $this->setLocale($locale);
124 * Add translation data
126 * It may be a new language or additional data for existing language
127 * If $clear parameter is true, then translation data for specified
128 * language is replaced and added otherwise
130 * @param array|string $data Translation data
131 * @param string|Zend_Locale $locale (optional) Locale/Language to add data for, identical
132 * with locale identifier, see Zend_Locale for more information
133 * @param array $options (optional) Option for this Adapter
134 * @throws Zend_Translate_Exception
135 * @return Zend_Translate_Adapter Provides fluent interface
137 public function addTranslation($data, $locale = null, array $options = array())
139 try {
140 $locale = Zend_Locale::findLocale($locale);
141 } catch (Zend_Locale_Exception $e) {
142 require_once 'Zend/Translate/Exception.php';
143 throw new Zend_Translate_Exception("The given Language '{$locale}' does not exist");
146 $originate = (string) $locale;
148 $this->setOptions($options);
149 if (is_string($data) and is_dir($data)) {
150 $data = realpath($data);
151 $prev = '';
152 foreach (new RecursiveIteratorIterator(
153 new RecursiveDirectoryIterator($data, RecursiveDirectoryIterator::KEY_AS_PATHNAME),
154 RecursiveIteratorIterator::SELF_FIRST) as $directory => $info) {
155 $file = $info->getFilename();
156 if (strpos($directory, DIRECTORY_SEPARATOR . $this->_options['ignore']) !== false) {
157 // ignore files matching first characters from option 'ignore' and all files below
158 continue;
161 if ($info->isDir()) {
162 // pathname as locale
163 if (($this->_options['scan'] === self::LOCALE_DIRECTORY) and (Zend_Locale::isLocale($file, true, false))) {
164 if (strlen($prev) <= strlen($file)) {
165 $locale = $file;
166 $prev = (string) $locale;
169 } else if ($info->isFile()) {
170 // filename as locale
171 if ($this->_options['scan'] === self::LOCALE_FILENAME) {
172 $filename = explode('.', $file);
173 array_pop($filename);
174 $filename = implode('.', $filename);
175 if (Zend_Locale::isLocale((string) $filename, true, false)) {
176 $locale = (string) $filename;
177 } else {
178 $parts = explode('.', $file);
179 $parts2 = array();
180 foreach($parts as $token) {
181 $parts2 += explode('_', $token);
183 $parts = array_merge($parts, $parts2);
184 $parts2 = array();
185 foreach($parts as $token) {
186 $parts2 += explode('-', $token);
188 $parts = array_merge($parts, $parts2);
189 $parts = array_unique($parts);
190 $prev = '';
191 foreach($parts as $token) {
192 if (Zend_Locale::isLocale($token, true, false)) {
193 if (strlen($prev) <= strlen($token)) {
194 $locale = $token;
195 $prev = $token;
201 try {
202 $this->_addTranslationData($info->getPathname(), (string) $locale, $this->_options);
203 if ((isset($this->_translate[(string) $locale]) === true) and (count($this->_translate[(string) $locale]) > 0)) {
204 $this->setLocale($locale);
206 } catch (Zend_Translate_Exception $e) {
207 // ignore failed sources while scanning
211 } else {
212 $this->_addTranslationData($data, (string) $locale, $this->_options);
213 if ((isset($this->_translate[(string) $locale]) === true) and (count($this->_translate[(string) $locale]) > 0)) {
214 $this->setLocale($locale);
218 if ((isset($this->_translate[$originate]) === true) and (count($this->_translate[$originate]) > 0) and ($originate !== (string) $locale)) {
219 $this->setLocale($originate);
222 return $this;
226 * Sets new adapter options
228 * @param array $options Adapter options
229 * @throws Zend_Translate_Exception
230 * @return Zend_Translate_Adapter Provides fluent interface
232 public function setOptions(array $options = array())
234 $change = false;
235 $locale = null;
236 foreach ($options as $key => $option) {
237 if ($key == 'locale') {
238 $locale = $option;
239 } else if ((isset($this->_options[$key]) and ($this->_options[$key] != $option)) or
240 !isset($this->_options[$key])) {
241 if (($key == 'log') && !($option instanceof Zend_Log)) {
242 require_once 'Zend/Translate/Exception.php';
243 throw new Zend_Translate_Exception('Instance of Zend_Log expected for option log');
246 $this->_options[$key] = $option;
247 $change = true;
251 if ($locale !== null) {
252 $this->setLocale($locale);
255 if (isset(self::$_cache) and ($change == true)) {
256 $id = 'Zend_Translate_' . $this->toString() . '_Options';
257 self::$_cache->save( serialize($this->_options), $id, array('Zend_Translate'));
260 return $this;
264 * Returns the adapters name and it's options
266 * @param string|null $optionKey String returns this option
267 * null returns all options
268 * @return integer|string|array|null
270 public function getOptions($optionKey = null)
272 if ($optionKey === null) {
273 return $this->_options;
276 if (isset($this->_options[$optionKey]) === true) {
277 return $this->_options[$optionKey];
280 return null;
284 * Gets locale
286 * @return Zend_Locale|string|null
288 public function getLocale()
290 return $this->_options['locale'];
294 * Sets locale
296 * @param string|Zend_Locale $locale Locale to set
297 * @throws Zend_Translate_Exception
298 * @return Zend_Translate_Adapter Provides fluent interface
300 public function setLocale($locale)
302 if (($locale === "auto") or ($locale === null)) {
303 $this->_automatic = true;
304 } else {
305 $this->_automatic = false;
308 try {
309 $locale = Zend_Locale::findLocale($locale);
310 } catch (Zend_Locale_Exception $e) {
311 require_once 'Zend/Translate/Exception.php';
312 throw new Zend_Translate_Exception("The given Language ({$locale}) does not exist");
315 if (!isset($this->_translate[$locale])) {
316 $temp = explode('_', $locale);
317 if (!isset($this->_translate[$temp[0]]) and !isset($this->_translate[$locale])) {
318 if (!$this->_options['disableNotices']) {
319 if ($this->_options['log']) {
320 $this->_options['log']->notice("The language '{$locale}' has to be added before it can be used.");
321 } else {
322 trigger_error("The language '{$locale}' has to be added before it can be used.", E_USER_NOTICE);
327 $locale = $temp[0];
330 if (empty($this->_translate[$locale])) {
331 if (!$this->_options['disableNotices']) {
332 if ($this->_options['log']) {
333 $this->_options['log']->notice("No translation for the language '{$locale}' available.");
334 } else {
335 trigger_error("No translation for the language '{$locale}' available.", E_USER_NOTICE);
340 if ($this->_options['locale'] != $locale) {
341 $this->_options['locale'] = $locale;
343 if (isset(self::$_cache)) {
344 $id = 'Zend_Translate_' . $this->toString() . '_Options';
345 self::$_cache->save( serialize($this->_options), $id, array('Zend_Translate'));
349 return $this;
353 * Returns the available languages from this adapter
355 * @return array
357 public function getList()
359 $list = array_keys($this->_translate);
360 $result = null;
361 foreach($list as $value) {
362 if (!empty($this->_translate[$value])) {
363 $result[$value] = $value;
366 return $result;
370 * Returns all available message ids from this adapter
371 * If no locale is given, the actual language will be used
373 * @param string|Zend_Locale $locale (optional) Language to return the message ids from
374 * @return array
376 public function getMessageIds($locale = null)
378 if (empty($locale) or !$this->isAvailable($locale)) {
379 $locale = $this->_options['locale'];
382 return array_keys($this->_translate[(string) $locale]);
386 * Returns all available translations from this adapter
387 * If no locale is given, the actual language will be used
388 * If 'all' is given the complete translation dictionary will be returned
390 * @param string|Zend_Locale $locale (optional) Language to return the messages from
391 * @return array
393 public function getMessages($locale = null)
395 if ($locale === 'all') {
396 return $this->_translate;
399 if ((empty($locale) === true) or ($this->isAvailable($locale) === false)) {
400 $locale = $this->_options['locale'];
403 return $this->_translate[(string) $locale];
407 * Is the wished language available ?
409 * @see Zend_Locale
410 * @param string|Zend_Locale $locale Language to search for, identical with locale identifier,
411 * @see Zend_Locale for more information
412 * @return boolean
414 public function isAvailable($locale)
416 $return = isset($this->_translate[(string) $locale]);
417 return $return;
421 * Load translation data
423 * @param mixed $data
424 * @param string|Zend_Locale $locale
425 * @param array $options (optional)
426 * @return array
428 abstract protected function _loadTranslationData($data, $locale, array $options = array());
431 * Internal function for adding translation data
433 * It may be a new language or additional data for existing language
434 * If $clear parameter is true, then translation data for specified
435 * language is replaced and added otherwise
437 * @see Zend_Locale
438 * @param array|string $data Translation data
439 * @param string|Zend_Locale $locale Locale/Language to add data for, identical with locale identifier,
440 * @see Zend_Locale for more information
441 * @param array $options (optional) Option for this Adapter
442 * @throws Zend_Translate_Exception
443 * @return Zend_Translate_Adapter Provides fluent interface
445 private function _addTranslationData($data, $locale, array $options = array())
447 try {
448 $locale = Zend_Locale::findLocale($locale);
449 } catch (Zend_Locale_Exception $e) {
450 require_once 'Zend/Translate/Exception.php';
451 throw new Zend_Translate_Exception("The given Language '{$locale}' does not exist");
454 if ($options['clear'] || !isset($this->_translate[$locale])) {
455 $this->_translate[$locale] = array();
458 $read = true;
459 if (isset(self::$_cache)) {
460 $id = 'Zend_Translate_' . md5(serialize($data)) . '_' . $this->toString();
461 $result = self::$_cache->load($id);
462 if ($result) {
463 $temp = unserialize($result);
464 $read = false;
468 if ($read) {
469 $temp = $this->_loadTranslationData($data, $locale, $options);
472 if (empty($temp)) {
473 $temp = array();
476 $keys = array_keys($temp);
477 foreach($keys as $key) {
478 if (!isset($this->_translate[$key])) {
479 $this->_translate[$key] = array();
482 $this->_translate[$key] = $temp[$key] + $this->_translate[$key];
485 if ($this->_automatic === true) {
486 $find = new Zend_Locale($locale);
487 $browser = $find->getEnvironment() + $find->getBrowser();
488 arsort($browser);
489 foreach($browser as $language => $quality) {
490 if (isset($this->_translate[$language])) {
491 $this->_options['locale'] = $language;
492 break;
497 if (($read) and (isset(self::$_cache))) {
498 $id = 'Zend_Translate_' . md5(serialize($data)) . '_' . $this->toString();
499 self::$_cache->save( serialize($temp), $id, array('Zend_Translate'));
502 return $this;
506 * Translates the given string
507 * returns the translation
509 * @see Zend_Locale
510 * @param string|array $messageId Translation string, or Array for plural translations
511 * @param string|Zend_Locale $locale (optional) Locale/Language to use, identical with
512 * locale identifier, @see Zend_Locale for more information
513 * @return string
515 public function translate($messageId, $locale = null)
517 if ($locale === null) {
518 $locale = $this->_options['locale'];
521 $plural = null;
522 if (is_array($messageId)) {
523 if (count($messageId) > 2) {
524 $number = array_pop($messageId);
525 if (!is_numeric($number)) {
526 $plocale = $number;
527 $number = array_pop($messageId);
528 } else {
529 $plocale = 'en';
532 $plural = $messageId;
533 $messageId = $messageId[0];
534 } else {
535 $messageId = $messageId[0];
539 if (!Zend_Locale::isLocale($locale, true, false)) {
540 if (!Zend_Locale::isLocale($locale, false, false)) {
541 // language does not exist, return original string
542 $this->_log($messageId, $locale);
543 if ($plural === null) {
544 return $messageId;
547 $rule = Zend_Translate_Plural::getPlural($number, $plocale);
548 if (!isset($plural[$rule])) {
549 $rule = 0;
552 return $plural[$rule];
555 $locale = new Zend_Locale($locale);
558 $locale = (string) $locale;
559 if (isset($this->_translate[$locale][$messageId])) {
560 // return original translation
561 if ($plural === null) {
562 return $this->_translate[$locale][$messageId];
565 $rule = Zend_Translate_Plural::getPlural($number, $locale);
566 if (isset($this->_translate[$locale][$plural[0]][$rule])) {
567 return $this->_translate[$locale][$plural[0]][$rule];
569 } else if (strlen($locale) != 2) {
570 // faster than creating a new locale and separate the leading part
571 $locale = substr($locale, 0, -strlen(strrchr($locale, '_')));
573 if (isset($this->_translate[$locale][$messageId])) {
574 // return regionless translation (en_US -> en)
575 if ($plural === null) {
576 return $this->_translate[$locale][$messageId];
579 $rule = Zend_Translate_Plural::getPlural($number, $locale);
580 if (isset($this->_translate[$locale][$plural[0]][$rule])) {
581 return $this->_translate[$locale][$plural[0]][$rule];
586 $this->_log($messageId, $locale);
587 if ($plural === null) {
588 return $messageId;
591 $rule = Zend_Translate_Plural::getPlural($number, $plocale);
592 if (!isset($plural[$rule])) {
593 $rule = 0;
596 return $plural[$rule];
600 * Translates the given string using plural notations
601 * Returns the translated string
603 * @see Zend_Locale
604 * @param string $singular Singular translation string
605 * @param string $plural Plural translation string
606 * @param integer $number Number for detecting the correct plural
607 * @param string|Zend_Locale $locale (Optional) Locale/Language to use, identical with
608 * locale identifier, @see Zend_Locale for more information
609 * @return string
611 public function plural($singular, $plural, $number, $locale = null)
613 return $this->translate(array($singular, $plural, $number), $locale);
617 * Logs a message when the log option is set
619 * @param string $message Message to log
620 * @param String $locale Locale to log
622 protected function _log($message, $locale) {
623 if ($this->_options['logUntranslated']) {
624 $message = str_replace('%message%', $message, $this->_options['logMessage']);
625 $message = str_replace('%locale%', $locale, $message);
626 if ($this->_options['log']) {
627 $this->_options['log']->notice($message);
628 } else {
629 trigger_error($message, E_USER_NOTICE);
635 * Translates the given string
636 * returns the translation
638 * @param string $messageId Translation string
639 * @param string|Zend_Locale $locale (optional) Locale/Language to use, identical with locale
640 * identifier, @see Zend_Locale for more information
641 * @return string
643 public function _($messageId, $locale = null)
645 return $this->translate($messageId, $locale);
649 * Checks if a string is translated within the source or not
650 * returns boolean
652 * @param string $messageId Translation string
653 * @param boolean $original (optional) Allow translation only for original language
654 * when true, a translation for 'en_US' would give false when it can
655 * be translated with 'en' only
656 * @param string|Zend_Locale $locale (optional) Locale/Language to use, identical with locale identifier,
657 * see Zend_Locale for more information
658 * @return boolean
660 public function isTranslated($messageId, $original = false, $locale = null)
662 if (($original !== false) and ($original !== true)) {
663 $locale = $original;
664 $original = false;
667 if ($locale === null) {
668 $locale = $this->_options['locale'];
671 if (!Zend_Locale::isLocale($locale, true, false)) {
672 if (!Zend_Locale::isLocale($locale, false, false)) {
673 // language does not exist, return original string
674 $this->_log($messageId, $locale);
675 return false;
678 $locale = new Zend_Locale($locale);
681 $locale = (string) $locale;
682 if (isset($this->_translate[$locale][$messageId]) === true) {
683 // return original translation
684 return true;
685 } else if ((strlen($locale) != 2) and ($original === false)) {
686 // faster than creating a new locale and separate the leading part
687 $locale = substr($locale, 0, -strlen(strrchr($locale, '_')));
689 if (isset($this->_translate[$locale][$messageId]) === true) {
690 // return regionless translation (en_US -> en)
691 return true;
695 // No translation found, return original
696 $this->_log($messageId, $locale);
697 return false;
701 * Returns the set cache
703 * @return Zend_Cache_Core The set cache
705 public static function getCache()
707 return self::$_cache;
711 * Sets a cache for all Zend_Translate_Adapters
713 * @param Zend_Cache_Core $cache Cache to store to
715 public static function setCache(Zend_Cache_Core $cache)
717 self::$_cache = $cache;
721 * Returns true when a cache is set
723 * @return boolean
725 public static function hasCache()
727 if (self::$_cache !== null) {
728 return true;
731 return false;
735 * Removes any set cache
737 * @return void
739 public static function removeCache()
741 self::$_cache = null;
745 * Clears all set cache data
747 * @return void
749 public static function clearCache()
751 require_once 'Zend/Cache.php';
752 self::$_cache->clean(Zend_Cache::CLEANING_MODE_MATCHING_TAG, array('Zend_Translate'));
756 * Returns the adapter name
758 * @return string
760 abstract public function toString();