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