PageRenderTime 66ms CodeModel.GetById 23ms RepoModel.GetById 1ms app.codeStats 0ms

/DevApp/library/ServerLibraries/ZendFramework/1.7/library/Zend/Translate/Adapter.php

http://firephp.googlecode.com/
PHP | 633 lines | 329 code | 65 blank | 239 comment | 69 complexity | 3c60ac873996a25b62d9f4eae05e6490 MD5 | raw file
Possible License(s): BSD-3-Clause, LGPL-2.0, MIT, Apache-2.0
  1. <?php
  2. /**
  3. * Zend Framework
  4. *
  5. * LICENSE
  6. *
  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.
  14. *
  15. * @category Zend
  16. * @package Zend_Translate
  17. * @subpackage Zend_Translate_Adapter
  18. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  19. * @license http://framework.zend.com/license/new-bsd New BSD License
  20. * @version $Id: Date.php 2498 2006-12-23 22:13:38Z thomas $
  21. */
  22. /**
  23. * @see Zend_Locale
  24. */
  25. require_once 'Zend/Locale.php';
  26. /**
  27. * Basic adapter class for each translation source adapter
  28. *
  29. * @category Zend
  30. * @package Zend_Translate
  31. * @subpackage Zend_Translate_Adapter
  32. * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com)
  33. * @license http://framework.zend.com/license/new-bsd New BSD License
  34. */
  35. abstract class Zend_Translate_Adapter {
  36. /**
  37. * Shows if locale detection is in automatic level
  38. * @var boolean
  39. */
  40. private $_automatic = true;
  41. /**
  42. * Internal cache for all adapters
  43. * @var Zend_Cache_Core
  44. */
  45. protected static $_cache = null;
  46. /**
  47. * Scans for the locale within the name of the directory
  48. * @constant integer
  49. */
  50. const LOCALE_DIRECTORY = 'directory';
  51. /**
  52. * Scans for the locale within the name of the file
  53. * @constant integer
  54. */
  55. const LOCALE_FILENAME = 'filename';
  56. /**
  57. * Array with all options, each adapter can have own additional options
  58. * 'clear' => clears already loaded data when adding new files
  59. * 'scan' => searches for translation files using the LOCALE constants
  60. * 'locale' => the actual set locale to use
  61. * @var array
  62. */
  63. protected $_options = array(
  64. 'clear' => false,
  65. 'scan' => null,
  66. 'locale' => 'auto',
  67. 'ignore' => '.',
  68. 'disableNotices' => false,
  69. );
  70. /**
  71. * Translation table
  72. * @var array
  73. */
  74. protected $_translate = array();
  75. /**
  76. * Generates the adapter
  77. *
  78. * @param string|array $data Translation data or filename for this adapter
  79. * @param string|Zend_Locale $locale (optional) Locale/Language to set, identical with Locale
  80. * identifiers see Zend_Locale for more information
  81. * @param array $options (optional) Options for the adaptor
  82. * @throws Zend_Translate_Exception
  83. * @return void
  84. */
  85. public function __construct($data, $locale = null, array $options = array())
  86. {
  87. if (isset(self::$_cache)) {
  88. $id = 'Zend_Translate_' . $this->toString() . '_Options';
  89. $result = self::$_cache->load($id);
  90. if ($result) {
  91. $this->_options = unserialize($result);
  92. }
  93. }
  94. if (($locale === "auto") or ($locale === null)) {
  95. $this->_automatic = true;
  96. } else {
  97. $this->_automatic = false;
  98. }
  99. $this->addTranslation($data, $locale, $options);
  100. $this->setLocale($locale);
  101. }
  102. /**
  103. * Add translation data
  104. *
  105. * It may be a new language or additional data for existing language
  106. * If $clear parameter is true, then translation data for specified
  107. * language is replaced and added otherwise
  108. *
  109. * @param array|string $data Translation data
  110. * @param string|Zend_Locale $locale (optional) Locale/Language to add data for, identical
  111. * with locale identifier, see Zend_Locale for more information
  112. * @param array $options (optional) Option for this Adapter
  113. * @throws Zend_Translate_Exception
  114. * @return Zend_Translate_Adapter Provides fluent interface
  115. */
  116. public function addTranslation($data, $locale = null, array $options = array())
  117. {
  118. try {
  119. $locale = Zend_Locale::findLocale($locale);
  120. } catch (Zend_Locale_Exception $e) {
  121. require_once 'Zend/Translate/Exception.php';
  122. throw new Zend_Translate_Exception("The given Language '{$locale}' does not exist");
  123. }
  124. $originate = (string) $locale;
  125. $this->setOptions($options);
  126. if (is_string($data) and is_dir($data)) {
  127. $data = realpath($data);
  128. $prev = '';
  129. foreach (new RecursiveIteratorIterator(
  130. new RecursiveDirectoryIterator($data, RecursiveDirectoryIterator::KEY_AS_PATHNAME),
  131. RecursiveIteratorIterator::SELF_FIRST) as $directory => $info) {
  132. $file = $info->getFilename();
  133. if (strpos($directory, DIRECTORY_SEPARATOR . $this->_options['ignore']) !== false) {
  134. // ignore files matching first characters from option 'ignore' and all files below
  135. continue;
  136. }
  137. if ($info->isDir()) {
  138. // pathname as locale
  139. if (($this->_options['scan'] === self::LOCALE_DIRECTORY) and (Zend_Locale::isLocale($file, true, false))) {
  140. if (strlen($prev) <= strlen($file)) {
  141. $locale = $file;
  142. $prev = (string) $locale;
  143. }
  144. }
  145. } else if ($info->isFile()) {
  146. // filename as locale
  147. if ($this->_options['scan'] === self::LOCALE_FILENAME) {
  148. $filename = explode('.', $file);
  149. array_pop($filename);
  150. $filename = implode('.', $filename);
  151. if (Zend_Locale::isLocale((string) $filename, true, false)) {
  152. $locale = (string) $filename;
  153. } else {
  154. $parts = explode('.', $file);
  155. $parts2 = array();
  156. foreach($parts as $token) {
  157. $parts2 += explode('_', $token);
  158. }
  159. $parts = array_merge($parts, $parts2);
  160. $parts2 = array();
  161. foreach($parts as $token) {
  162. $parts2 += explode('-', $token);
  163. }
  164. $parts = array_merge($parts, $parts2);
  165. $parts = array_unique($parts);
  166. $prev = '';
  167. foreach($parts as $token) {
  168. if (Zend_Locale::isLocale($token, true, false)) {
  169. if (strlen($prev) <= strlen($token)) {
  170. $locale = $token;
  171. $prev = $token;
  172. }
  173. }
  174. }
  175. }
  176. }
  177. try {
  178. $this->_addTranslationData($info->getPathname(), (string) $locale, $this->_options);
  179. if ((isset($this->_translate[(string) $locale]) === true) and (count($this->_translate[(string) $locale]) > 0)) {
  180. $this->setLocale($locale);
  181. }
  182. } catch (Zend_Translate_Exception $e) {
  183. // ignore failed sources while scanning
  184. }
  185. }
  186. }
  187. } else {
  188. $this->_addTranslationData($data, (string) $locale, $this->_options);
  189. if ((isset($this->_translate[(string) $locale]) === true) and (count($this->_translate[(string) $locale]) > 0)) {
  190. $this->setLocale($locale);
  191. }
  192. }
  193. if ((isset($this->_translate[$originate]) === true) and (count($this->_translate[$originate]) > 0)) {
  194. $this->setLocale($originate);
  195. }
  196. return $this;
  197. }
  198. /**
  199. * Sets new adapter options
  200. *
  201. * @param array $options Adapter options
  202. * @throws Zend_Translate_Exception
  203. * @return Zend_Translate_Adapter Provides fluent interface
  204. */
  205. public function setOptions(array $options = array())
  206. {
  207. $change = false;
  208. foreach ($options as $key => $option) {
  209. if ($key == "locale") {
  210. $this->setLocale($option);
  211. } else if ((isset($this->_options[$key]) and ($this->_options[$key] != $option)) or
  212. !isset($this->_options[$key])) {
  213. $this->_options[$key] = $option;
  214. $change = true;
  215. }
  216. }
  217. if (isset(self::$_cache) and ($change == true)) {
  218. $id = 'Zend_Translate_' . $this->toString() . '_Options';
  219. self::$_cache->save( serialize($this->_options), $id);
  220. }
  221. return $this;
  222. }
  223. /**
  224. * Returns the adapters name and it's options
  225. *
  226. * @param string|null $optionKey String returns this option
  227. * null returns all options
  228. * @return integer|string|array|null
  229. */
  230. public function getOptions($optionKey = null)
  231. {
  232. if ($optionKey === null) {
  233. return $this->_options;
  234. }
  235. if (isset($this->_options[$optionKey]) === true) {
  236. return $this->_options[$optionKey];
  237. }
  238. return null;
  239. }
  240. /**
  241. * Gets locale
  242. *
  243. * @return Zend_Locale|string|null
  244. */
  245. public function getLocale()
  246. {
  247. return $this->_options['locale'];
  248. }
  249. /**
  250. * Sets locale
  251. *
  252. * @param string|Zend_Locale $locale Locale to set
  253. * @throws Zend_Translate_Exception
  254. * @return Zend_Translate_Adapter Provides fluent interface
  255. */
  256. public function setLocale($locale)
  257. {
  258. if (($locale === "auto") or ($locale === null)) {
  259. $this->_automatic = true;
  260. } else {
  261. $this->_automatic = false;
  262. }
  263. try {
  264. $locale = Zend_Locale::findLocale($locale);
  265. } catch (Zend_Locale_Exception $e) {
  266. require_once 'Zend/Translate/Exception.php';
  267. throw new Zend_Translate_Exception("The given Language ({$locale}) does not exist");
  268. }
  269. if (!isset($this->_translate[$locale])) {
  270. $temp = explode('_', $locale);
  271. if (!isset($this->_translate[$temp[0]]) and !isset($this->_translate[$locale])) {
  272. // Should we suppress notices ?
  273. if ($this->_options['disableNotices'] === false) {
  274. // throwing a notice due to possible problems on locale setting
  275. trigger_error("The language '{$locale}' has to be added before it can be used.", E_USER_NOTICE);
  276. }
  277. }
  278. $locale = $temp[0];
  279. }
  280. if (empty($this->_translate[$locale])) {
  281. // Should we suppress notices ?
  282. if ($this->_options['disableNotices'] === false) {
  283. // throwing a notice due to possible problems on locale setting
  284. trigger_error("No translation for the language '{$locale}' available.", E_USER_NOTICE);
  285. }
  286. }
  287. if ($this->_options['locale'] != $locale) {
  288. $this->_options['locale'] = $locale;
  289. if (isset(self::$_cache)) {
  290. $id = 'Zend_Translate_' . $this->toString() . '_Options';
  291. self::$_cache->save( serialize($this->_options), $id);
  292. }
  293. }
  294. return $this;
  295. }
  296. /**
  297. * Returns the available languages from this adapter
  298. *
  299. * @return array
  300. */
  301. public function getList()
  302. {
  303. $list = array_keys($this->_translate);
  304. $result = null;
  305. foreach($list as $value) {
  306. if (!empty($this->_translate[$value])) {
  307. $result[$value] = $value;
  308. }
  309. }
  310. return $result;
  311. }
  312. /**
  313. * Returns all available message ids from this adapter
  314. * If no locale is given, the actual language will be used
  315. *
  316. * @param string|Zend_Locale $locale (optional) Language to return the message ids from
  317. * @return array
  318. */
  319. public function getMessageIds($locale = null)
  320. {
  321. if (empty($locale) or !$this->isAvailable($locale)) {
  322. $locale = $this->_options['locale'];
  323. }
  324. return array_keys($this->_translate[(string) $locale]);
  325. }
  326. /**
  327. * Returns all available translations from this adapter
  328. * If no locale is given, the actual language will be used
  329. * If 'all' is given the complete translation dictionary will be returned
  330. *
  331. * @param string|Zend_Locale $locale (optional) Language to return the messages from
  332. * @return array
  333. */
  334. public function getMessages($locale = null)
  335. {
  336. if ($locale === 'all') {
  337. return $this->_translate;
  338. }
  339. if ((empty($locale) === true) or ($this->isAvailable($locale) === false)) {
  340. $locale = $this->_options['locale'];
  341. }
  342. return $this->_translate[(string) $locale];
  343. }
  344. /**
  345. * Is the wished language available ?
  346. *
  347. * @see Zend_Locale
  348. * @param string|Zend_Locale $locale Language to search for, identical with locale identifier,
  349. * @see Zend_Locale for more information
  350. * @return boolean
  351. */
  352. public function isAvailable($locale)
  353. {
  354. $return = isset($this->_translate[(string) $locale]);
  355. return $return;
  356. }
  357. /**
  358. * Load translation data
  359. *
  360. * @param mixed $data
  361. * @param string|Zend_Locale $locale
  362. * @param array $options (optional)
  363. * @return void
  364. */
  365. abstract protected function _loadTranslationData($data, $locale, array $options = array());
  366. /**
  367. * Internal function for adding translation data
  368. *
  369. * It may be a new language or additional data for existing language
  370. * If $clear parameter is true, then translation data for specified
  371. * language is replaced and added otherwise
  372. *
  373. * @see Zend_Locale
  374. * @param array|string $data Translation data
  375. * @param string|Zend_Locale $locale Locale/Language to add data for, identical with locale identifier,
  376. * @see Zend_Locale for more information
  377. * @param array $options (optional) Option for this Adapter
  378. * @throws Zend_Translate_Exception
  379. * @return Zend_Translate_Adapter Provides fluent interface
  380. */
  381. private function _addTranslationData($data, $locale, array $options = array())
  382. {
  383. try {
  384. $locale = Zend_Locale::findLocale($locale);
  385. } catch (Zend_Locale_Exception $e) {
  386. require_once 'Zend/Translate/Exception.php';
  387. throw new Zend_Translate_Exception("The given Language '{$locale}' does not exist");
  388. }
  389. if (isset($this->_translate[$locale]) === false) {
  390. $this->_translate[$locale] = array();
  391. }
  392. $read = true;
  393. if (isset(self::$_cache)) {
  394. $id = 'Zend_Translate_' . preg_replace('/[^a-zA-Z0-9_]/', '_', $data) . '_' . $locale . '_' . $this->toString();
  395. $result = self::$_cache->load($id);
  396. if ($result) {
  397. $this->_translate[$locale] = unserialize($result);
  398. $read = false;
  399. }
  400. }
  401. if ($read) {
  402. $this->_loadTranslationData($data, $locale, $options);
  403. }
  404. if ($this->_automatic === true) {
  405. $find = new Zend_Locale($locale);
  406. $browser = $find->getEnvironment() + $find->getBrowser();
  407. arsort($browser);
  408. foreach($browser as $language => $quality) {
  409. if (isset($this->_translate[$language]) === true) {
  410. $this->_options['locale'] = $language;
  411. break;
  412. }
  413. }
  414. }
  415. if (($read) and (isset(self::$_cache))) {
  416. $id = 'Zend_Translate_' . preg_replace('/[^a-zA-Z0-9_]/', '_', $data) . '_' . $locale . '_' . $this->toString();
  417. self::$_cache->save( serialize($this->_translate[$locale]), $id);
  418. }
  419. return $this;
  420. }
  421. /**
  422. * Translates the given string
  423. * returns the translation
  424. *
  425. * @see Zend_Locale
  426. * @param string $messageId Translation string
  427. * @param string|Zend_Locale $locale (optional) Locale/Language to use, identical with
  428. * locale identifier, @see Zend_Locale for more information
  429. * @return string
  430. */
  431. public function translate($messageId, $locale = null)
  432. {
  433. if ($locale === null) {
  434. $locale = $this->_options['locale'];
  435. }
  436. if (!Zend_Locale::isLocale($locale, true, false)) {
  437. if (!Zend_Locale::isLocale($locale, false, false)) {
  438. // language does not exist, return original string
  439. return $messageId;
  440. }
  441. $locale = new Zend_Locale($locale);
  442. }
  443. $locale = (string) $locale;
  444. if (isset($this->_translate[$locale][$messageId]) === true) {
  445. // return original translation
  446. return $this->_translate[$locale][$messageId];
  447. } else if (strlen($locale) != 2) {
  448. // faster than creating a new locale and separate the leading part
  449. $locale = substr($locale, 0, -strlen(strrchr($locale, '_')));
  450. if (isset($this->_translate[$locale][$messageId]) === true) {
  451. // return regionless translation (en_US -> en)
  452. return $this->_translate[$locale][$messageId];
  453. }
  454. }
  455. // no translation found, return original
  456. return $messageId;
  457. }
  458. /**
  459. * Translates the given string
  460. * returns the translation
  461. *
  462. * @param string $messageId Translation string
  463. * @param string|Zend_Locale $locale (optional) Locale/Language to use, identical with locale
  464. * identifier, @see Zend_Locale for more information
  465. * @return string
  466. */
  467. public function _($messageId, $locale = null)
  468. {
  469. return $this->translate($messageId, $locale);
  470. }
  471. /**
  472. * Checks if a string is translated within the source or not
  473. * returns boolean
  474. *
  475. * @param string $messageId Translation string
  476. * @param boolean $original (optional) Allow translation only for original language
  477. * when true, a translation for 'en_US' would give false when it can
  478. * be translated with 'en' only
  479. * @param string|Zend_Locale $locale (optional) Locale/Language to use, identical with locale identifier,
  480. * see Zend_Locale for more information
  481. * @return boolean
  482. */
  483. public function isTranslated($messageId, $original = false, $locale = null)
  484. {
  485. if (($original !== false) and ($original !== true)) {
  486. $locale = $original;
  487. $original = false;
  488. }
  489. if ($locale === null) {
  490. $locale = $this->_options['locale'];
  491. }
  492. if (!Zend_Locale::isLocale($locale, true, false)) {
  493. if (!Zend_Locale::isLocale($locale, false, false)) {
  494. // language does not exist, return original string
  495. return false;
  496. }
  497. $locale = new Zend_Locale();
  498. }
  499. $locale = (string) $locale;
  500. if (isset($this->_translate[$locale][$messageId]) === true) {
  501. // return original translation
  502. return true;
  503. } else if ((strlen($locale) != 2) and ($original === false)) {
  504. // faster than creating a new locale and separate the leading part
  505. $locale = substr($locale, 0, -strlen(strrchr($locale, '_')));
  506. if (isset($this->_translate[$locale][$messageId]) === true) {
  507. // return regionless translation (en_US -> en)
  508. return true;
  509. }
  510. }
  511. // No translation found, return original
  512. return false;
  513. }
  514. /**
  515. * Returns the set cache
  516. *
  517. * @return Zend_Cache_Core The set cache
  518. */
  519. public static function getCache()
  520. {
  521. return self::$_cache;
  522. }
  523. /**
  524. * Sets a cache for all Zend_Translate_Adapters
  525. *
  526. * @param Zend_Cache_Core $cache Cache to store to
  527. */
  528. public static function setCache(Zend_Cache_Core $cache)
  529. {
  530. self::$_cache = $cache;
  531. }
  532. /**
  533. * Returns true when a cache is set
  534. *
  535. * @return boolean
  536. */
  537. public static function hasCache()
  538. {
  539. if (self::$_cache !== null) {
  540. return true;
  541. }
  542. return false;
  543. }
  544. /**
  545. * Removes any set cache
  546. *
  547. * @return void
  548. */
  549. public static function removeCache()
  550. {
  551. self::$_cache = null;
  552. }
  553. /**
  554. * Clears all set cache data
  555. *
  556. * @return void
  557. */
  558. public static function clearCache()
  559. {
  560. self::$_cache->clean();
  561. }
  562. /**
  563. * Returns the adapter name
  564. *
  565. * @return string
  566. */
  567. abstract public function toString();
  568. }