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"),
},
},
});
});