ILIAS  release_8 Revision v8.24
class.ilLanguage.php
Go to the documentation of this file.
1<?php
2
20declare(strict_types=1);
21
44{
45 public ILIAS $ilias;
46 public array $text = [];
47 public string $lang_default;
48 public string $lang_user;
49 public string $lang_path;
50 public string $lang_key;
51 public string $lang_name;
52 public string $separator = "#:#";
53 public string $comment_separator = "###";
54 public array $loaded_modules = array();
55 protected static array $used_topics = array();
56 protected static array $used_modules = array();
57 protected array $cached_modules = array();
58 protected array $map_modules_txt = array();
59 protected bool $usage_log_enabled = false;
60 protected static array $lng_log = array();
61 protected string $cust_lang_path;
62 protected ilLogger $log;
64
74 public function __construct(string $a_lang_key)
75 {
76 global $DIC;
77 $client_ini = $DIC->clientIni();
78
79 $this->log = $DIC->logger()->root();
80
81 $this->lang_key = $a_lang_key;
82
83 $this->usage_log_enabled = self::isUsageLogEnabled();
84
85 $this->lang_path = ILIAS_ABSOLUTE_PATH . "/lang";
86 $this->cust_lang_path = ILIAS_ABSOLUTE_PATH . "/Customizing/global/lang";
87
88 $this->lang_default = $client_ini->readVariable("language", "default") ?? 'en';
89 $this->lang_user = $this->lang_default;
90
91 if ($DIC->offsetExists("ilSetting")) {
92 $ilSetting = $DIC->settings();
93 if ($ilSetting->get("language") != "") {
94 $this->lang_default = $ilSetting->get("language");
95 }
96 }
97 if ($DIC->offsetExists("ilUser")) {
98 $ilUser = $DIC->user();
99 $this->lang_user = $ilUser->prefs["language"];
100 }
101
102 $langs = $this->getInstalledLanguages();
103
104 if (!in_array($this->lang_key, $langs, true)) {
105 $this->lang_key = $this->lang_default;
106 }
107
108 require_once("./Services/Language/classes/class.ilCachedLanguage.php");
109 $this->global_cache = ilCachedLanguage::getInstance($this->lang_key);
110 if ($this->global_cache->isActive()) {
111 $this->cached_modules = $this->global_cache->getTranslations();
112 }
113 $this->loadLanguageModule("common");
114 }
115
119 public function getLangKey(): string
120 {
121 return $this->lang_key;
122 }
123
127 public function getDefaultLanguage(): string
128 {
129 return $this->lang_default ?? "en";
130 }
131
135 public function getTextDirection(): string
136 {
137 $rtl = array("ar", "fa", "ur", "he");
138 if (in_array($this->getContentLanguage(), $rtl)) {
139 return "rtl";
140 }
141 return "ltr";
142 }
143
147 public function getContentLanguage(): string
148 {
149 if ($this->getUserLanguage()) {
150 return $this->getUserLanguage();
151 }
152 return $this->getLangKey();
153 }
154
159 public function txtlng(string $a_module, string $a_topic, string $a_language): string
160 {
161 if (strcmp($a_language, $this->lang_key) === 0) {
162 return $this->txt($a_topic);
163 } else {
164 return self::_lookupEntry($a_language, $a_module, $a_topic);
165 }
166 }
167
172 public function txt(string $a_topic, string $a_default_lang_fallback_mod = ""): string
173 {
174 if (empty($a_topic)) {
175 return "";
176 }
177
178 // remember the used topics
179 self::$used_topics[$a_topic] = $a_topic;
180
181 $translation = $this->text[$a_topic] ?? "";
182
183 if ($translation === "" && $a_default_lang_fallback_mod !== "") {
184 // #13467 - try current language first (could be missing module)
185 if ($this->lang_key != $this->lang_default) {
186 $translation = self::_lookupEntry(
187 $this->lang_key,
188 $a_default_lang_fallback_mod,
189 $a_topic
190 );
191 }
192 // try default language last
193 if ($translation === "" || $translation === "-" . $a_topic . "-") {
194 $translation = self::_lookupEntry(
195 $this->lang_default,
196 $a_default_lang_fallback_mod,
197 $a_topic
198 );
199 }
200 }
201
202
203 if ($translation === "") {
204 if (ILIAS_LOG_ENABLED && is_object($this->log)) {
205 $this->log->debug("Language (" . $this->lang_key . "): topic -" . $a_topic . "- not present");
206 }
207 return "-" . $a_topic . "-";
208 }
209
210 if ($this->usage_log_enabled) {
211 self::logUsage($this->map_modules_txt[$a_topic] ?? "", $a_topic);
212 }
213
214 return $translation;
215 }
216
220 public function exists(string $a_topic): bool
221 {
222 return isset($this->text[$a_topic]);
223 }
224
228 public function loadLanguageModule(string $a_module): void
229 {
230 global $DIC;
231 $ilDB = $DIC->database();
232
233 if (in_array($a_module, $this->loaded_modules, true)) {
234 return;
235 }
236
237 $this->loaded_modules[] = $a_module;
238
239 // remember the used modules globally
240 self::$used_modules[$a_module] = $a_module;
241
243
244 if (empty($this->lang_key)) {
246 }
247
248 if (isset($this->cached_modules[$a_module]) && is_array($this->cached_modules[$a_module])) {
249 $this->text = array_merge($this->text, $this->cached_modules[$a_module]);
250
251 if ($this->usage_log_enabled) {
252 foreach (array_keys($this->cached_modules[$a_module]) as $key) {
253 $this->map_modules_txt[$key] = $a_module;
254 }
255 }
256
257 return;
258 }
259
260 $q = "SELECT * FROM lng_modules " .
261 "WHERE lang_key = " . $ilDB->quote($lang_key, "text") . " AND module = " .
262 $ilDB->quote($a_module, "text");
263 $r = $ilDB->query($q);
264 $row = $r->fetchRow(ilDBConstants::FETCHMODE_ASSOC);
265
266 if ($row === false) {
267 return;
268 }
269
270 $new_text = unserialize($row["lang_array"], ["allowed_classes" => false]);
271 if (is_array($new_text)) {
272 $this->text = array_merge($this->text, $new_text);
273
274 if ($this->usage_log_enabled) {
275 foreach (array_keys($new_text) as $key) {
276 $this->map_modules_txt[$key] = $a_module;
277 }
278 }
279 }
280 }
281
285 public function getInstalledLanguages(): array
286 {
288 }
289
293 public static function _getInstalledLanguages(): array
294 {
295 include_once "./Services/Object/classes/class.ilObject.php";
296 $langlist = ilObject::_getObjectsByType("lng");
297
298 $languages = [];
299 foreach ($langlist as $lang) {
300 if (strpos($lang["desc"], "installed") === 0) {
301 $languages[] = $lang["title"];
302 }
303 }
304
305 return $languages ?: [];
306 }
307
308 public static function _lookupEntry(string $a_lang_key, string $a_mod, string $a_id): string
309 {
310 global $DIC;
311 $ilDB = $DIC->database();
312
313 $set = $ilDB->query($q = sprintf(
314 "SELECT * FROM lng_data WHERE module = %s " .
315 "AND lang_key = %s AND identifier = %s",
316 $ilDB->quote($a_mod, "text"),
317 $ilDB->quote($a_lang_key, "text"),
318 $ilDB->quote($a_id, "text")
319 ));
320 $rec = $ilDB->fetchAssoc($set);
321
322 if (isset($rec["value"]) && $rec["value"] != "") {
323 // remember the used topics
324 self::$used_topics[$a_id] = $a_id;
325 self::$used_modules[$a_mod] = $a_mod;
326
327 if (self::isUsageLogEnabled()) {
328 self::logUsage($a_mod, $a_id);
329 }
330
331 return $rec["value"];
332 }
333
334 return "-" . $a_id . "-";
335 }
336
340 public static function lookupId(string $a_lang_key): int
341 {
342 global $DIC;
343 $ilDB = $DIC->database();
344
345 $query = "SELECT obj_id FROM object_data " . " " .
346 "WHERE title = " . $ilDB->quote($a_lang_key, "text") . " " .
347 "AND type = " . $ilDB->quote("lng", "text");
348
349 $res = $ilDB->query($query);
350 while ($row = $res->fetchRow(ilDBConstants::FETCHMODE_OBJECT)) {
351 return (int) $row->obj_id;
352 }
353 return 0;
354 }
355
359 public function getUsedTopics(): array
360 {
361 asort(self::$used_topics);
362 return self::$used_topics;
363 }
364
368 public function getUsedModules(): array
369 {
370 asort(self::$used_modules);
371 return self::$used_modules;
372 }
373
377 public function getUserLanguage(): string
378 {
379 return $this->lang_user;
380 }
381
382 public function getCustomLangPath(): string
383 {
385 }
386
390 public static function getFallbackInstance(): ilLanguage
391 {
392 return new self("en");
393 }
394
398 public static function getGlobalInstance(): self
399 {
400 global $DIC;
401
402 $ilSetting = $DIC->settings();
403
404 $ilUser = null;
405 if ($DIC->offsetExists("ilUser")) {
406 $ilUser = $DIC->user();
407 }
408
409 $isset_get_lang = $DIC->http()->wrapper()->query()->has("lang");
410 if (!ilSession::get("lang") && !$isset_get_lang && $ilUser instanceof ilObjUser &&
411 (!$ilUser->getId() || $ilUser->isAnonymous())) {
412 $language_detection = new ilLanguageDetection();
413 $language = $language_detection->detect();
414
415 ilSession::set("lang", $language);
416 }
417
418 $post_change_lang_to = [];
419 if ($DIC->http()->wrapper()->post()->has('change_lang_to')) {
420 $post_change_lang_to = $DIC->http()->wrapper()->post()->retrieve(
421 'change_lang_to',
422 $DIC->refinery()->kindlyTo()->dictOf(
423 $DIC->refinery()->kindlyTo()->string()
424 )
425 );
426 }
427
428 // prefer personal setting when coming from login screen
429 // Added check for ilUser->getId > 0 because it is 0 when the language is changed and
430 // the terms of service should be displayed
431 if ($ilUser instanceof ilObjUser &&
432 (($ilUser->getId() && !$ilUser->isAnonymous()))
433 ) {
434 ilSession::set("lang", $ilUser->getPref("language"));
435 }
436
437 $get_lang = null;
438 if ($isset_get_lang) {
439 $get_lang = $DIC->http()->wrapper()->query()->retrieve(
440 "lang",
441 $DIC->refinery()->kindlyTo()->string()
442 );
443 }
444 ilSession::set("lang", ($isset_get_lang && $get_lang) ? $get_lang : ilSession::get("lang"));
445
446 // check whether lang selection is valid
448 if (!in_array(ilSession::get("lang"), $langs, true)) {
449 if ($ilSetting instanceof ilSetting && (string) $ilSetting->get("language", '') !== "") {
450 ilSession::set("lang", $ilSetting->get("language"));
451 } else {
452 ilSession::set("lang", $langs[0]);
453 }
454 }
455
456 return new self(ilSession::get("lang"));
457 }
458
466 public function toJS($a_lang_key, ilGlobalTemplateInterface $a_tpl = null): void
467 {
468 global $DIC;
469 $tpl = $DIC["tpl"];
470
471 if (!is_object($a_tpl)) {
472 $a_tpl = $tpl;
473 }
474
475 if (!is_array($a_lang_key)) {
476 $a_lang_key = array($a_lang_key);
477 }
478
479 $map = array();
480 foreach ($a_lang_key as $lk) {
481 $map[$lk] = $this->txt($lk);
482 }
483 $this->toJSMap($map, $a_tpl);
484 }
485
491 public function toJSMap(array $a_map, ilGlobalTemplateInterface $a_tpl = null): void
492 {
493 global $DIC;
494 $tpl = $DIC["tpl"];
495
496 if (!is_object($a_tpl)) {
497 $a_tpl = $tpl;
498 }
499
500 if (!is_array($a_map)) {
501 return;
502 }
503
504 foreach ($a_map as $k => $v) {
505 if ($v != "") {
506 $a_tpl->addOnloadCode("il.Language.setLangVar('" . $k . "', " . json_encode($v, JSON_THROW_ON_ERROR) . ");");
507 }
508 }
509 }
510
514 protected static function logUsage(string $a_module, string $a_identifier): void
515 {
516 if ($a_module !== "" && $a_identifier !== "") {
517 self::$lng_log[$a_identifier] = $a_module;
518 }
519 }
520
527 protected static function isUsageLogEnabled(): bool
528 {
529 global $DIC;
530 $ilClientIniFile = $DIC->clientIni();
531 $ilDB = $DIC->database();
532
533 if (!$ilClientIniFile instanceof ilIniFile) {
534 return false;
535 }
536
537 if (defined("DEVMODE") && DEVMODE) {
538 return true;
539 }
540
541 if (!$ilClientIniFile->variableExists("system", "LANGUAGE_LOG")) {
542 return (int) $ilClientIniFile->readVariable("system", "LANGUAGE_LOG") === 1;
543 }
544 return false;
545 }
546
550 public function __destruct()
551 {
552 global $DIC;
553
554 //case $ilDB not existing should not happen but if something went wrong it shouldn't leads to any failures
555 if (!$this->usage_log_enabled || !$DIC->isDependencyAvailable("database")) {
556 return;
557 }
558
559 $ilDB = $DIC->database();
560
561 foreach (self::$lng_log as $identifier => $module) {
562 $wave[] = "(" . $ilDB->quote($module, "text") . ', ' . $ilDB->quote($identifier, "text") . ")";
563 unset(self::$lng_log[$identifier]);
564
565 if (count($wave) === 150 || (count(self::$lng_log) === 0 && count($wave) > 0)) {
566 $query = "REPLACE INTO lng_log (module, identifier) VALUES " . implode(", ", $wave);
567 $ilDB->manipulate($query);
568
569 $wave = array();
570 }
571 }
572 }
573} // END class.Language
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
language handling
loadLanguageModule(string $a_module)
Load language module.
getLangKey()
Return lang key.
getContentLanguage()
Return content language.
static getFallbackInstance()
Builds a global default language instance.
bool $usage_log_enabled
toJS($a_lang_key, ilGlobalTemplateInterface $a_tpl=null)
Transfer text to Javascript.
static lookupId(string $a_lang_key)
Lookup obj_id of language.
getUsedTopics()
Return used topics.
static array $used_modules
string $lang_default
exists(string $a_topic)
Check if language entry exists.
static _getInstalledLanguages()
Get installed languages.
txt(string $a_topic, string $a_default_lang_fallback_mod="")
gets the text for a given topic if the topic is not in the list, the topic itself with "-" will be re...
static isUsageLogEnabled()
checks if language usage log is enabled you need MySQL to use this function this function is automati...
array $cached_modules
static array $used_topics
getUsedModules()
Return used modules.
__destruct()
destructor saves all language usages to db if log is enabled and ilDB exists
getDefaultLanguage()
Return default language.
static array $lng_log
static logUsage(string $a_module, string $a_identifier)
saves tupel of language module and identifier
array $map_modules_txt
getInstalledLanguages()
Get installed languages.
array $loaded_modules
string $comment_separator
txtlng(string $a_module, string $a_topic, string $a_language)
gets the text for a given topic in a given language if the topic is not in the list,...
getTextDirection()
Return text direction.
static getGlobalInstance()
Builds the global language object.
toJSMap(array $a_map, ilGlobalTemplateInterface $a_tpl=null)
Transfer text to Javascript.
getUserLanguage()
Return language of user.
static _lookupEntry(string $a_lang_key, string $a_mod, string $a_id)
ilCachedLanguage $global_cache
string $cust_lang_path
__construct(string $a_lang_key)
Constructor read the single-language file and put this in an array text.
Component logger with individual log levels by component id.
User class.
static _getObjectsByType(string $obj_type="", int $owner=null)
static get(string $a_var)
static set(string $a_var, $a_val)
Set a value.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
global $DIC
Definition: feed.php:28
$ilUser
Definition: imgupload.php:34
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
if($DIC->http() ->request() ->getMethod()=="GET" &&isset($DIC->http() ->request() ->getQueryParams()['tex'])) $tpl
Definition: latex.php:41
$res
Definition: ltiservices.php:69
string $key
Consumer key/client ID value.
Definition: System.php:193
Class ChatMainBarProvider \MainMenu\Provider.
global $ilSetting
Definition: privfeed.php:17
$query
$lang
Definition: xapiexit.php:26