[BUGFIX] Strict Standards - setLanguageKeys must be static
[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 * Returns the localized label of the LOCAL_LANG key, $key.
82 *
83 * @param string $key The key from the LOCAL_LANG array for which to return the value.
84 * @param string $extensionName The name of the extension
85 * @param array $arguments the arguments of the extension, being passed over to vsprintf
86 * @return string|NULL The value from LOCAL_LANG or NULL if no translation was found.
87 * @api
88 * @todo : If vsprintf gets a malformed string, it returns FALSE! Should we throw an exception there?
89 */
90 static public function translate($key, $extensionName, $arguments = NULL) {
91 $value = NULL;
92 if (\TYPO3\CMS\Core\Utility\GeneralUtility::isFirstPartOfStr($key, 'LLL:')) {
93 $value = self::translateFileReference($key);
94 } else {
95 self::initializeLocalization($extensionName);
96 // The "from" charset of csConv() is only set for strings from TypoScript via _LOCAL_LANG
97 if (!empty(self::$LOCAL_LANG[$extensionName][self::$languageKey][$key][0]['target'])
98 || isset(self::$LOCAL_LANG_UNSET[$extensionName][self::$languageKey][$key])
99 ) {
100 // Local language translation for key exists
101 $value = self::$LOCAL_LANG[$extensionName][self::$languageKey][$key][0]['target'];
102 if (!empty(self::$LOCAL_LANG_charset[$extensionName][self::$languageKey][$key])) {
103 $value = self::convertCharset($value, self::$LOCAL_LANG_charset[$extensionName][self::$languageKey][$key]);
104 }
105 } elseif (count(self::$alternativeLanguageKeys)) {
106 $languages = array_reverse(self::$alternativeLanguageKeys);
107 foreach ($languages as $language) {
108 if (!empty(self::$LOCAL_LANG[$extensionName][$language][$key][0]['target'])
109 || isset(self::$LOCAL_LANG_UNSET[$extensionName][$language][$key])
110 ) {
111 // Alternative language translation for key exists
112 $value = self::$LOCAL_LANG[$extensionName][$language][$key][0]['target'];
113 if (!empty(self::$LOCAL_LANG_charset[$extensionName][$language][$key])) {
114 $value = self::convertCharset($value, self::$LOCAL_LANG_charset[$extensionName][$language][$key]);
115 }
116 break;
117 }
118 }
119 }
120 if ($value === NULL && (!empty(self::$LOCAL_LANG[$extensionName]['default'][$key][0]['target'])
121 || isset(self::$LOCAL_LANG_UNSET[$extensionName]['default'][$key]))
122 ) {
123 // Default language translation for key exists
124 // No charset conversion because default is English and thereby ASCII
125 $value = self::$LOCAL_LANG[$extensionName]['default'][$key][0]['target'];
126 }
127 }
128 if (is_array($arguments) && $value !== NULL) {
129 return vsprintf($value, $arguments);
130 } else {
131 return $value;
132 }
133 }
134
135 /**
136 * Returns the localized label of the LOCAL_LANG key, $key.
137 *
138 * @param string $key The language key including the path to a custom locallang file ("LLL:path:key").
139 * @return string The value from LOCAL_LANG or NULL if no translation was found.
140 * @see language::sL()
141 * @see \TYPO3\CMS\Frontend\Controller\TypoScriptFrontendController::sL()
142 */
143 static protected function translateFileReference($key) {
144 if (TYPO3_MODE === 'FE') {
145 $value = $GLOBALS['TSFE']->sL($key);
146 return $value !== FALSE ? $value : NULL;
147 } elseif (is_object($GLOBALS['LANG'])) {
148 $value = $GLOBALS['LANG']->sL($key);
149 return $value !== '' ? $value : NULL;
150 } else {
151 return $key;
152 }
153 }
154
155 /**
156 * Loads local-language values by looking for a "locallang.php" (or "locallang.xml") file in the plugin resources directory and if found includes it.
157 * Also locallang values set in the TypoScript property "_LOCAL_LANG" are merged onto the values found in the "locallang.php" file.
158 *
159 * @param string $extensionName
160 * @return void
161 */
162 static protected function initializeLocalization($extensionName) {
163 if (isset(self::$LOCAL_LANG[$extensionName])) {
164 return;
165 }
166 $locallangPathAndFilename = 'EXT:' . \TYPO3\CMS\Core\Utility\GeneralUtility::camelCaseToLowerCaseUnderscored($extensionName) . '/' . self::$locallangPath . 'locallang.xml';
167 self::setLanguageKeys();
168 $renderCharset = TYPO3_MODE === 'FE' ? $GLOBALS['TSFE']->renderCharset : $GLOBALS['LANG']->charSet;
169 self::$LOCAL_LANG[$extensionName] = \TYPO3\CMS\Core\Utility\GeneralUtility::readLLfile($locallangPathAndFilename, self::$languageKey, $renderCharset);
170 foreach (self::$alternativeLanguageKeys as $language) {
171 $tempLL = \TYPO3\CMS\Core\Utility\GeneralUtility::readLLfile($locallangPathAndFilename, $language, $renderCharset);
172 if (self::$languageKey !== 'default' && isset($tempLL[$language])) {
173 self::$LOCAL_LANG[$extensionName][$language] = $tempLL[$language];
174 }
175 }
176 self::loadTypoScriptLabels($extensionName);
177 }
178
179 /**
180 * Sets the currently active language/language_alt keys.
181 * Default values are "default" for language key and "" for language_alt key.
182 *
183 * @return void
184 */
185 static protected function setLanguageKeys() {
186 self::$languageKey = 'default';
187 self::$alternativeLanguageKeys = array();
188 if (TYPO3_MODE === 'FE') {
189 if (isset($GLOBALS['TSFE']->config['config']['language'])) {
190 self::$languageKey = $GLOBALS['TSFE']->config['config']['language'];
191 if (isset($GLOBALS['TSFE']->config['config']['language_alt'])) {
192 self::$alternativeLanguageKeys[] = $GLOBALS['TSFE']->config['config']['language_alt'];
193 } else {
194 /** @var $locales \TYPO3\CMS\Core\Localization\Locales */
195 $locales = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Localization\\Locales');
196 if (in_array(self::$languageKey, $locales->getLocales())) {
197 foreach ($locales->getLocaleDependencies(self::$languageKey) as $language) {
198 self::$alternativeLanguageKeys[] = $language;
199 }
200 }
201 }
202 }
203 } elseif (strlen($GLOBALS['BE_USER']->uc['lang']) > 0) {
204 self::$languageKey = $GLOBALS['BE_USER']->uc['lang'];
205 }
206 }
207
208 /**
209 * Overwrites labels that are set via TypoScript.
210 * TS locallang labels have to be configured like:
211 * plugin.tx_myextension._LOCAL_LANG.languageKey.key = value
212 *
213 * @param string $extensionName
214 * @return void
215 */
216 static protected function loadTypoScriptLabels($extensionName) {
217 $configurationManager = static::getConfigurationManager();
218 $frameworkConfiguration = $configurationManager->getConfiguration(\TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface::CONFIGURATION_TYPE_FRAMEWORK, $extensionName);
219 if (!is_array($frameworkConfiguration['_LOCAL_LANG'])) {
220 return;
221 }
222 self::$LOCAL_LANG_UNSET[$extensionName] = array();
223 foreach ($frameworkConfiguration['_LOCAL_LANG'] as $languageKey => $labels) {
224 if (!(is_array($labels) && isset(self::$LOCAL_LANG[$extensionName][$languageKey]))) {
225 continue;
226 }
227 foreach ($labels as $labelKey => $labelValue) {
228 if (is_string($labelValue)) {
229 self::$LOCAL_LANG[$extensionName][$languageKey][$labelKey][0]['target'] = $labelValue;
230 if ($labelValue === '') {
231 self::$LOCAL_LANG_UNSET[$extensionName][$languageKey][$labelKey] = '';
232 }
233 if (is_object($GLOBALS['LANG'])) {
234 self::$LOCAL_LANG_charset[$extensionName][$languageKey][$labelKey] = $GLOBALS['LANG']->csConvObj->charSetArray[$languageKey];
235 } else {
236 self::$LOCAL_LANG_charset[$extensionName][$languageKey][$labelKey] = $GLOBALS['TSFE']->csConvObj->charSetArray[$languageKey];
237 }
238 } elseif (is_array($labelValue)) {
239 $labelValue = self::flattenTypoScriptLabelArray($labelValue, $labelKey);
240 foreach ($labelValue as $key => $value) {
241 self::$LOCAL_LANG[$extensionName][$languageKey][$key][0]['target'] = $value;
242 if ($value === '') {
243 self::$LOCAL_LANG_UNSET[$extensionName][$languageKey][$key] = '';
244 }
245 }
246 }
247 }
248 }
249 }
250
251 /**
252 * Flatten TypoScript label array; converting a hierarchical array into a flat
253 * array with the keys separated by dots.
254 *
255 * Example Input: array('k1' => array('subkey1' => 'val1'))
256 * Example Output: array('k1.subkey1' => 'val1')
257 *
258 * @param array $labelValues Hierarchical array of labels
259 * @param string $parentKey the name of the parent key in the recursion; is only needed for recursion.
260 * @return array flattened array of labels.
261 */
262 protected function flattenTypoScriptLabelArray(array $labelValues, $parentKey = '') {
263 $result = array();
264 foreach ($labelValues as $key => $labelValue) {
265 if (!empty($parentKey)) {
266 $key = $parentKey . '.' . $key;
267 }
268 if (is_array($labelValue)) {
269 $labelValue = self::flattenTypoScriptLabelArray($labelValue, $key);
270 $result = array_merge($result, $labelValue);
271 } else {
272 $result[$key] = $labelValue;
273 }
274 }
275 return $result;
276 }
277
278 /**
279 * Converts a string from the specified character set to the current.
280 * The current charset is defined by the TYPO3 mode.
281 *
282 * @param string $value string to be converted
283 * @param string $charset The source charset
284 * @return string converted string
285 */
286 protected function convertCharset($value, $charset) {
287 if (TYPO3_MODE === 'FE') {
288 return $GLOBALS['TSFE']->csConv($value, $charset);
289 } else {
290 $convertedValue = $GLOBALS['LANG']->csConvObj->conv($value, $GLOBALS['LANG']->csConvObj->parse_charset($charset), $GLOBALS['LANG']->charSet, 1);
291 return $convertedValue !== NULL ? $convertedValue : $value;
292 }
293 }
294
295 /**
296 * Returns instance of the configuration manager
297 *
298 * @return \TYPO3\CMS\Extbase\Configuration\ConfigurationManagerInterface
299 */
300 static protected function getConfigurationManager() {
301 $objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Object\\ObjectManager');
302 $configurationManager = $objectManager->get('TYPO3\\CMS\\Extbase\\Configuration\\ConfigurationManagerInterface');
303 return $configurationManager;
304 }
305 }