Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions lib/bundles/base.js
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ window._ = require('lodash');
// add translation function into global scope
// signature is almost the same as for PHP functions, but accept extra arguments for string variables
window.i18n = require('gettext.js/lib/gettext').default({domain: 'glpi'});
if (window.loadLocales !== undefined) {
await window.loadLocales();
}

const escape_msgid = function (msgid) {
return msgid.replace(/%(\d+)\$/g, '%%$1\$');
Expand Down
52 changes: 23 additions & 29 deletions src/Glpi/Application/View/Extension/FrontEndAssetsExtension.php
Original file line number Diff line number Diff line change
Expand Up @@ -242,36 +242,30 @@ public function localesJs(): string
$locales_domains[$plugin] = Plugin::getPluginFilesVersion($plugin);
}

$script = "
$(function() {
i18n.setLocale('" . \jsescape($_SESSION['glpilanguage']) . "');
});

$.fn.select2.defaults.set(
'language',
'" . \jsescape($CFG_GLPI['languages'][$_SESSION['glpilanguage']][2]) . "',
);
";

foreach ($locales_domains as $locale_domain => $locale_version) {
$locales_path = Html::getPrefixedUrl(
'/front/locale.php'
. '?domain=' . $locale_domain
. '&lang=' . $_SESSION['glpilanguage']
. '&v=' . FrontEnd::getVersionCacheKey($locale_version)
);
$script .= "
$(function() {
$.ajax({
type: 'GET',
url: '" . \jsescape($locales_path) . "',
success: function(json) {
i18n.loadJSON(json, '" . \jsescape($locale_domain) . "');
$locales_json = json_encode(array_combine(array_keys($locales_domains), array_map(static fn($domain, $version) => Html::getPrefixedUrl(
'/front/locale.php'
. '?domain=' . $domain
. '&lang=' . $_SESSION['glpilanguage']
. '&v=' . FrontEnd::getVersionCacheKey($version)
), array_keys($locales_domains), $locales_domains)));

$script = <<<JS
// Fetch locale JSON without jQuery to allow fetching before jQuery is loaded
async function loadLocales() {
const locales = $locales_json;
const promises = [];
for (const [domain, url] of Object.entries(locales)) {
promises.push(window.fetch(url).then(response => {
if (response.ok) {
return response.json().then(data => {
i18n.loadJSON(data, domain);
});
}
});
});
";
}
}));
}
await Promise.all(promises);
}
JS;

return Html::scriptBlock($script);
}
Expand Down
4 changes: 3 additions & 1 deletion src/Html.php
Original file line number Diff line number Diff line change
Expand Up @@ -1050,9 +1050,11 @@ public static function includeHeader(

$theme = ThemeManager::getInstance()->getCurrentTheme();
$lang = $_SESSION['glpilanguage'] ?? Session::getPreferredLanguage();
// Force lang to be BCP 47 compliant
$lang = str_replace('_', '-', $lang);

$tpl_vars = [
'lang' => $CFG_GLPI["languages"][$lang][3],
'lang' => $lang,
'title' => $title,
'theme' => $theme,
'is_anonymous_page' => false,
Expand Down
4 changes: 2 additions & 2 deletions templates/layout/parts/head.html.twig
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,13 @@

{{ config_js() }}

{{ locales_js() }}

{% for js_file in js_files %}
<script type="text/javascript" src="{{ js_path(js_file.path, js_file.options ?? []) }}"></script>
{% endfor %}

{% for js_file in js_modules %}
<script type="module" src="{{ js_path(js_file.path, js_file.options ?? []) }}"></script>
{% endfor %}

{{ locales_js() }}
</head>