[BUGFIX] Properly handle translation file detection 85/34285/7
authorMathias Schreiber <mathias.schreiber@wmdb.de>
Thu, 18 Dec 2014 10:24:21 +0000 (11:24 +0100)
committerMarkus Klein <klein.t3@reelworx.at>
Tue, 24 Feb 2015 14:08:11 +0000 (15:08 +0100)
The GeneralUtility::llXmlAutoFileName() method will now also correctly
handle paths to files that are not placed within a known directory (ext,
sysext, test etc.) if the call is made with $sameFile = TRUE.

This allows placing language files in storages like fileadmin.

Resolves: #35093
Resolves: #34728
Releases: master, 6.2
Change-Id: Ic5901c3fa98233978abf26db377666dade16f8e6
Reviewed-on: http://review.typo3.org/34285
Reviewed-by: Gernot Ploiner <gp@webprofil.at>
Tested-by: Gernot Ploiner <gp@webprofil.at>
Reviewed-by: Markus Klein <klein.t3@reelworx.at>
Tested-by: Markus Klein <klein.t3@reelworx.at>
typo3/sysext/core/Classes/Localization/Parser/LocallangXmlParser.php
typo3/sysext/core/Classes/Utility/GeneralUtility.php

index 2d5cff5..c1f3edb 100644 (file)
@@ -14,6 +14,9 @@ namespace TYPO3\CMS\Core\Localization\Parser;
  * The TYPO3 project - inspiring people to share!
  */
 
+use TYPO3\CMS\Core\Localization\Exception\InvalidXmlFileException;
+use TYPO3\CMS\Core\Utility\GeneralUtility;
+
 /**
  * Parser for XML locallang file.
  *
@@ -43,11 +46,21 @@ class LocallangXmlParser extends AbstractXmlParser {
                // Parse source
                $parsedSource = $this->parseXmlFile();
                // Parse target
-               $localizedTargetPath = \TYPO3\CMS\Core\Utility\GeneralUtility::getFileAbsFileName(\TYPO3\CMS\Core\Utility\GeneralUtility::llXmlAutoFileName($this->sourcePath, $this->languageKey));
-               $targetPath = $this->languageKey !== 'default' && @is_file($localizedTargetPath) ? $localizedTargetPath : $this->sourcePath;
+               $targetPath = $this->sourcePath;
+               if ($this->languageKey !== 'default') {
+                       $localizedTargetPath = GeneralUtility::getFileAbsFileName(GeneralUtility::llXmlAutoFileName($this->sourcePath, $this->languageKey));
+                       if (!@is_file($localizedTargetPath)) {
+                               // Global localization is not available, try split localization file
+                               $localizedTargetPath = GeneralUtility::getFileAbsFileName(GeneralUtility::llXmlAutoFileName($this->sourcePath, $this->languageKey, TRUE));
+                       }
+                       if (!@is_file($localizedTargetPath)) {
+                               $localizedTargetPath = $this->sourcePath;
+                       }
+                       $targetPath = $localizedTargetPath;
+               }
                try {
                        $parsedTarget = $this->getParsedTargetData($targetPath);
-               } catch (\TYPO3\CMS\Core\Localization\Exception\InvalidXmlFileException $e) {
+               } catch (InvalidXmlFileException $e) {
                        $parsedTarget = $this->getParsedTargetData($this->sourcePath);
                }
                $LOCAL_LANG = array();
@@ -59,7 +72,7 @@ class LocallangXmlParser extends AbstractXmlParser {
        /**
         * Returns array representation of XLIFF data, starting from a root node.
         *
-        * @param SimpleXMLElement $root XML root element
+        * @param \SimpleXMLElement $root XML root element
         * @param string $element Target or Source
         * @return array
         */
@@ -99,7 +112,7 @@ class LocallangXmlParser extends AbstractXmlParser {
                        // <languageKey index="fr">EXT:yourext/path/to/localized/locallang.xml</languageKey>
                        $reference = sprintf('%s', $bodyOfFileTag);
                        if (substr($reference, -4) === '.xml') {
-                               return $this->getParsedTargetData(\TYPO3\CMS\Core\Utility\GeneralUtility::getFileAbsFileName($reference));
+                               return $this->getParsedTargetData(GeneralUtility::getFileAbsFileName($reference));
                        }
                }
                /** @var \SimpleXMLElement $translationElement */
@@ -154,7 +167,7 @@ class LocallangXmlParser extends AbstractXmlParser {
         *
         * @param string $targetPath Path of the target file
         * @return array
-        * @throws \TYPO3\CMS\Core\Localization\Exception\InvalidXmlFileException
+        * @throws InvalidXmlFileException
         */
        protected function parseXmlTargetFile($targetPath) {
                $rootXmlNode = FALSE;
@@ -162,7 +175,7 @@ class LocallangXmlParser extends AbstractXmlParser {
                        $rootXmlNode = simplexml_load_file($targetPath, 'SimpleXmlElement', \LIBXML_NOWARNING);
                }
                if (!isset($rootXmlNode) || $rootXmlNode === FALSE) {
-                       throw new \TYPO3\CMS\Core\Localization\Exception\InvalidXmlFileException('The path provided does not point to existing and accessible well-formed XML file (' . $targetPath . ').', 1278155987);
+                       throw new InvalidXmlFileException('The path provided does not point to existing and accessible well-formed XML file (' . $targetPath . ').', 1278155987);
                }
                return $this->doParsingTargetFromRoot($rootXmlNode);
        }
index 43e3069..f662a8a 100755 (executable)
@@ -3979,18 +3979,24 @@ Connection: close
        /**
         * Returns auto-filename for locallang-XML localizations.
         *
-        * @param string $fileRef Absolute file reference to locallang-XML file. Must be inside system/global/local extension
+        * @param string $fileRef Absolute file reference to locallang-XML file.
         * @param string $language Language key
         * @param bool $sameLocation if TRUE, then locallang-XML localization file name will be returned with same directory as $fileRef
-        * @return string Returns the filename reference for the language unless error occurred (or local mode is used) in which case it will be NULL
+        * @return string Returns the filename reference for the language unless error occurred in which case it will be NULL
         */
        static public function llXmlAutoFileName($fileRef, $language, $sameLocation = FALSE) {
+               // If $fileRef is already prefixed with "[language key]" then we should return it as this
+               $fileName = basename($fileRef);
+               if (self::isFirstPartOfStr($fileName, $language . '.')) {
+                       return $fileRef;
+               }
+
                if ($sameLocation) {
-                       $location = 'EXT:';
-               } else {
-                       // Default location of translations
-                       $location = 'typo3conf/l10n/' . $language . '/';
+                       return str_replace($fileName, $language . '.' . $fileName, $fileRef);
                }
+
+               // Default location of translations
+               $location = 'typo3conf/l10n/' . $language . '/';
                // Analyse file reference:
                // Is system:
                if (self::isFirstPartOfStr($fileRef, PATH_typo3 . 'sysext/')) {
@@ -4017,10 +4023,6 @@ Connection: close
                        }
                        // Add empty first-entry if not there.
                        list($file_extPath, $file_fileName) = $temp;
-                       // If $fileRef is already prefix with "[language key]" then we should return it as this
-                       if (substr($file_fileName, 0, strlen($language) + 1) === $language . '.') {
-                               return $fileRef;
-                       }
                        // The filename is prefixed with "[language key]." because it prevents the llxmltranslate tool from detecting it.
                        return $location . $file_extKey . '/' . ($file_extPath ? $file_extPath . '/' : '') . $language . '.' . $file_fileName;
                } else {