ILIAS  release_8 Revision v8.24
class.ilSetupLanguage.php
Go to the documentation of this file.
1<?php
2
41{
42 public array $text;
43 public string $lang_default = "en";
44 public string $lang_path;
45 public string $lang_key;
46 public string $separator = "#:#";
47 public string $comment_separator = "###";
48 protected ilDBInterface $db;
49
50 public function __construct(string $a_lang_key)
51 {
52 $this->lang_key = $a_lang_key ?: $this->lang_default;
53 $il_absolute_path = realpath(__DIR__ . "/../../../../");
54 $this->lang_path = $il_absolute_path . "/lang";
55 $this->cust_lang_path = $il_absolute_path . "/Customizing/global/lang";
56 }
57
65 public function txt(string $a_topic, string $a_default_lang_fallback_mod = ''): string
66 {
67 global $log;
68
69 if (empty($a_topic)) {
70 return "";
71 }
72
73 $translation = $this->text[$a_topic] ?? '';
74
75 //get position of the comment_separator
76 $pos = strpos($translation, $this->comment_separator);
77
78 if ($pos !== false) {
79 // remove comment
80 $translation = substr($translation, 0, $pos);
81 }
82
83 if ($translation === "") {
84 $log->writeLanguageLog($a_topic, $this->lang_key);
85 return "-" . $a_topic . "-";
86 }
87
88 return $translation;
89 }
90
98 public function installLanguages(array $a_lang_keys, array $a_local_keys)
99 {
100 global $ilDB;
101
102 if (empty($a_lang_keys)) {
103 $a_lang_keys = array();
104 }
105
106 if (empty($a_local_keys)) {
107 $a_local_keys = array();
108 }
109
110 $err_lang = array();
111
112 $db_langs = $this->getAvailableLanguages();
113
114 foreach ($a_lang_keys as $lang_key) {
115 if ($this->checkLanguage($lang_key)) {
116 $this->flushLanguage($lang_key, "keep_local");
117 $this->insertLanguage($lang_key);
118
119 if (in_array($lang_key, $a_local_keys, true) && is_dir($this->cust_lang_path)) {
120 if ($this->checkLanguage($lang_key, "local")) {
121 $this->insertLanguage($lang_key, "local");
122 } else {
123 $err_lang[] = $lang_key;
124 }
125 }
126
127 // register language first time install
128 if (!array_key_exists($lang_key, $db_langs)) {
129 if (in_array($lang_key, $a_local_keys, true)) {
130 $itype = "installed_local";
131 } else {
132 $itype = "installed";
133 }
134 $lid = $ilDB->nextId("object_data");
135 $query = "INSERT INTO object_data " .
136 "(obj_id,type,title,description,owner,create_date,last_update) " .
137 "VALUES " .
138 "(" .
139 $ilDB->quote($lid, "integer") . "," .
140 $ilDB->quote("lng", "text") . "," .
141 $ilDB->quote($lang_key, "text") . "," .
142 $ilDB->quote($itype, "text") . "," .
143 $ilDB->quote("-1", "integer") . "," .
144 $ilDB->now() . "," .
145 $ilDB->now() .
146 ")";
147 $ilDB->manipulate($query);
148 }
149 } else {
150 $err_lang[] = $lang_key;
151 }
152 }
153
154 foreach ($db_langs as $key => $val) {
155 if (!in_array($key, $err_lang, true)) {
156 if (in_array($key, $a_lang_keys, true)) {
157 if (in_array($key, $a_local_keys, true)) {
158 $ld = "installed_local";
159 } else {
160 $ld = "installed";
161 }
162 $query = "UPDATE object_data SET " .
163 "description = " . $ilDB->quote($ld, "text") . ", " .
164 "last_update = " . $ilDB->now() . " " .
165 "WHERE obj_id = " . $ilDB->quote($val["obj_id"], "integer") . " " .
166 "AND type = " . $ilDB->quote("lng", "text");
167 $ilDB->manipulate($query);
168 } else {
169 $this->flushLanguage($key, "all");
170
171 if (strpos($val["status"], "installed") === 0) {
172 $query = "UPDATE object_data SET " .
173 "description = " . $ilDB->quote("not_installed", "text") . ", " .
174 "last_update = " . $ilDB->now() . " " .
175 "WHERE obj_id = " . $ilDB->quote($val["obj_id"], "integer") . " " .
176 "AND type = " . $ilDB->quote("lng", "text");
177 $ilDB->manipulate($query);
178 }
179 }
180 }
181 }
182
183 return ($err_lang) ?: true;
184 }
185
186
187
191 public function getInstalledLanguages(): array
192 {
193 global $ilDB;
194 $arr = [];
195 if ($ilDB instanceof ilDBInterface) {
196 $query = "SELECT * FROM object_data " .
197 "WHERE type = " . $ilDB->quote("lng", "text") . " " .
198 "AND " . $ilDB->like("description", "text", "installed%");
199 $r = $ilDB->query($query);
200
201 while ($row = $ilDB->fetchObject($r)) {
202 $arr[] = $row->title;
203 }
204 }
205 return $arr;
206 }
207
211 public function getInstalledLocalLanguages(): array
212 {
213 global $ilDB;
214 $arr = [];
215 if ($ilDB instanceof ilDBInterface) {
216 $query = "SELECT * FROM object_data " .
217 "WHERE type = " . $ilDB->quote("lng", "text") . " " .
218 "AND description = " . $ilDB->quote("installed_local", "text");
219 $r = $ilDB->query($query);
220
221 while ($row = $ilDB->fetchObject($r)) {
222 $arr[] = $row->title;
223 }
224 }
225 return $arr;
226 }
227
231 protected function getAvailableLanguages(): array
232 {
233 global $ilDB;
234
235 $arr = array();
236
237 $query = "SELECT * FROM object_data " .
238 "WHERE type = " . $ilDB->quote("lng", "text");
239 $r = $ilDB->query($query);
240
241 while ($row = $ilDB->fetchObject($r)) {
242 $arr[$row->title]["obj_id"] = $row->obj_id;
243 $arr[$row->title]["status"] = $row->description;
244 }
245
246 return $arr;
247 }
248
260 protected function checkLanguage(string $a_lang_key, string $scope = ""): bool
261 {
262 $scopeExtension = "";
263 if (!empty($scope)) {
264 if ($scope === "global") {
265 $scope = "";
266 } else {
267 $scopeExtension = "." . $scope;
268 }
269 }
270
272 if ($scope === "local") {
274 }
275
276 $tmpPath = getcwd();
277 chdir($path);
278
279 // compute lang-file name format
280 $lang_file = "ilias_" . $a_lang_key . ".lang" . $scopeExtension;
281
282 // file check
283 if (!is_file($lang_file)) {
284 chdir($tmpPath);
285 return false;
286 }
287
288 // header check
289 if (!$content = $this->cut_header(file($lang_file))) {
290 chdir($tmpPath);
291 return false;
292 }
293
294 // check (counting) elements of each lang-entry
295 foreach ($content as $key => $val) {
296 $separated = explode($this->separator, trim($val));
297 $num = count($separated);
298
299 if ($num !== 3) {
300 chdir($tmpPath);
301 return false;
302 }
303 }
304
305 chdir($tmpPath);
306
307 // no error occured
308 return true;
309 }
310
321 protected function cut_header(array $content)
322 {
323 foreach ($content as $key => $val) {
324 if (trim($val) === "<!-- language file start -->") {
325 return array_slice($content, $key + 1);
326 }
327 }
328 return false;
329 }
330
336 protected function flushLanguage(string $a_lang_key, string $a_mode = "all"): void
337 {
338 global $ilDB;
339
340 self::_deleteLangData($a_lang_key, ($a_mode === "keep_local"));
341
342 if ($a_mode === "all") {
343 $ilDB->manipulate("DELETE FROM lng_modules WHERE lang_key = " .
344 $ilDB->quote($a_lang_key, "text"));
345 }
346 }
347
353 public static function _deleteLangData(string $a_lang_key, bool $a_keep_local_change): void
354 {
355 global $ilDB;
356
357 if (!$a_keep_local_change) {
358 $ilDB->manipulate("DELETE FROM lng_data WHERE lang_key = " .
359 $ilDB->quote($a_lang_key, "text"));
360 } else {
361 $ilDB->manipulate("DELETE FROM lng_data WHERE lang_key = " .
362 $ilDB->quote($a_lang_key, "text") .
363 " AND local_change IS NULL");
364 }
365 }
366
374 public function getLocalChanges(string $a_lang_key, string $a_min_date = "", string $a_max_date = ""): array
375 {
376 global $ilDB;
377
378 if ($a_min_date === "") {
379 $a_min_date = "1980-01-01 00:00:00";
380 }
381 if ($a_max_date === "") {
382 $a_max_date = "2200-01-01 00:00:00";
383 }
384
385 $q = sprintf(
386 "SELECT * FROM lng_data WHERE lang_key = %s " .
387 "AND local_change >= %s AND local_change <= %s",
388 $ilDB->quote($a_lang_key, "text"),
389 $ilDB->quote($a_min_date, "timestamp"),
390 $ilDB->quote($a_max_date, "timestamp")
391 );
392 $result = $ilDB->query($q);
393
394 $changes = array();
395 while ($row = $result->fetchRow(ilDBConstants::FETCHMODE_ASSOC)) {
396 $changes[$row["module"]][$row["identifier"]] = $row["value"];
397 }
398 return $changes;
399 }
400
401
402 //TODO: remove redundant checks here!
409 protected function insertLanguage(string $lang_key, string $scope = ""): void
410 {
411 global $ilDB;
412
413 $lang_array = array();
414
415 $scopeExtension = "";
416 if (!empty($scope)) {
417 if ($scope === "global") {
418 $scope = "";
419 } else {
420 $scopeExtension = "." . $scope;
421 }
422 }
423
425 if ($scope === "local") {
427 }
428
429 $tmpPath = getcwd();
430 chdir($path);
431
432 $lang_file = "ilias_" . $lang_key . ".lang" . $scopeExtension;
433 $change_date = null;
434
435 if (is_file($lang_file)) {
436 // initialize the array for updating lng_modules below
437 $lang_array = [];
438 $lang_array["common"] = [];
439
440 // remove header first
441 if ($content = $this->cut_header(file($lang_file))) {
442 // get the local changes from the database
443 if (empty($scope)) {
444 $local_changes = $this->getLocalChanges($lang_key);
445 } elseif ($scope === "local") {
446 // set the change date to import time for a local file
447 // get the modification date of the local file
448 // get the newer local changes for a local file
449 $change_date = date("Y-m-d H:i:s", time());
450 $min_date = date("Y-m-d H:i:s", filemtime($lang_file));
451 $local_changes = $this->getLocalChanges($lang_key, $min_date);
452 }
453
454 $query_check = false;
455 $query = "INSERT INTO lng_data (module,identifier,lang_key,value,local_change,remarks) VALUES ";
456 foreach ($content as $key => $val) {
457 // split the line of the language file
458 // [0]: module
459 // [1]: identifier
460 // [2]: value
461 // [3]: comment (optional)
462 $separated = explode($this->separator, trim($val));
463
464 //get position of the comment_separator
465 $pos = strpos($separated[2], $this->comment_separator);
466
467 if ($pos !== false) {
468 //cut comment of
469 $separated[2] = substr($separated[2], 0, $pos);
470 }
471
472 // check if the value has a local change
473 if (isset($local_changes[$separated[0]])) {
474 $local_value = $local_changes[$separated[0]][$separated[1]] ?? "";
475 } else {
476 $local_value = "";
477 }
478
479 if (empty($scope)) {
480 if ($local_value !== "" && $local_value !== $separated[2]) {
481 // keep the locally changed value
482 $lang_array[$separated[0]][$separated[1]] = $local_value;
483 continue;
484 }
485 } elseif ($scope === "local") {
486 if ($local_value !== "") {
487 // keep a locally changed value that is newer than the local file
488 $lang_array[$separated[0]][$separated[1]] = $local_value;
489 continue;
490 }
491 }
492
493 $query .= sprintf(
494 "(%s,%s,%s,%s,%s,%s),",
495 $ilDB->quote($separated[0], "text"),
496 $ilDB->quote($separated[1], "text"),
497 $ilDB->quote($lang_key, "text"),
498 $ilDB->quote($separated[2], "text"),
499 $ilDB->quote($change_date, "timestamp"),
500 $ilDB->quote($separated[3] ?? null, "text")
501 );
502 $query_check = true;
503 $lang_array[$separated[0]][$separated[1]] = $separated[2];
504 }
505 $query = rtrim($query, ",") . " ON DUPLICATE KEY UPDATE value=VALUES(value),remarks=VALUES(remarks);";
506 if ($query_check) {
507 $ilDB->manipulate($query);
508 }
509 }
510
511 $query = "INSERT INTO lng_modules (module, lang_key, lang_array) VALUES ";
512 $modules_to_delete = [];
513 foreach ($lang_array as $module => $lang_arr) {
514 if ($scope === "local") {
515 $q = "SELECT * FROM lng_modules WHERE " .
516 " lang_key = " . $ilDB->quote($lang_key, "text") .
517 " AND module = " . $ilDB->quote($module, "text");
518 $set = $ilDB->query($q);
519 $row = $ilDB->fetchAssoc($set);
520 $arr2 = unserialize($row["lang_array"], ["allowed_classes" => false]);
521 if (is_array($arr2)) {
522 $lang_arr = array_merge($arr2, $lang_arr);
523 }
524 }
525 $query .= sprintf(
526 "(%s,%s,%s),",
527 $ilDB->quote($module, "text"),
528 $ilDB->quote($lang_key, "text"),
529 $ilDB->quote(serialize($lang_arr), "clob"),
530 );
531 $modules_to_delete[] = $module;
532 }
533
534 $inModulesToDelete = $ilDB->in('module', $modules_to_delete, false, 'text');
535 $ilDB->manipulate(sprintf("DELETE FROM lng_modules WHERE lang_key = %s AND $inModulesToDelete",
536 $ilDB->quote($lang_key, "text")
537 ));
538
539 $query = rtrim($query, ",") . ";";
540 $ilDB->manipulate($query);
541 }
542
543 chdir($tmpPath);
544 }
545
550 public function getLocalLanguages(): array
551 {
552 $local_langs = array();
553 if (is_dir($this->cust_lang_path)) {
554 $d = dir($this->cust_lang_path);
555 $tmpPath = getcwd();
556 chdir($this->cust_lang_path);
557
558 // get available .lang.local files
559 while ($entry = $d->read()) {
560 if (is_file($entry) && (preg_match("~(^ilias_.{2}\.lang.local$)~", $entry))) {
561 $lang_key = substr($entry, 6, 2);
562 $local_langs[] = $lang_key;
563 }
564 }
565
566 chdir($tmpPath);
567 }
568
569 return $local_langs;
570 }
571
575 public function getInstallableLanguages(): array
576 {
577 $d = dir($this->lang_path);
578 $tmpPath = getcwd();
579 chdir($this->lang_path);
580
581 $installableLanguages = [];
582 // get available lang-files
583 while ($entry = $d->read()) {
584 if (is_file($entry) && (preg_match("~(^ilias_.{2}\.lang$)~", $entry))) {
585 $lang_key = substr($entry, 6, 2);
586 $installableLanguages[] = $lang_key;
587 }
588 }
589
590 chdir($tmpPath);
591
592 return $installableLanguages;
593 }
594
600 public function setDbHandler(ilDBInterface $a_db_handler): bool
601 {
602 $this->db = &$a_db_handler;
603 return true;
604 }
605
606 public function loadLanguageModule(string $a_module): void
607 {
608 }
609}
language handling
string $cust_lang_path
writeLanguageLog(string $a_topic, string $a_lang_key)
Write language log.
This file is part of ILIAS, a powerful learning management system published by ILIAS open source e-Le...
getLocalChanges(string $a_lang_key, string $a_min_date="", string $a_max_date="")
get locally changed language entries $a_lang_key language key $a_min_date minimum change date "yyyy-m...
cut_header(array $content)
Remove *.lang header information from '$content'.
installLanguages(array $a_lang_keys, array $a_local_keys)
install languages
txt(string $a_topic, string $a_default_lang_fallback_mod='')
gets the text for a given topic
flushLanguage(string $a_lang_key, string $a_mode="all")
remove language data from database $a_lang_key language key $a_mode "all" or "keep_local"
getInstalledLanguages()
get already installed languages (in db)
loadLanguageModule(string $a_module)
Load language module.
__construct(string $a_lang_key)
Constructor read the single-language file and put this in an array text.
getAvailableLanguages()
get already registered languages (in db)
getInstalledLocalLanguages()
get already installed local languages (in db)
getLocalLanguages()
Searches for the existence of *.lang.local files.
insertLanguage(string $lang_key, string $scope="")
insert language data from file in database
static _deleteLangData(string $a_lang_key, bool $a_keep_local_change)
Delete languge data.
checkLanguage(string $a_lang_key, string $scope="")
validate the logical structure of a lang-file
setDbHandler(ilDBInterface $a_db_handler)
set db handler object @string object db handler Return true on success
getInstallableLanguages()
Return installable languages.
for( $i=6;$i< 13;$i++) for($i=1; $i< 13; $i++) $d
Definition: date.php:296
Interface ilDBInterface.
$scope
Definition: ltiregstart.php:53
$path
Definition: ltiservices.php:32
string $key
Consumer key/client ID value.
Definition: System.php:193
$query