1: <?php
2: 3: 4: 5: 6: 7: 8: 9: 10: 11: 12: 13: 14: 15: 16: 17: 18: 19: 20: 21: 22: 23: 24: 25:
26:
27: 28: 29: 30: 31:
32: class Mage_Core_Model_Translate
33: {
34: const CSV_SEPARATOR = ',';
35: const SCOPE_SEPARATOR = '::';
36: const CACHE_TAG = 'translate';
37:
38: const CONFIG_KEY_AREA = 'area';
39: const CONFIG_KEY_LOCALE = 'locale';
40: const CONFIG_KEY_STORE = 'store';
41: const CONFIG_KEY_DESIGN_PACKAGE = 'package';
42: const CONFIG_KEY_DESIGN_THEME = 'theme';
43:
44: 45: 46: 47: 48:
49: protected $_locale;
50:
51: 52: 53: 54: 55:
56: protected $_translate;
57:
58: 59: 60: 61: 62:
63: protected $_config;
64:
65: protected $_useCache = true;
66:
67: 68: 69: 70: 71:
72: protected $_cacheId;
73:
74: 75: 76: 77: 78:
79: protected $_data = array();
80:
81: 82: 83: 84: 85:
86: protected $_dataScope;
87:
88: 89: 90: 91: 92:
93: protected $_translateInline;
94:
95: 96: 97: 98: 99:
100: protected $_canUseInline = true;
101:
102: public function __construct()
103: {
104: }
105:
106: 107: 108: 109: 110: 111:
112: public function init($area, $forceReload = false)
113: {
114: $this->setConfig(array(self::CONFIG_KEY_AREA=>$area));
115:
116: $this->_translateInline = Mage::getSingleton('core/translate_inline')
117: ->isAllowed($area=='adminhtml' ? 'admin' : null);
118:
119: if (!$forceReload) {
120: if ($this->_canUseCache()) {
121: $this->_data = $this->_loadCache();
122: if ($this->_data !== false) {
123: return $this;
124: }
125: }
126: Mage::app()->removeCache($this->getCacheId());
127: }
128:
129: $this->_data = array();
130:
131: foreach ($this->getModulesConfig() as $moduleName=>$info) {
132: $info = $info->asArray();
133: $this->_loadModuleTranslation($moduleName, $info['files'], $forceReload);
134: }
135:
136: $this->_loadThemeTranslation($forceReload);
137: $this->_loadDbTranslation($forceReload);
138:
139: if (!$forceReload && $this->_canUseCache()) {
140: $this->_saveCache();
141: }
142:
143: return $this;
144: }
145:
146: 147: 148: 149: 150:
151: public function getModulesConfig()
152: {
153: if (!Mage::getConfig()->getNode($this->getConfig(self::CONFIG_KEY_AREA).'/translate/modules')) {
154: return array();
155: }
156:
157: $config = Mage::getConfig()->getNode($this->getConfig(self::CONFIG_KEY_AREA).'/translate/modules')->children();
158: if (!$config) {
159: return array();
160: }
161: return $config;
162: }
163:
164: 165: 166: 167: 168: 169:
170: public function setConfig($config)
171: {
172: $this->_config = $config;
173: if (!isset($this->_config[self::CONFIG_KEY_LOCALE])) {
174: $this->_config[self::CONFIG_KEY_LOCALE] = $this->getLocale();
175: }
176: if (!isset($this->_config[self::CONFIG_KEY_STORE])) {
177: $this->_config[self::CONFIG_KEY_STORE] = Mage::app()->getStore()->getId();
178: }
179: if (!isset($this->_config[self::CONFIG_KEY_DESIGN_PACKAGE])) {
180: $this->_config[self::CONFIG_KEY_DESIGN_PACKAGE] = Mage::getDesign()->getPackageName();
181: }
182: if (!isset($this->_config[self::CONFIG_KEY_DESIGN_THEME])) {
183: $this->_config[self::CONFIG_KEY_DESIGN_THEME] = Mage::getDesign()->getTheme('locale');
184: }
185: return $this;
186: }
187:
188: 189: 190: 191: 192: 193:
194: public function getConfig($key)
195: {
196: if (isset($this->_config[$key])) {
197: return $this->_config[$key];
198: }
199: return null;
200: }
201:
202: 203: 204: 205: 206: 207: 208:
209: protected function _loadModuleTranslation($moduleName, $files, $forceReload=false)
210: {
211: foreach ($files as $file) {
212: $file = $this->_getModuleFilePath($moduleName, $file);
213: $this->_addData($this->_getFileData($file), $moduleName, $forceReload);
214: }
215: return $this;
216: }
217:
218: 219: 220: 221: 222: 223: 224:
225: protected function _addData($data, $scope, $forceReload=false)
226: {
227: foreach ($data as $key => $value) {
228: if ($key === $value) {
229: continue;
230: }
231: $key = $this->_prepareDataString($key);
232: $value = $this->_prepareDataString($value);
233: if ($scope && isset($this->_dataScope[$key]) && !$forceReload ) {
234: 235: 236:
237: $scopeKey = $this->_dataScope[$key] . self::SCOPE_SEPARATOR . $key;
238: if (!isset($this->_data[$scopeKey])) {
239: if (isset($this->_data[$key])) {
240: $this->_data[$scopeKey] = $this->_data[$key];
241: 242: 243:
244: if (Mage::getIsDeveloperMode()) {
245: unset($this->_data[$key]);
246: }
247: }
248: }
249: $scopeKey = $scope . self::SCOPE_SEPARATOR . $key;
250: $this->_data[$scopeKey] = $value;
251: }
252: else {
253: $this->_data[$key] = $value;
254: $this->_dataScope[$key]= $scope;
255: }
256: }
257: return $this;
258: }
259:
260: protected function _prepareDataString($string)
261: {
262: return str_replace('""', '"', $string);
263: }
264:
265: 266: 267: 268: 269:
270: protected function _loadThemeTranslation($forceReload = false)
271: {
272: $file = Mage::getDesign()->getLocaleFileName('translate.csv');
273: $this->_addData($this->_getFileData($file), false, $forceReload);
274: return $this;
275: }
276:
277: 278: 279: 280: 281:
282: protected function _loadDbTranslation($forceReload = false)
283: {
284: $arr = $this->getResource()->getTranslationArray(null, $this->getLocale());
285: $this->_addData($arr, $this->getConfig(self::CONFIG_KEY_STORE), $forceReload);
286: return $this;
287: }
288:
289: 290: 291: 292: 293: 294:
295: protected function _getModuleFilePath($module, $fileName)
296: {
297:
298: $file = Mage::getBaseDir('locale');
299: $file.= DS.$this->getLocale().DS.$fileName;
300: return $file;
301: }
302:
303: 304: 305: 306: 307: 308:
309: protected function _getFileData($file)
310: {
311: $data = array();
312: if (file_exists($file)) {
313: $parser = new Varien_File_Csv();
314: $parser->setDelimiter(self::CSV_SEPARATOR);
315: $data = $parser->getDataPairs($file);
316: }
317: return $data;
318: }
319:
320: 321: 322: 323: 324:
325: public function getData()
326: {
327: if (is_null($this->_data)) {
328: return array();
329:
330: }
331: return $this->_data;
332: }
333:
334: 335: 336: 337: 338:
339: public function getLocale()
340: {
341: if (is_null($this->_locale)) {
342: $this->_locale = Mage::app()->getLocale()->getLocaleCode();
343: }
344: return $this->_locale;
345: }
346:
347: public function setLocale( $locale )
348: {
349: $this->_locale = $locale;
350: return $this;
351: }
352:
353: 354: 355: 356: 357:
358: public function getResource()
359: {
360: return Mage::getResourceSingleton('core/translate');
361: }
362:
363: 364: 365: 366: 367:
368: public function getTranslate()
369: {
370: if (is_null($this->_translate)) {
371: $this->_translate = new Zend_Translate('array', $this->getData(), $this->getLocale());
372: }
373: return $this->_translate;
374: }
375:
376: 377: 378: 379: 380: 381:
382: public function translate($args)
383: {
384: $text = array_shift($args);
385:
386: if (is_string($text) && ''==$text
387: || is_null($text)
388: || is_bool($text) && false===$text
389: || is_object($text) && ''==$text->getText()) {
390: return '';
391: }
392: if ($text instanceof Mage_Core_Model_Translate_Expr) {
393: $code = $text->getCode(self::SCOPE_SEPARATOR);
394: $module = $text->getModule();
395: $text = $text->getText();
396: $translated = $this->_getTranslatedString($text, $code);
397: }
398: else {
399: if (!empty($_REQUEST['theme'])) {
400: $module = 'frontend/default/'.$_REQUEST['theme'];
401: } else {
402: $module = 'frontend/default/default';
403: }
404: $code = $module.self::SCOPE_SEPARATOR.$text;
405: $translated = $this->_getTranslatedString($text, $code);
406: }
407:
408:
409:
410:
411: $result = @vsprintf($translated, $args);
412: if ($result === false) {
413: $result = $translated;
414: }
415:
416: if ($this->_translateInline && $this->getTranslateInline()) {
417: if (strpos($result, '{{{')===false || strpos($result, '}}}')===false || strpos($result, '}}{{')===false) {
418: $result = '{{{'.$result.'}}{{'.$translated.'}}{{'.$text.'}}{{'.$module.'}}}';
419: }
420: }
421:
422: return $result;
423: }
424:
425: 426: 427: 428: 429: 430:
431: public function setTranslateInline($flag=null)
432: {
433: $this->_canUseInline = (bool) $flag;
434: return $this;
435: }
436:
437: 438: 439: 440: 441:
442: public function getTranslateInline()
443: {
444: return $this->_canUseInline;
445: }
446:
447: 448: 449: 450: 451: 452: 453: 454:
455: public function getTemplateFile($file, $type, $localeCode=null)
456: {
457: if (is_null($localeCode) || preg_match('/[^a-zA-Z_]/', $localeCode)) {
458: $localeCode = $this->getLocale();
459: }
460:
461: $filePath = Mage::getBaseDir('locale') . DS
462: . $localeCode . DS . 'template' . DS . $type . DS . $file;
463:
464: if (!file_exists($filePath)) {
465: $filePath = Mage::getBaseDir('locale') . DS
466: . Mage::app()->getLocale()->getDefaultLocale()
467: . DS . 'template' . DS . $type . DS . $file;
468: }
469:
470: if (!file_exists($filePath)) {
471: $filePath = Mage::getBaseDir('locale') . DS
472: . Mage_Core_Model_Locale::DEFAULT_LOCALE
473: . DS . 'template' . DS . $type . DS . $file;
474: }
475:
476: $ioAdapter = new Varien_Io_File();
477: $ioAdapter->open(array('path' => Mage::getBaseDir('locale')));
478:
479: return (string) $ioAdapter->read($filePath);
480: }
481:
482: 483: 484: 485: 486:
487: public function getCacheId()
488: {
489: if (is_null($this->_cacheId)) {
490: $this->_cacheId = 'translate';
491: if (isset($this->_config[self::CONFIG_KEY_LOCALE])) {
492: $this->_cacheId.= '_'.$this->_config[self::CONFIG_KEY_LOCALE];
493: }
494: if (isset($this->_config[self::CONFIG_KEY_AREA])) {
495: $this->_cacheId.= '_'.$this->_config[self::CONFIG_KEY_AREA];
496: }
497: if (isset($this->_config[self::CONFIG_KEY_STORE])) {
498: $this->_cacheId.= '_'.$this->_config[self::CONFIG_KEY_STORE];
499: }
500: if (isset($this->_config[self::CONFIG_KEY_DESIGN_PACKAGE])) {
501: $this->_cacheId.= '_'.$this->_config[self::CONFIG_KEY_DESIGN_PACKAGE];
502: }
503: if (isset($this->_config[self::CONFIG_KEY_DESIGN_THEME])) {
504: $this->_cacheId.= '_'.$this->_config[self::CONFIG_KEY_DESIGN_THEME];
505: }
506: }
507: return $this->_cacheId;
508: }
509:
510: 511: 512: 513: 514: 515:
516: protected function _loadCache()
517: {
518: if (!$this->_canUseCache()) {
519: return false;
520: }
521: $data = Mage::app()->loadCache($this->getCacheId());
522: $data = unserialize($data);
523: return $data;
524: }
525:
526: 527: 528: 529: 530: 531:
532: protected function _saveCache()
533: {
534: if (!$this->_canUseCache()) {
535: return $this;
536: }
537: Mage::app()->saveCache(serialize($this->getData()), $this->getCacheId(), array(self::CACHE_TAG), null);
538: return $this;
539: }
540:
541: 542: 543: 544: 545:
546: protected function _canUseCache()
547: {
548: return Mage::app()->useCache('translate');
549: }
550:
551: 552: 553: 554: 555: 556: 557:
558: protected function _getTranslatedString($text, $code)
559: {
560: $translated = '';
561: if (array_key_exists($code, $this->getData())) {
562: $translated = $this->_data[$code];
563: }
564: elseif (array_key_exists($text, $this->getData())) {
565: $translated = $this->_data[$text];
566: }
567: else {
568: $translated = $text;
569: }
570: return $translated;
571: }
572: }
573: