3 namespace wcf\data\language
;
5 use wcf\data\DatabaseObject
;
6 use wcf\data\devtools\missing\language\item\DevtoolsMissingLanguageItemAction
;
7 use wcf\system\language\LanguageFactory
;
9 use wcf\util\StringUtil
;
12 * Represents a language.
14 * @author Alexander Ebert
15 * @copyright 2001-2019 WoltLab GmbH
16 * @license GNU Lesser General Public License <http://opensource.org/licenses/lgpl-license.php>
17 * @package WoltLabSuite\Core\Data\Language
19 * @property-read int $languageID unique id of the language
20 * @property-read string $languageCode code of the language according to ISO 639-1
21 * @property-read string $languageName name of the language within the language itself
22 * @property-read string $countryCode code of the country using the language according to ISO 3166-1, used to determine the language's country flag
23 * @property-read int $isDefault is `1` if the language is the default language, otherwise `0`
24 * @property-read int $hasContent is `1` if the language can be selected when creating language-specific content, otherwise `0`
25 * @property-read int $isDisabled is `1` if the language is disabled and thus not selectable, otherwise `0`
27 class Language
extends DatabaseObject
30 * list of language items
33 protected $items = [];
36 * list of dynamic language items
39 protected $dynamicItems = [];
42 * instance of LanguageEditor
48 * id of the active package
51 public $packageID = PACKAGE_ID
;
54 * contains categories currently being loaded as array keys
57 protected $categoriesBeingLoaded = [];
60 * Returns the name of this language.
64 public function __toString()
66 return $this->languageName
;
70 * Returns the fixed language code of this language.
74 public function getFixedLanguageCode()
76 return LanguageFactory
::fixLanguageCode($this->languageCode
);
80 * Returns the page direction of this language.
84 public function getPageDirection()
86 return $this->get('wcf.global.pageDirection');
90 * Returns a single language variable.
93 * @param bool $optional
96 public function get($item, $optional = false)
99 \
defined('ENABLE_DEBUG_MODE')
101 && \
defined('ENABLE_DEVELOPER_TOOLS')
102 && ENABLE_DEVELOPER_TOOLS
103 && \
is_array($optional)
106 throw new \
InvalidArgumentException("The second parameter of Language::get() does not support non-empty arrays. Did you mean to use Language::getDynamicVariable()?");
109 if (!isset($this->items
[$item])) {
110 // load category file
111 $explodedItem = \
explode('.', $item);
112 if (\
count($explodedItem) < 3) {
116 // attempt to load the most specific category
117 $this->loadCategory($explodedItem[0] . '.' . $explodedItem[1] . '.' . $explodedItem[2]);
118 if (!isset($this->items
[$item])) {
119 $this->loadCategory($explodedItem[0] . '.' . $explodedItem[1]);
123 // return language variable
124 if (isset($this->items
[$item])) {
125 return $this->items
[$item];
128 // do not output value if there was no match and the item looks like a valid language item
129 if ($optional && \
preg_match('~^([a-zA-Z0-9-_]+\.)+[a-zA-Z0-9-_]+$~', $item)) {
134 \
defined('ENABLE_DEVELOPER_TOOLS')
135 && ENABLE_DEVELOPER_TOOLS
136 && \
defined('LOG_MISSING_LANGUAGE_ITEMS')
137 && LOG_MISSING_LANGUAGE_ITEMS
138 && \
preg_match('~^([a-zA-Z0-9-_]+\.)+[a-zA-Z0-9-_]+$~', $item)
140 (new DevtoolsMissingLanguageItemAction([], 'logLanguageItem', [
142 'languageItem' => $item,
143 ]))->executeAction();
146 // return plain input
151 * Executes template scripting in a language variable.
153 * @param string $item
154 * @param array $variables
155 * @param bool $optional
156 * @return string result
158 public function getDynamicVariable($item, array $variables = [], $optional = false)
160 $staticItem = $this->get($item, $optional);
165 if (isset($this->dynamicItems
[$item])) {
166 // assign active language
167 $variables['__language'] = $this;
169 return WCF
::getTPL()->fetchString($this->dynamicItems
[$item], $variables);
173 \
defined('ENABLE_DEVELOPER_TOOLS')
174 && ENABLE_DEVELOPER_TOOLS
175 && \
defined('LOG_MISSING_LANGUAGE_ITEMS')
176 && LOG_MISSING_LANGUAGE_ITEMS
177 && $staticItem === $item
178 && \
preg_match('~^([a-zA-Z0-9-_]+\.)+[a-zA-Z0-9-_]+$~', $item)
180 (new DevtoolsMissingLanguageItemAction([], 'logLanguageItem', [
182 'languageItem' => $item,
183 ]))->executeAction();
190 * Shortcut method to reduce the code repetition in the compiled template code.
192 * @param string $item
193 * @param mixed[] $tagStackData
197 public function tplGet($item, array &$tagStackData)
199 $optional = !empty($tagStackData['__optional']);
201 if (!empty($tagStackData['__literal'])) {
202 $value = $this->get($item, $optional);
204 $value = $this->getDynamicVariable($item, $tagStackData, $optional);
207 if (!empty($tagStackData['__encode'])) {
208 return StringUtil
::encodeHTML($value);
215 * Loads category files.
217 * @param string $category
220 protected function loadCategory($category)
222 if (!LanguageFactory
::getInstance()->isValidCategory($category)) {
226 // search language file
227 $filename = WCF_DIR
. 'language/' . $this->languageID
. '_' . $category . '.php';
228 if (!@\file_exists
($filename)) {
229 if (isset($this->categoriesBeingLoaded
[$category])) {
230 throw new \
LogicException("Circular dependency detected! Cannot load category '{$category}' while it is already being loaded.");
233 if ($this->editor
=== null) {
234 $this->editor
= new LanguageEditor($this);
237 // rebuild language file
238 $languageCategory = LanguageFactory
::getInstance()->getCategory($category);
239 if ($languageCategory === null) {
243 $this->categoriesBeingLoaded
[$category] = true;
245 $this->editor
->updateCategory($languageCategory);
247 unset($this->categoriesBeingLoaded
[$category]);
250 // include language file
251 @include_once
($filename);
257 * Returns true if given items includes template scripting.
259 * @param string $item
262 public function isDynamicItem($item)
264 if (isset($this->dynamicItems
[$item])) {
272 * Returns language icon path.
276 public function getIconPath()
278 return WCF
::getPath() . 'icon/flag/' . $this->countryCode
. '.svg';
282 * Returns a list of available languages.
286 public function getLanguages()
288 return LanguageFactory
::getInstance()->getLanguages();
292 * Sets the package id when a language object is unserialized.
294 public function __wakeup()
296 $this->packageID
= PACKAGE_ID
;