[TASK] Update to phpunit 4.1
[Packages/TYPO3.CMS.git] / typo3 / sysext / extbase / Classes / Utility / LocalizationUtility.php
1 <?php
2 namespace TYPO3\CMS\Extbase\Utility;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 2010-2013 Extbase Team (http://forge.typo3.org/projects/typo3v4-mvc)
8 * Extbase is a backport of TYPO3 Flow. All credits go to the TYPO3 Flow team.
9 * All rights reserved
10 *
11 * This script is part of the TYPO3 project. The TYPO3 project is
12 * free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * The GNU General Public License can be found at
18 * http://www.gnu.org/copyleft/gpl.html.
19 * A copy is found in the text file GPL.txt and important notices to the license
20 * from the author is found in LICENSE.txt distributed with these scripts.
21 *
22 *
23 * This script is distributed in the hope that it will be useful,
24 * but WITHOUT ANY WARRANTY; without even the implied warranty of
25 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26 * GNU General Public License for more details.
27 *
28 * This copyright notice MUST APPEAR in all copies of the script!
29 ***************************************************************/
30 /**
31 * Localization helper which should be used to fetch localized labels.
32 *
33 * @api
34 */
35 class LocalizationUtility {
36
37 /**
38 * @var string
39 */
40 static protected $locallangPath = 'Resources/Private/Language/';
41
42 /**
43 * Local Language content
44 *
45 * @var array
46 */
47 static protected $LOCAL_LANG = array();
48
49 /**
50 * Contains those LL keys, which have been set to (empty) in TypoScript.
51 * This is necessary, as we cannot distinguish between a nonexisting
52 * translation and a label that has been cleared by TS.
53 * In both cases ['key'][0]['target'] is "".
54 *
55 * @var array
56 */
57 static protected $LOCAL_LANG_UNSET = array();
58
59 /**
60 * Local Language content charset for individual labels (overriding)
61 *
62 * @var array
63 */
64 static protected $LOCAL_LANG_charset = array();
65
66 /**
67 * Key of the language to use
68 *
69 * @var string
70 */
71 static protected $languageKey = 'default';
72
73 /**
74 * Pointer to alternative fall-back language to use
75 *
76 * @var array
77 */
78 static protected $alternativeLanguageKeys = array();
79
80 /**
81 * @var \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
82 */
83 static protected $configurationManager = NULL;
84
85 /**
86 * Returns the localized label of the LOCAL_LANG key, $key.
87 *
88 * @param string $key The key from the LOCAL_LANG array for which to return the value.
89 * @param string $extensionName The name of the extension
90 * @param array $arguments the arguments of the extension, being passed over to vsprintf
91 * @return string|NULL The value from LOCAL_LANG or NULL if no translation was found.
92 * @api
93 * @todo : If vsprintf gets a malformed string, it returns FALSE! Should we throw an exception there?
94 */
95 static public function translate($key, $extensionName, $arguments = NULL) {
96 $value = NULL;
97 if (\TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($key, 'LLL:')) {
98 $value = self::translateFileReference($key);
99 } else {
100 self::initializeLocalization($extensionName);
101 // The "from" charset of csConv() is only set for strings from TypoScript via _LOCAL_LANG
102 if (!empty(self::$LOCAL_LANG[$extensionName][self::$languageKey][$key][0]['target'])
103 || isset(self::$LOCAL_LANG_UNSET[$extensionName][self::$languageKey][$key])
104 ) {
105 // Local language translation for key exists
106 $value = self::$LOCAL_LANG[$extensionName][self::$languageKey][$key][0]['target'];
107 if (!empty(self::$LOCAL_LANG_charset[$extensionName][self::$languageKey][$key])) {
108 $value = self::convertCharset($value, self::$LOCAL_LANG_charset[$extensionName][self::$languageKey][$key]);
109 }
110 } elseif (count(self::$alternativeLanguageKeys)) {
111 $languages = array_reverse(self::$alternativeLanguageKeys);
112 foreach ($languages as $language) {
113 if (!empty(self::$LOCAL_LANG[$extensionName][$language][$key][0]['target'])
114 || isset(self::$LOCAL_LANG_UNSET[$extensionName][$language][$key])
115 ) {
116 // Alternative language translation for key exists
117 $value = self::$LOCAL_LANG[$extensionName][$language][$key][0]['target'];
118 if (!empty(self::$LOCAL_LANG_charset[$extensionName][$language][$key])) {
119 $value = self::convertCharset($value, self::$LOCAL_LANG_charset[$extensionName][$language][$key]);
120 }
121 break;
122 }
123 }
124 }
125 if ($value === NULL && (!empty(self::$LOCAL_LANG[$extensionName]['default'][$key][0]['target'])
126 || isset(self::$LOCAL_LANG_UNSET[$extensionName]['default'][$key]))
127 ) {
128 // Default language translation for key exists
129 // No charset conversion because default is English and thereby ASCII
130 $value = self::$LOCAL_LANG[$extensionName]['default'][$key][0]['target'];
131 }
132 }
133 if (is_array($arguments) && $value !== NULL) {
134 return vsprintf($value, $arguments);
135 } else {
136 return $value;
137 }
138 }
139
140 /**
141 * Returns the localized label of the LOCAL_LANG key, $key.
142 *
143 * @param string $key The language key including the path to a custom locallang file ("LLL:path:key").
144 * @return string The value from LOCAL_LANG or NULL if no translation was found.
145 * @see language::sL()
146 * @see \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::sL()
147 */
148 static protected function translateFileReference($key) {
149 if (TYPO3_MODE === 'FE') {
150 $value = $GLOBALS['TSFE']->sL($key);
151 return $value !== FALSE ? $value : NULL;
152 } elseif (is_object($GLOBALS['LANG'])) {
153 $value = $GLOBALS['LANG']->sL($key);
154 return $value !== '' ? $value : NULL;
155 } else {
156 return $key;
157 }
158 }
159
160 /**
161 * Loads local-language values by looking for a "locallang.php" (or "locallang.xml") file in the plugin resources directory and if found includes it.
162 * Also locallang values set in the TypoScript property "_LOCAL_LANG" are merged onto the values found in the "locallang.php" file.
163 *
164 * @param string $extensionName
165 * @return void
166 */
167 static protected function initializeLocalization($extensionName) {
168 if (isset(self::$LOCAL_LANG[$extensionName])) {
169 return;
170 }
171 $locallangPathAndFilename = 'EXT:' . \TYPO3\CMS\Core\Utility\GeneralUtility::camelCaseToLowerCaseUnderscored($extensionName) . '/' . self::$locallangPath . 'locallang.xml';
172 self::setLanguageKeys();
173 $renderCharset = TYPO3_MODE === 'FE' ? $GLOBALS['TSFE']->renderCharset : $GLOBALS['LANG']->charSet;
174 self::$LOCAL_LANG[$extensionName] = \TYPO3\CMS\Core\Utility\GeneralUtility::readLLfile($locallangPathAndFilename, self::$languageKey, $renderCharset);
175 foreach (self::$alternativeLanguageKeys as $language) {
176 $tempLL = \TYPO3\CMS\Core\Utility\GeneralUtility::readLLfile($locallangPathAndFilename, $language, $renderCharset);
177 if (self::$languageKey !== 'default' && isset($tempLL[$language])) {
178 self::$LOCAL_LANG[$extensionName][$language] = $tempLL[$language];
179 }
180 }
181 self::loadTypoScriptLabels($extensionName);
182 }
183
184 /**
185 * Sets the currently active language/language_alt keys.
186 * Default values are "default" for language key and "" for language_alt key.
187 *
188 * @return void
189 */
190 static protected function setLanguageKeys() {
191 self::$languageKey = 'default';
192 self::$alternativeLanguageKeys = array();
193 if (TYPO3_MODE === 'FE') {
194 if (isset($GLOBALS['TSFE']->config['config']['language'])) {
195 self::$languageKey = $GLOBALS['TSFE']->config['config']['language'];
196 if (isset($GLOBALS['TSFE']->config['config']['language_alt'])) {
197 self::$alternativeLanguageKeys[] = $GLOBALS['TSFE']->config['config']['language_alt'];
198 } else {
199 /** @var $locales \TYPO3\CMS\Core\Localization\Locales */
200 $locales = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Localization\\Locales');
201 if (in_array(self::$languageKey, $locales->getLocales())) {
202 foreach ($locales->getLocaleDependencies(self::$languageKey) as $language) {
203 self::$alternativeLanguageKeys[] = $language;
204 }
205 }
206 }
207 }
208 } elseif (strlen($GLOBALS['BE_USER']->uc['lang']) > 0) {
209 self::$languageKey = $GLOBALS['BE_USER']->uc['lang'];
210 }
211 }
212
213 /**
214 * Overwrites labels that are set via TypoScript.
215 * TS locallang labels have to be configured like:
216 * plugin.tx_myextension._LOCAL_LANG.languageKey.key = value
217 *
218 * @param string $extensionName
219 * @return void
220 */
221 static protected function loadTypoScriptLabels($extensionName) {
222 $configurationManager = static::getConfigurationManager();
223 $frameworkConfiguration = $configurationManager->getConfiguration(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK, $extensionName);
224 if (!is_array($frameworkConfiguration['_LOCAL_LANG'])) {
225 return;
226 }
227 self::$LOCAL_LANG_UNSET[$extensionName] = array();
228 foreach ($frameworkConfiguration['_LOCAL_LANG'] as $languageKey => $labels) {
229 if (!(is_array($labels) && isset(self::$LOCAL_LANG[$extensionName][$languageKey]))) {
230 continue;
231 }
232 foreach ($labels as $labelKey => $labelValue) {
233 if (is_string($labelValue)) {
234 self::$LOCAL_LANG[$extensionName][$languageKey][$labelKey][0]['target'] = $labelValue;
235 if ($labelValue === '') {
236 self::$LOCAL_LANG_UNSET[$extensionName][$languageKey][$labelKey] = '';
237 }
238 if (is_object($GLOBALS['LANG'])) {
239 self::$LOCAL_LANG_charset[$extensionName][$languageKey][$labelKey] = $GLOBALS['LANG']->csConvObj->charSetArray[$languageKey];
240 } else {
241 self::$LOCAL_LANG_charset[$extensionName][$languageKey][$labelKey] = $GLOBALS['TSFE']->csConvObj->charSetArray[$languageKey];
242 }
243 } elseif (is_array($labelValue)) {
244 $labelValue = self::flattenTypoScriptLabelArray($labelValue, $labelKey);
245 foreach ($labelValue as $key => $value) {
246 self::$LOCAL_LANG[$extensionName][$languageKey][$key][0]['target'] = $value;
247 if ($value === '') {
248 self::$LOCAL_LANG_UNSET[$extensionName][$languageKey][$key] = '';
249 }
250 }
251 }
252 }
253 }
254 }
255
256 /**
257 * Flatten TypoScript label array; converting a hierarchical array into a flat
258 * array with the keys separated by dots.
259 *
260 * Example Input: array('k1' => array('subkey1' => 'val1'))
261 * Example Output: array('k1.subkey1' => 'val1')
262 *
263 * @param array $labelValues Hierarchical array of labels
264 * @param string $parentKey the name of the parent key in the recursion; is only needed for recursion.
265 * @return array flattened array of labels.
266 */
267 static protected function flattenTypoScriptLabelArray(array $labelValues, $parentKey = '') {
268 $result = array();
269 foreach ($labelValues as $key => $labelValue) {
270 if (!empty($parentKey)) {
271 $key = $parentKey . '.' . $key;
272 }
273 if (is_array($labelValue)) {
274 $labelValue = self::flattenTypoScriptLabelArray($labelValue, $key);
275 $result = array_merge($result, $labelValue);
276 } else {
277 $result[$key] = $labelValue;
278 }
279 }
280 return $result;
281 }
282
283 /**
284 * Converts a string from the specified character set to the current.
285 * The current charset is defined by the TYPO3 mode.
286 *
287 * @param string $value string to be converted
288 * @param string $charset The source charset
289 * @return string converted string
290 */
291 static protected function convertCharset($value, $charset) {
292 if (TYPO3_MODE === 'FE') {
293 return $GLOBALS['TSFE']->csConv($value, $charset);
294 } else {
295 $convertedValue = $GLOBALS['LANG']->csConvObj->conv($value, $GLOBALS['LANG']->csConvObj->parse_charset($charset), $GLOBALS['LANG']->charSet, 1);
296 return $convertedValue !== NULL ? $convertedValue : $value;
297 }
298 }
299
300 /**
301 * Returns instance of the configuration manager
302 *
303 * @return \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
304 */
305 static protected function getConfigurationManager() {
306 if (!is_null(static::$configurationManager)) {
307 return static::$configurationManager;
308 }
309 $objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Object\\ObjectManager');
310 $configurationManager = $objectManager->get('TYPO3\\CMS\\Extbase\\Configuration\\ConfigurationManagerInterface');
311 static::$configurationManager = $configurationManager;
312 return $configurationManager;
313 }
314 }