161 lines
4.9 KiB
JavaScript
161 lines
4.9 KiB
JavaScript
/* This file is copyright under the latest version of the EUPL.
|
|
* Please see LICENSE file for your rights under this license. */
|
|
|
|
"use strict";
|
|
|
|
const defaultLang = "en-us";
|
|
const lang = (new URL(location.href).searchParams.get("lang") || defaultLang).toLowerCase();
|
|
/** @type {{ [key in string]: string }} */
|
|
let translations;
|
|
|
|
waitFor(
|
|
() => document.body?.dataset,
|
|
async () => {
|
|
translations = await getTranslations(lang);
|
|
}
|
|
);
|
|
|
|
function hasKey(key) {
|
|
return Boolean(translations?.[key]);
|
|
}
|
|
|
|
function t(key) {
|
|
if (!translations) {
|
|
console.warn("waiting for translation:", key); // eslint-disable-line no-console
|
|
return waitForTranslations(() => t(key));
|
|
}
|
|
|
|
return translations[key] || `[${key}]`;
|
|
}
|
|
|
|
function tf(key, ...substitutes) {
|
|
if (!translations) {
|
|
console.warn("waiting for translation:", key); // eslint-disable-line no-console
|
|
return waitForTranslations(() => tf(key, ...substitutes));
|
|
}
|
|
|
|
const value = translations[key];
|
|
if (!value) return `[${key}]`;
|
|
|
|
const placeholderCount = value.match(/\%s/g)?.length || 0; // eslint-disable-line unicorn/better-regex, no-useless-escape
|
|
if (placeholderCount !== substitutes.length) {
|
|
console.error("Amount of placeholder and substitutes don't match!"); // eslint-disable-line no-console
|
|
return `[${key}]`;
|
|
}
|
|
|
|
let i = 0;
|
|
return value.replaceAll(/\%s/g, () => substitutes[i++]); // eslint-disable-line unicorn/better-regex, no-useless-escape, unicorn/prefer-string-replace-all
|
|
}
|
|
|
|
function waitFor(conditionFunc, func) {
|
|
return new Promise(resolve => {
|
|
const wait = () => {
|
|
if (conditionFunc()) resolve(func());
|
|
else requestAnimationFrame(() => wait());
|
|
};
|
|
|
|
wait();
|
|
});
|
|
}
|
|
|
|
function waitForTranslations(func) {
|
|
return waitFor(() => translations, func);
|
|
}
|
|
|
|
/**
|
|
* Gets the translations from the server
|
|
* @param {string} lang Language for the translation
|
|
* @returns {Promise<{ [key in string]: string }>}
|
|
*/
|
|
function getTranslations(lang) {
|
|
return fetch(`${document.body.dataset.webhome}i18n/${lang}.ini`)
|
|
.then(res => res.text())
|
|
.then(content => iniToObject(content))
|
|
.catch(error => {
|
|
console.error(error); // eslint-disable-line no-console
|
|
return lang === defaultLang ? {} : getTranslations(defaultLang);
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Converts the content of an ini-file to an object
|
|
* @param {string} content The content of an ini-file
|
|
* @returns { [key in string]: string }
|
|
*/
|
|
function iniToObject(content) {
|
|
// eslint-disable-next-line unicorn/no-array-reduce
|
|
return content.split("\n").reduce((prev, curr) => {
|
|
const index = curr.indexOf("=");
|
|
const key = curr.substring(0, index).trim();
|
|
const value = curr.substring(index + 1).trim();
|
|
|
|
if (key && value) {
|
|
if (prev[key]) console.warn(key); // eslint-disable-line no-console
|
|
|
|
// unescape new-lines
|
|
const unescapedValue = value.replaceAll(/\\n/g, "\n"); // eslint-disable-line unicorn/prefer-string-replace-all
|
|
if (Object.values(prev).includes(unescapedValue)) console.debug(unescapedValue); // eslint-disable-line no-console
|
|
|
|
prev[key] = unescapedValue;
|
|
}
|
|
|
|
return prev;
|
|
}, {});
|
|
}
|
|
|
|
globalThis.i18n = (function () {
|
|
return {
|
|
lang,
|
|
hasKey,
|
|
t,
|
|
tf,
|
|
waitForTranslations,
|
|
};
|
|
})();
|
|
|
|
// translate libs
|
|
waitForTranslations(() => {
|
|
if (lang === "en-us") return;
|
|
|
|
$.fn.select2.amd.define("select2/i18n/de", [], () => {
|
|
return {
|
|
errorLoading: () => t("jquery.select2.error_oading"),
|
|
inputTooLong: err => tf("jquery.select2.input_too_long", err.input.length - err.maximum),
|
|
inputTooShort: err => tf("jquery.select2.input_too_short", err.minimum - err.input.length),
|
|
loadingMore: () => t("jquery.select2.loading_more"),
|
|
maximumSelected: err =>
|
|
tf(
|
|
err.maximum !== 1
|
|
? "jquery.select2.maximum_selected_n"
|
|
: "jquery.select2.maximum_selected",
|
|
err.maximum
|
|
),
|
|
noResults: () => t("jquery.select2.no_results"),
|
|
searching: () => t("jquery.select2.searching"),
|
|
removeAllItems: () => t("jquery.select2.remove_all_items"),
|
|
};
|
|
});
|
|
|
|
$.extend(true, $.fn.dataTable.defaults, {
|
|
language: {
|
|
decimal: t("jquery.datatable.decimal"),
|
|
thousands: t("jquery.datatable.thousands"),
|
|
search: t("jquery.datatable.search"),
|
|
lengthMenu: t("jquery.datatable.length_menu"),
|
|
info: t("jquery.datatable.info"),
|
|
infoEmpty: t("jquery.datatable.info_empty"),
|
|
infoFiltered: t("jquery.datatable.info_filtered"),
|
|
loadingRecords: t("jquery.datatable.loading_records"),
|
|
zeroRecords: t("jquery.datatable.zero_records"),
|
|
emptyTable: t("jquery.datatable.empty_table"),
|
|
processing: t("jquery.datatable.processing"),
|
|
paginate: {
|
|
first: t("jquery.datatable.first"),
|
|
previous: t("jquery.datatable.previous"),
|
|
next: t("jquery.datatable.next"),
|
|
last: t("jquery.datatable.last"),
|
|
},
|
|
},
|
|
});
|
|
});
|