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