Skip to content

Commit ac802aa

Browse files
committed
rework client-side language handling to improve availability
1 parent 0685c50 commit ac802aa

File tree

4 files changed

+30
-29
lines changed

4 files changed

+30
-29
lines changed

lib/bundles/base.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,9 @@ window._ = require('lodash');
9797
// add translation function into global scope
9898
// signature is almost the same as for PHP functions, but accept extra arguments for string variables
9999
window.i18n = require('gettext.js/lib/gettext').default({domain: 'glpi'});
100+
if (window.loadLocales !== undefined) {
101+
await window.loadLocales();
102+
}
100103

101104
const escape_msgid = function (msgid) {
102105
return msgid.replace(/%(\d+)\$/g, '%%$1\$');

src/Glpi/Application/View/Extension/FrontEndAssetsExtension.php

Lines changed: 22 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -242,36 +242,32 @@ public function localesJs(): string
242242
$locales_domains[$plugin] = Plugin::getPluginFilesVersion($plugin);
243243
}
244244

245-
$script = "
246-
$(function() {
247-
i18n.setLocale('" . \jsescape($_SESSION['glpilanguage']) . "');
248-
});
249-
250-
$.fn.select2.defaults.set(
251-
'language',
252-
'" . \jsescape($CFG_GLPI['languages'][$_SESSION['glpilanguage']][2]) . "',
253-
);
254-
";
255-
256-
foreach ($locales_domains as $locale_domain => $locale_version) {
257-
$locales_path = Html::getPrefixedUrl(
245+
$locales_json = json_encode(array_combine(array_keys($locales_domains), array_map(static function ($domain, $version) {
246+
return Html::getPrefixedUrl(
258247
'/front/locale.php'
259-
. '?domain=' . $locale_domain
248+
. '?domain=' . $domain
260249
. '&lang=' . $_SESSION['glpilanguage']
261-
. '&v=' . FrontEnd::getVersionCacheKey($locale_version)
250+
. '&v=' . FrontEnd::getVersionCacheKey($version)
262251
);
263-
$script .= "
264-
$(function() {
265-
$.ajax({
266-
type: 'GET',
267-
url: '" . \jsescape($locales_path) . "',
268-
success: function(json) {
269-
i18n.loadJSON(json, '" . \jsescape($locale_domain) . "');
252+
}, array_keys($locales_domains), $locales_domains)));
253+
254+
$script = <<<JS
255+
// Fetch locale JSON without jQuery to allow fetching before jQuery is loaded
256+
async function loadLocales() {
257+
const locales = $locales_json;
258+
const promises = [];
259+
for (const [domain, url] of Object.entries(locales)) {
260+
promises.push(window.fetch(url).then(response => {
261+
if (response.ok) {
262+
return response.json().then(data => {
263+
i18n.loadJSON(data, domain);
264+
});
270265
}
271-
});
272-
});
273-
";
274-
}
266+
}));
267+
}
268+
await Promise.all(promises);
269+
}
270+
JS;
275271

276272
return Html::scriptBlock($script);
277273
}

src/Html.php

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1050,9 +1050,11 @@ public static function includeHeader(
10501050

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

10541056
$tpl_vars = [
1055-
'lang' => $CFG_GLPI["languages"][$lang][3],
1057+
'lang' => $lang,
10561058
'title' => $title,
10571059
'theme' => $theme,
10581060
'is_anonymous_page' => false,

templates/layout/parts/head.html.twig

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,13 +79,13 @@
7979

8080
{{ config_js() }}
8181

82+
{{ locales_js() }}
83+
8284
{% for js_file in js_files %}
8385
<script type="text/javascript" src="{{ js_path(js_file.path, js_file.options ?? []) }}"></script>
8486
{% endfor %}
8587

8688
{% for js_file in js_modules %}
8789
<script type="module" src="{{ js_path(js_file.path, js_file.options ?? []) }}"></script>
8890
{% endfor %}
89-
90-
{{ locales_js() }}
9191
</head>

0 commit comments

Comments
 (0)