Permalink
Find file
Fetching contributors…
Cannot retrieve contributors at this time
288 lines (270 sloc) 10.5 KB
<?php
namespace Derhansen\Standaloneview\Service;
/*
* This file is part of the TYPO3 CMS project.
*
* It is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License, either version 2
* of the License, or any later version.
*
* For the full copyright and license information, please read the
* LICENSE.txt file that was distributed with this source code.
*
* The TYPO3 project - inspiring people to share!
*/
/**
* Localization Service which should be used to fetch localized labels.
*/
class LocalizationService {
/**
* @var string
*/
protected $locallangPath = 'Resources/Private/Language/';
/**
* Local Language content
*
* @var array
*/
protected $LOCAL_LANG = array();
/**
* Contains those LL keys, which have been set to (empty) in TypoScript.
* This is necessary, as we cannot distinguish between a nonexisting
* translation and a label that has been cleared by TS.
* In both cases ['key'][0]['target'] is "".
*
* @var array
*/
protected $LOCAL_LANG_UNSET = array();
/**
* Local Language content charset for individual labels (overriding)
*
* @var array
*/
protected $LOCAL_LANG_charset = array();
/**
* Key of the language to use
*
* @var string
*/
protected $languageKey = 'default';
/**
* Pointer to alternative fall-back language to use
*
* @var array
*/
protected $alternativeLanguageKeys = array();
/**
* The configuration manager
*
* @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManager
* @inject
*/
protected $configurationManager;
/**
* Returns the localized label of the LOCAL_LANG key, $key.
*
* @param string $key The key from the LOCAL_LANG array for which to return the value.
* @param string $extensionName The name of the extension
* @param array $arguments the arguments of the extension, being passed over to vsprintf
* @return string|NULL The value from LOCAL_LANG or NULL if no translation was found.
* @api
* @todo : If vsprintf gets a malformed string, it returns FALSE! Should we throw an exception there?
*/
public function translate($key, $extensionName, $arguments = NULL) {
$value = NULL;
if (\TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($key, 'LLL:')) {
$value = $this->translateFileReference($key);
} else {
$this->initializeLocalization($extensionName);
// The "from" charset of csConv() is only set for strings from TypoScript via _LOCAL_LANG
if (!empty($this->LOCAL_LANG[$extensionName][$this->languageKey][$key][0]['target'])
|| isset($this->LOCAL_LANG_UNSET[$extensionName][$this->languageKey][$key])
) {
// Local language translation for key exists
$value = $this->LOCAL_LANG[$extensionName][$this->languageKey][$key][0]['target'];
if (!empty($this->LOCAL_LANG_charset[$extensionName][$this->languageKey][$key])) {
$value = $this->convertCharset($value, $this->LOCAL_LANG_charset[$extensionName][$this->languageKey][$key]);
}
} elseif (count($this->alternativeLanguageKeys)) {
$languages = array_reverse($this->alternativeLanguageKeys);
foreach ($languages as $language) {
if (!empty($this->LOCAL_LANG[$extensionName][$language][$key][0]['target'])
|| isset($this->LOCAL_LANG_UNSET[$extensionName][$language][$key])
) {
// Alternative language translation for key exists
$value = $this->LOCAL_LANG[$extensionName][$language][$key][0]['target'];
if (!empty($this->LOCAL_LANG_charset[$extensionName][$language][$key])) {
$value = $this->convertCharset($value, $this->LOCAL_LANG_charset[$extensionName][$language][$key]);
}
break;
}
}
}
if ($value === NULL && (!empty($this->LOCAL_LANG[$extensionName]['default'][$key][0]['target'])
|| isset($this->LOCAL_LANG_UNSET[$extensionName]['default'][$key]))
) {
// Default language translation for key exists
// No charset conversion because default is English and thereby ASCII
$value = $this->LOCAL_LANG[$extensionName]['default'][$key][0]['target'];
}
}
if (is_array($arguments) && $value !== NULL) {
return vsprintf($value, $arguments);
} else {
return $value;
}
}
/**
* Returns the localized label of the LOCAL_LANG key, $key.
*
* @param string $key The language key including the path to a custom locallang file ("LLL:path:key").
* @return string The value from LOCAL_LANG or NULL if no translation was found.
* @see language::sL()
* @see \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::sL()
*/
protected function translateFileReference($key) {
if (TYPO3_MODE === 'FE') {
$value = $GLOBALS['TSFE']->sL($key);
return $value !== FALSE ? $value : NULL;
} elseif (is_object($GLOBALS['LANG'])) {
$value = $GLOBALS['LANG']->sL($key);
return $value !== '' ? $value : NULL;
} else {
return $key;
}
}
/**
* Loads local-language values by looking for a "locallang.php" (or "locallang.xml") file in the plugin resources directory and if found includes it.
* Also locallang values set in the TypoScript property "_LOCAL_LANG" are merged onto the values found in the "locallang.php" file.
*
* @param string $extensionName
* @return void
*/
protected function initializeLocalization($extensionName) {
if (isset($this->LOCAL_LANG[$extensionName])) {
return;
}
$locallangPathAndFilename = 'EXT:' . \TYPO3\CMS\Core\Utility\GeneralUtility::camelCaseToLowerCaseUnderscored($extensionName) . '/' . $this->locallangPath . 'locallang.xml';
$this->setLanguageKeys();
$renderCharset = TYPO3_MODE === 'FE' ? $GLOBALS['TSFE']->renderCharset : $GLOBALS['LANG']->charSet;
$this->LOCAL_LANG[$extensionName] = \TYPO3\CMS\Core\Utility\GeneralUtility::readLLfile($locallangPathAndFilename, $this->languageKey, $renderCharset);
foreach ($this->alternativeLanguageKeys as $language) {
$tempLL = \TYPO3\CMS\Core\Utility\GeneralUtility::readLLfile($locallangPathAndFilename, $language, $renderCharset);
if ($this->languageKey !== 'default' && isset($tempLL[$language])) {
$this->LOCAL_LANG[$extensionName][$language] = $tempLL[$language];
}
}
$this->loadTypoScriptLabels($extensionName);
}
/**
* Sets the currently active language/language_alt keys.
* Default values are "default" for language key and "" for language_alt key.
*
* @return void
*/
protected function setLanguageKeys() {
$this->languageKey = 'default';
$this->alternativeLanguageKeys = array();
if (TYPO3_MODE === 'FE') {
if (isset($GLOBALS['TSFE']->config['config']['language'])) {
$this->languageKey = $GLOBALS['TSFE']->config['config']['language'];
if (isset($GLOBALS['TSFE']->config['config']['language_alt'])) {
$this->alternativeLanguageKeys[] = $GLOBALS['TSFE']->config['config']['language_alt'];
} else {
/** @var $locales \TYPO3\CMS\Core\Localization\Locales */
$locales = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Localization\\Locales');
if (in_array($this->languageKey, $locales->getLocales())) {
foreach ($locales->getLocaleDependencies($this->languageKey) as $language) {
$this->alternativeLanguageKeys[] = $language;
}
}
}
}
} elseif (strlen($GLOBALS['BE_USER']->uc['lang']) > 0) {
$this->languageKey = $GLOBALS['BE_USER']->uc['lang'];
}
}
/**
* Overwrites labels that are set via TypoScript.
* TS locallang labels have to be configured like:
* plugin.tx_myextension._LOCAL_LANG.languageKey.key = value
*
* @param string $extensionName
* @return void
*/
protected function loadTypoScriptLabels($extensionName) {
$frameworkConfiguration = $this->configurationManager->getConfiguration(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK, $extensionName);
if (!is_array($frameworkConfiguration['_LOCAL_LANG'])) {
return;
}
$this->LOCAL_LANG_UNSET[$extensionName] = array();
foreach ($frameworkConfiguration['_LOCAL_LANG'] as $languageKey => $labels) {
if (!(is_array($labels) && isset($this->LOCAL_LANG[$extensionName][$languageKey]))) {
continue;
}
foreach ($labels as $labelKey => $labelValue) {
if (is_string($labelValue)) {
$this->LOCAL_LANG[$extensionName][$languageKey][$labelKey][0]['target'] = $labelValue;
if ($labelValue === '') {
$this->LOCAL_LANG_UNSET[$extensionName][$languageKey][$labelKey] = '';
}
if (is_object($GLOBALS['LANG'])) {
$this->LOCAL_LANG_charset[$extensionName][$languageKey][$labelKey] = $GLOBALS['LANG']->csConvObj->charSetArray[$languageKey];
} else {
$this->LOCAL_LANG_charset[$extensionName][$languageKey][$labelKey] = $GLOBALS['TSFE']->csConvObj->charSetArray[$languageKey];
}
} elseif (is_array($labelValue)) {
$labelValue = $this->flattenTypoScriptLabelArray($labelValue, $labelKey);
foreach ($labelValue as $key => $value) {
$this->LOCAL_LANG[$extensionName][$languageKey][$key][0]['target'] = $value;
if ($value === '') {
$this->LOCAL_LANG_UNSET[$extensionName][$languageKey][$key] = '';
}
}
}
}
}
}
/**
* Flatten TypoScript label array; converting a hierarchical array into a flat
* array with the keys separated by dots.
*
* Example Input: array('k1' => array('subkey1' => 'val1'))
* Example Output: array('k1.subkey1' => 'val1')
*
* @param array $labelValues Hierarchical array of labels
* @param string $parentKey the name of the parent key in the recursion; is only needed for recursion.
* @return array flattened array of labels.
*/
protected function flattenTypoScriptLabelArray(array $labelValues, $parentKey = '') {
$result = array();
foreach ($labelValues as $key => $labelValue) {
if (!empty($parentKey)) {
$key = $parentKey . '.' . $key;
}
if (is_array($labelValue)) {
$labelValue = $this->flattenTypoScriptLabelArray($labelValue, $key);
$result = array_merge($result, $labelValue);
} else {
$result[$key] = $labelValue;
}
}
return $result;
}
/**
* Converts a string from the specified character set to the current.
* The current charset is defined by the TYPO3 mode.
*
* @param string $value string to be converted
* @param string $charset The source charset
* @return string converted string
*/
protected function convertCharset($value, $charset) {
if (TYPO3_MODE === 'FE') {
return $GLOBALS['TSFE']->csConv($value, $charset);
} else {
$convertedValue = $GLOBALS['LANG']->csConvObj->conv($value, $GLOBALS['LANG']->csConvObj->parse_charset($charset), $GLOBALS['LANG']->charSet, 1);
return $convertedValue !== NULL ? $convertedValue : $value;
}
}
}