[FEATURE] Add Parser for PHP locallang array
authorXavier Perseguers <typo3@perseguers.ch>
Fri, 24 Jun 2011 07:01:41 +0000 (09:01 +0200)
committerSteffen Gebert <steffen.gebert@typo3.org>
Wed, 6 Jul 2011 10:03:17 +0000 (12:03 +0200)
Implement the parser to support LLPHP file as localization file format.

Change-Id: I4e4d66e73d92eae57663b8e905db33a17da5cb2a
Resolves: #27673
Reviewed-on: http://review.typo3.org/2903
Reviewed-by: Steffen Gebert
Tested-by: Steffen Gebert
Reviewed-by: Dmitry Dulepov
Tested-by: Dmitry Dulepov
Reviewed-by: Stefan Neufeind
Tested-by: Stefan Neufeind
typo3/sysext/lang/classes/parser/class.tx_lang_parser_llphp.php
typo3/sysext/lang/lang.php

index 5295899..f2c1abf 100644 (file)
  *
  * @package    TYPO3
  * @subpackage tx_lang
- * @author     Dominique Feyer <dfeyer@reelpeek.net>
+ * @author Dominique Feyer <dfeyer@reelpeek.net>
+ * @author Dmitry Dulepov <dmitry.dulepov@gmail.com>
  */
 class tx_lang_parser_Llphp implements tx_lang_parser {
 
+       /** @var string */
+       protected $cacheFileName;
+
+       /** @var t3lib_cs */
+       protected $csConvObj;
+
+       /** @var string */
+       protected $hashSource;
+
+       /** @var string */
+       protected $sourceCharset;
+
+       /** @var string */
+       protected $targetCharset;
+
+       /**
+        * Initializes the parser.
+        *
+        * @return void
+        */
+       public function __construct() {
+               $this->createCsConvObject();
+       }
+
        /**
         * Returns parsed representation of PHP locallang file.
         *
@@ -41,15 +66,176 @@ class tx_lang_parser_Llphp implements tx_lang_parser {
         * @param string $sourcePath Source file path
         * @param string $languageKey Language key
         * @param string $charset Charset
-        * @return void
+        * @return array
         */
        public function getParsedData($sourcePath, $languageKey, $charset = '') {
-               throw new RuntimeException(
-                       'Parser for plain old PHP array is not yet implemented.',
-                       1301654458
-               );
+               $this->validateParameters($sourcePath, $languageKey);
+               $this->setCharsets($languageKey, $charset);
+               $this->generateCacheFileName($sourcePath, $languageKey);
+
+               if (!file_exists($this->cacheFileName)) {
+                       $LOCAL_LANG = $this->generateCacheFile($sourcePath, $languageKey);
+               } else {
+                       $LOCAL_LANG = $this->getContentFromCacheFile();
+               }
+
+               $xliff = $this->convertToXLIFF($LOCAL_LANG);
+
+               return $xliff;
+       }
+
+       /**
+        * Converts the LOCAL_LANG array to XLIFF structure.
+        *
+        * @param array $LOCAL_LANG
+        * @return array
+        */
+       protected function convertToXLIFF(array $LOCAL_LANG) {
+               foreach ($LOCAL_LANG as &$keysLabels) {
+                       foreach ($keysLabels as &$label) {
+                               $label = array(0 => array(
+                                       'target' => $label,
+                               ));
+                       }
+                       unset($label);
+               }
+               return $LOCAL_LANG;
+       }
+
+       /**
+        * Creates a character conversion object.
+        *
+        * @return void
+        */
+       protected function createCsConvObject() {
+               if (is_object($GLOBALS['LANG'])) {
+                       $this->csConvObj = $GLOBALS['LANG']->csConvObj;
+               } elseif (is_object($GLOBALS['TSFE'])) {
+                       $this->csConvObj = $GLOBALS['TSFE']->csConvObj;
+               } else {
+                       $this->csConvObj = t3lib_div::makeInstance('t3lib_cs');
+               }
+       }
+
+       /**
+        * Generates the cache file.
+        *
+        * @throws RuntimeException
+        * @param string $sourcePath
+        * @param string $languageKey
+        * @return array
+        */
+       protected function generateCacheFile($sourcePath, $languageKey) {
+               $LOCAL_LANG = array();
+
+                       // Get PHP data
+               include($sourcePath);
+               if (!is_array($LOCAL_LANG)) {
+                       $fileName = substr($sourcePath, strlen(PATH_site));
+                       throw new RuntimeException(
+                               'TYPO3 Fatal Error: "' . $fileName . '" is no TYPO3 language file!',
+                               1308898491
+                       );
+               }
+
+                       // Converting the default language (English)
+                       // This needs to be done for a few accented loan words and extension names
+               if (is_array($LOCAL_LANG['default']) && $this->targetCharset !== 'iso-8859-1') {
+                       foreach ($LOCAL_LANG['default'] as &$labelValue) {
+                               $labelValue = $this->csConvObj->conv($labelValue, 'iso-8859-1', $this->targetCharset);
+                       }
+                       unset($labelValue);
+               }
+
+               if ($languageKey !== 'default' && is_array($LOCAL_LANG[$languageKey]) && $this->sourceCharset != $this->targetCharset) {
+                       foreach ($LOCAL_LANG[$languageKey] as &$labelValue) {
+                               $labelValue = $this->csConvObj->conv($labelValue, $this->sourceCharset, $this->targetCharset);
+                       }
+                       unset($labelValue);
+               }
+
+               // Cache the content now:
+               $serContent = array('origFile' => $this->hashSource, 'LOCAL_LANG' => array('default' => $LOCAL_LANG['default'], $languageKey => $LOCAL_LANG[$languageKey]));
+               $res = t3lib_div::writeFileToTypo3tempDir($this->cacheFileName, serialize($serContent));
+               if ($res) {
+                       throw new RuntimeException(
+                               'TYPO3 Fatal Error: "' . $res,
+                               1308898501
+                       );
+               }
+               return $LOCAL_LANG;
+       }
+
+       /**
+        * Generates the name of the cached file.
+        *
+        * @param string $sourcePath
+        * @param string $languageKey
+        * @return void
+        */
+       protected function generateCacheFileName($sourcePath, $languageKey) {
+               $this->hashSource = substr($sourcePath, strlen(PATH_site)) . '|' . date('d-m-Y H:i:s', filemtime($sourcePath)) . '|version=2.3';
+               $this->cacheFileName = PATH_site . 'typo3temp/llxml/' .
+                       substr(basename($sourcePath), 10, 15) .
+                       '_' . t3lib_div::shortMD5($this->hashSource) . '.' . $languageKey .
+                       '.' . $this->targetCharset . '.cache';
+       }
+
+       /**
+        * Obtains the content from the cache file.
+        *
+        * @return array
+        */
+       protected function getContentFromCacheFile() {
+               $serContent = (array)unserialize(file_get_contents($this->cacheFileName));
+               $LOCAL_LANG = $serContent['LOCAL_LANG'];
+               return (array)$LOCAL_LANG;
+       }
+
+       /**
+        * Checks if the file is within the web root.
+        *
+        * @param string $fileName
+        * @return bool
+        */
+       protected function isWithinWebRoot($fileName) {
+               return (bool)t3lib_div::getFileAbsFileName($fileName);
+       }
+
+       /**
+        * Sets character sets for the language key.
+        *
+        * @param string $languageKey
+        * @param string $charset
+        * @return void
+        */
+       protected function setCharsets($languageKey, $charset) {
+               $this->sourceCharset = $this->csConvObj->parse_charset($this->csConvObj->charSetArray[$languageKey]
+                       ? $this->csConvObj->charSetArray[$languageKey] : 'iso-8859-1');
+               if ($charset) {
+                       $this->targetCharset = $this->csConvObj->parse_charset($charset);
+               } elseif ($GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset']) {
+                               // When forceCharset is set, we store ALL labels in this charset!!!
+                       $this->targetCharset = $this->csConvObj->parse_charset($GLOBALS['TYPO3_CONF_VARS']['BE']['forceCharset']);
+               } else {
+                       $this->targetCharset = $this->csConvObj->parse_charset($this->csConvObj->charSetArray[$languageKey]
+                               ? $this->csConvObj->charSetArray[$languageKey] : 'iso-8859-1');
+               }
        }
 
+       /**
+        * Validates parameters for the function.
+        *
+        * @throws RuntimeException
+        * @param string $sourcePath
+        * @param string $languageKey
+        * @return void
+        */
+       protected function validateParameters($sourcePath, $languageKey) {
+               if (!$this->isWithinWebRoot($sourcePath) || !@is_file($sourcePath) || !$languageKey) {
+                       throw new RuntimeException(sprintf('Invalid source path (%s) or languageKey (%s)', $sourcePath, $languageKey), 1309245002);
+               }
+       }
 }
 
 ?>
\ No newline at end of file
index 800c10a..5195dc6 100755 (executable)
@@ -353,11 +353,13 @@ class language {
         * @access      public
         */
        public function getLLL($index, $localLanguage, $hsc = FALSE) {
-                       // Get Local Language
-               if ($localLanguage[$this->lang][$index][0]['target'] !== '') {
-                       $output = $this->hscAndCharConv($localLanguage[$this->lang][$index][0]['target'], $hsc);
+                       // Get Local Language. Special handling for all extensions that
+                       // read PHP LL files and pass arrays here directly.
+               $value = is_string($localLanguage[$this->lang][$index]) ? $localLanguage[$this->lang][$index] : $localLanguage[$this->lang][$index][0]['target'];
+               if ($value !== '') {
+                       $output = $this->hscAndCharConv($value, $hsc);
                } else {
-                       $output = $this->hscAndCharConv($localLanguage['default'][$index][0]['target'], $hsc);
+                       $output = $this->hscAndCharConv($value, $hsc);
                }
                return $output . $this->debugLL($index);
        }