19declare(strict_types=1);
58 return $this->data->text()->markdown()->simpleDocument(
60Installs one or
more languages in the
ILIAS system, or applies just their
61customizing/local
language file, depending on the chosen mode.
63Mode
"install" fully installs a
language that is not yet installed (
base
64data, plus a customizing/local file
if one exists) and leaves an already
65installed
language completely untouched.
Mode "install_local" instead
66(re-)applies only the customizing/local file on top of an already installed
67language, without touching its
base data, and leaves a not-yet-installed
70In both modes, invalid
language files (including a shipped `.po`) reject the
71request as a whole before anything is written.
78 $language_keys =
$f->text(
80 'Comma-separated list of language keys, e.g. de, fr, it.'
81 )->withRequired(
true)->withDedicatedName(
'language_keys');
86 self::MODE_INSTALL =>
'Install',
87 self::MODE_INSTALL_LOCAL =>
'Install local',
89 'Whether to fully install the given languages, or to only ' .
90 '(re-)apply their customizing/local file on top of an existing ' .
92 )->withRequired(
true)->withDedicatedName(
'mode');
95 'language_keys' => $language_keys,
97 ],
'Install languages');
102 $text = $this->data->text()->markdown();
105 $text->simpleDocument(
'Result of the language installation.'),
107 'installed_language_keys' =>
$f->list(
108 $text->simpleDocument(
'Newly installed languages without a custom language file.'),
109 $f->string(
$text->simpleDocument(
'Language key of a newly installed language.'))
111 'installed_with_local_language_keys' =>
$f->list(
112 $text->simpleDocument(
113 'Languages for which a custom/local language file was (re-)installed - ' .
114 'either as part of a fresh installation (mode "install"), or applied on ' .
115 'top of an already installed language (mode "install_local").'
117 $f->string(
$text->simpleDocument(
'Language key of a language with an installed custom language file.'))
119 'already_installed_language_keys' =>
$f->list(
120 $text->simpleDocument(
121 'Languages for which this run changed nothing: mode "install" was ' .
122 'requested for a language that was already installed (a no-op by design ' .
123 '- use mode "install_local" to (re-)apply a customizing file instead), ' .
124 'or mode "install_local" was requested for an installed language that ' .
125 'has no customizing/local file to apply.'
127 $f->string(
$text->simpleDocument(
'Language key of an already installed language.'))
129 'not_installed_language_keys' =>
$f->list(
130 $text->simpleDocument(
131 'Languages requested with mode "install_local" that are not installed - ' .
132 'skipped entirely, since there is nothing installed yet to apply local ' .
135 $f->string(
$text->simpleDocument(
'Language key of a not-yet-installed language.'))
137 'invalid_local_language_files' =>
$f->list(
138 $text->simpleDocument(
'Local language files with an invalid file name.'),
139 $f->string(
$text->simpleDocument(
'File name of an invalid local language file.'))
141 'overlay_write_failed_language_keys' => $this->overlayWriteFailedOutputField(
$f),
142 'invalid_markup_customizing_entries' => $this->invalidMarkupCustomizingOutputField(
$f),
143 'duplicate_customizing_entries' => $this->duplicateCustomizingOutputField(
$f),
155 $mode = $this->
toMode($parameters[
'mode'] ??
null);
157 $currently_installed_language_keys = $this->setup_language->getInstalledLanguages();
159 $to_fully_install = [];
160 $to_apply_local_changes = [];
161 $already_installed_no_op = [];
162 $not_installed_no_op = [];
164 foreach ($language_keys as $language_key) {
165 $is_installed = in_array($language_key, $currently_installed_language_keys,
true);
166 if ($mode === self::MODE_INSTALL) {
168 $already_installed_no_op[] = $language_key;
170 $to_fully_install[] = $language_key;
172 } elseif ($is_installed) {
173 $to_apply_local_changes[] = $language_key;
175 $not_installed_no_op[] = $language_key;
179 $error_language_keys = [];
181 foreach (array_merge($to_fully_install, $to_apply_local_changes) as $language_key) {
182 if (!$this->setup_language->checkLanguageForInstallation($language_key)) {
183 $error_language_keys[] = $language_key;
187 if ($error_language_keys !== []) {
189 $unknown_language_keys = array_values(array_diff(
190 array_intersect($error_language_keys, $to_fully_install),
191 $this->setup_language->getInstallableLanguagesForInstallation()
193 if ($unknown_language_keys !== []) {
199 $installed_language_keys = [];
200 $installed_with_local_language_keys = [];
201 $invalid_local_language_files = [];
202 $overlay_write_failed_language_keys = [];
204 $affected_language_keys = array_merge($to_fully_install, $to_apply_local_changes);
205 if ($affected_language_keys !== []) {
206 $db_languages = $this->setup_language->getAvailableLanguagesForInstallation();
207 $local_language_keys = $this->setup_language->getLocalLanguages();
208 $invalid_local_language_files = $this->setup_language->getInvalidLocalLanguageFiles(
209 $affected_language_keys
212 foreach ($to_fully_install as $language_key) {
213 $this->setup_language->flushLanguageForInstallation($language_key);
214 if ($this->setup_language->insertLanguageForInstallation($language_key) !== []) {
215 $overlay_write_failed_language_keys[] = $language_key;
217 $this->setup_language->registerInstalledLanguage($language_key, $db_languages, $local_language_keys);
219 if (in_array($language_key, $local_language_keys,
true)) {
220 $installed_with_local_language_keys[] = $language_key;
222 $installed_language_keys[] = $language_key;
226 foreach ($to_apply_local_changes as $language_key) {
227 if ($this->setup_language->insertLanguageForApplyingLocalChanges($language_key) !== []) {
228 $overlay_write_failed_language_keys[] = $language_key;
230 $this->setup_language->registerInstalledLanguage($language_key, $db_languages, $local_language_keys);
232 if (in_array($language_key, $local_language_keys,
true)) {
233 $installed_with_local_language_keys[] = $language_key;
236 $already_installed_no_op[] = $language_key;
242 'installed_language_keys' => $installed_language_keys,
243 'installed_with_local_language_keys' => $installed_with_local_language_keys,
244 'already_installed_language_keys' => $already_installed_no_op,
245 'not_installed_language_keys' => $not_installed_no_op,
246 'invalid_local_language_files' => $invalid_local_language_files,
247 'overlay_write_failed_language_keys' => $overlay_write_failed_language_keys,
249 $this->setup_language->getSkippedInvalidMarkupEntries(),
250 $affected_language_keys
253 $this->setup_language->getSkippedDuplicateEntries(),
254 $affected_language_keys
259 private function toMode(mixed $value): string
261 if ($value === self::MODE_INSTALL || $value === self::MODE_INSTALL_LOCAL) {
266 'mode must be either "' . self::MODE_INSTALL .
'" or "' . self::MODE_INSTALL_LOCAL .
'".'
278 'mode' => $this->
toMode($grind_result[
'mode']),
This describes some datastructure in terms of standard data structures such as primitives,...
static forSetup(\ilSetupLanguage $setup_language)
__construct(?RBAC $rbac, private readonly \ilSetupLanguage $setup_language, LanguageFolder $language_folder,)
const string MODE_INSTALL_LOCAL
getInputDescription(FieldFactory $f)
perform(mixed $parameters)
This shall perform the activity.
normalizeParameters(array $grind_result)
getOutputDescription(Description\Factory $f)
const string MODE_INSTALL
A state of the server, not of the call: 409, so Failure::of() passes it on and the GUI can name the l...
duplicateCustomizingEntries(array $skipped, array $language_keys)
invalidMarkupCustomizingEntries(array $skipped, array $language_keys)
Looks the ref_id up on every call, so it can be built at build time without database access.
language handling for setup
Public RBAC service of the AccessControl component.
The language folder in the administration, whose "write" permission guards the language Activities.
__construct(Container $dic, ilPlugin $plugin)
@inheritDoc
toLanguageKeyList(mixed $value)
trait ParsesLanguageKeyList
Interface Observer \BackgroundTasks Contains several chained tasks and infos about them.