Seperate language translation in diffrent file and sort files
This commit is contained in:
@@ -0,0 +1,261 @@
|
||||
// handels the language translation
|
||||
|
||||
(function attachAppLanguage(window, document) {
|
||||
const DEFAULT_LANGUAGE = "de";
|
||||
const DEFAULT_STORAGE_KEY = "preferredLanguage";
|
||||
const DEFAULT_SUPPORTED_LANGUAGES = ["de", "en"];
|
||||
|
||||
function resolveSupportedLanguages(supportedLanguages = DEFAULT_SUPPORTED_LANGUAGES) {
|
||||
const normalizedLanguages = Array.isArray(supportedLanguages)
|
||||
? supportedLanguages
|
||||
.map((language) => String(language || "").trim().slice(0, 2).toLowerCase())
|
||||
.filter(Boolean)
|
||||
: [];
|
||||
|
||||
return normalizedLanguages.length > 0 ? normalizedLanguages : DEFAULT_SUPPORTED_LANGUAGES.slice();
|
||||
}
|
||||
|
||||
function normalizeLanguage(
|
||||
language,
|
||||
{
|
||||
supportedLanguages = DEFAULT_SUPPORTED_LANGUAGES,
|
||||
defaultLanguage = DEFAULT_LANGUAGE
|
||||
} = {}
|
||||
) {
|
||||
const normalizedSupportedLanguages = resolveSupportedLanguages(supportedLanguages);
|
||||
const normalizedDefaultLanguage = normalizedSupportedLanguages.includes(defaultLanguage)
|
||||
? defaultLanguage
|
||||
: normalizedSupportedLanguages[0] || DEFAULT_LANGUAGE;
|
||||
const shortLanguage = String(language || "").trim().slice(0, 2).toLowerCase();
|
||||
|
||||
return normalizedSupportedLanguages.includes(shortLanguage) ? shortLanguage : normalizedDefaultLanguage;
|
||||
}
|
||||
|
||||
function getStoredLanguage({ storageKey = DEFAULT_STORAGE_KEY } = {}) {
|
||||
try {
|
||||
return window.localStorage.getItem(storageKey);
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
function storeLanguage(language, { storageKey = DEFAULT_STORAGE_KEY } = {}) {
|
||||
try {
|
||||
window.localStorage.setItem(storageKey, language);
|
||||
} catch (error) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
function detectBrowserLanguage(options = {}) {
|
||||
return normalizeLanguage(navigator.language || navigator.userLanguage || options.defaultLanguage, options);
|
||||
}
|
||||
|
||||
function getPreferredLanguage(
|
||||
{
|
||||
supportedLanguages = DEFAULT_SUPPORTED_LANGUAGES,
|
||||
defaultLanguage = DEFAULT_LANGUAGE,
|
||||
storageKey = DEFAULT_STORAGE_KEY,
|
||||
fallbackLanguage = defaultLanguage
|
||||
} = {}
|
||||
) {
|
||||
return normalizeLanguage(
|
||||
getStoredLanguage({ storageKey }) || detectBrowserLanguage({ supportedLanguages, defaultLanguage }) || fallbackLanguage,
|
||||
{
|
||||
supportedLanguages,
|
||||
defaultLanguage: fallbackLanguage
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
function getNextLanguage(language, supportedLanguages = DEFAULT_SUPPORTED_LANGUAGES) {
|
||||
const normalizedSupportedLanguages = resolveSupportedLanguages(supportedLanguages);
|
||||
const currentLanguage = normalizeLanguage(language, {
|
||||
supportedLanguages: normalizedSupportedLanguages,
|
||||
defaultLanguage: normalizedSupportedLanguages[0]
|
||||
});
|
||||
const currentIndex = normalizedSupportedLanguages.indexOf(currentLanguage);
|
||||
|
||||
if (currentIndex === -1 || normalizedSupportedLanguages.length < 2) {
|
||||
return currentLanguage;
|
||||
}
|
||||
|
||||
return normalizedSupportedLanguages[(currentIndex + 1) % normalizedSupportedLanguages.length];
|
||||
}
|
||||
|
||||
function setDocumentLanguage(language) {
|
||||
if (document.documentElement) {
|
||||
document.documentElement.lang = language;
|
||||
}
|
||||
|
||||
if (document.body) {
|
||||
document.body.dataset.language = language;
|
||||
}
|
||||
}
|
||||
|
||||
function applyTextTranslations({
|
||||
translate,
|
||||
selector = "[data-i18n]",
|
||||
allowHtml = () => false
|
||||
} = {}) {
|
||||
if (typeof translate !== "function") {
|
||||
return;
|
||||
}
|
||||
|
||||
document.querySelectorAll(selector).forEach((element) => {
|
||||
const key = element.dataset.i18n;
|
||||
const translatedText = translate(key, element);
|
||||
|
||||
if (translatedText === undefined || translatedText === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (allowHtml(element, translatedText, key)) {
|
||||
element.innerHTML = String(translatedText);
|
||||
return;
|
||||
}
|
||||
|
||||
element.textContent = String(translatedText);
|
||||
});
|
||||
}
|
||||
|
||||
function applyAttributeTranslations({
|
||||
translate,
|
||||
mappings = []
|
||||
} = {}) {
|
||||
if (typeof translate !== "function") {
|
||||
return;
|
||||
}
|
||||
|
||||
mappings.forEach(({ selector, datasetKey, attribute }) => {
|
||||
document.querySelectorAll(selector).forEach((element) => {
|
||||
const key = element.dataset[datasetKey];
|
||||
const translatedText = translate(key, element, attribute);
|
||||
|
||||
if (translatedText === undefined || translatedText === null) {
|
||||
return;
|
||||
}
|
||||
|
||||
element.setAttribute(attribute, String(translatedText));
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
function applyTranslations({
|
||||
translate,
|
||||
selector = "[data-i18n]",
|
||||
allowHtml,
|
||||
attributeMappings = []
|
||||
} = {}) {
|
||||
applyTextTranslations({ translate, selector, allowHtml });
|
||||
applyAttributeTranslations({ translate, mappings: attributeMappings });
|
||||
}
|
||||
|
||||
function updateLanguageSwitch(
|
||||
button,
|
||||
{
|
||||
language,
|
||||
label = String(language || "").toUpperCase(),
|
||||
ariaLabel,
|
||||
title
|
||||
} = {}
|
||||
) {
|
||||
if (!button) {
|
||||
return;
|
||||
}
|
||||
|
||||
button.textContent = label;
|
||||
|
||||
if (ariaLabel !== undefined) {
|
||||
button.setAttribute("aria-label", ariaLabel);
|
||||
}
|
||||
|
||||
if (title !== undefined) {
|
||||
button.title = title;
|
||||
}
|
||||
}
|
||||
|
||||
function createController({
|
||||
button = document.getElementById("langSwitch"),
|
||||
defaultLanguage = DEFAULT_LANGUAGE,
|
||||
supportedLanguages = DEFAULT_SUPPORTED_LANGUAGES,
|
||||
storageKey = DEFAULT_STORAGE_KEY,
|
||||
onApply = () => { }
|
||||
} = {}) {
|
||||
const options = {
|
||||
defaultLanguage,
|
||||
supportedLanguages,
|
||||
storageKey
|
||||
};
|
||||
|
||||
let currentLanguage = normalizeLanguage(defaultLanguage, options);
|
||||
|
||||
function apply(language, source = "apply") {
|
||||
currentLanguage = normalizeLanguage(language, options);
|
||||
setDocumentLanguage(currentLanguage);
|
||||
|
||||
onApply(currentLanguage, {
|
||||
source,
|
||||
button,
|
||||
applyTranslations,
|
||||
updateLanguageSwitch: (switchOptions = {}) => updateLanguageSwitch(button, {
|
||||
language: currentLanguage,
|
||||
...switchOptions
|
||||
}),
|
||||
getNextLanguage: () => getNextLanguage(currentLanguage, supportedLanguages),
|
||||
normalizeLanguage: (value) => normalizeLanguage(value, options)
|
||||
});
|
||||
|
||||
storeLanguage(currentLanguage, { storageKey });
|
||||
return currentLanguage;
|
||||
}
|
||||
|
||||
function toggle() {
|
||||
return apply(getNextLanguage(currentLanguage, supportedLanguages), "toggle");
|
||||
}
|
||||
|
||||
function init(initialLanguage = getPreferredLanguage({
|
||||
supportedLanguages,
|
||||
defaultLanguage,
|
||||
storageKey,
|
||||
fallbackLanguage: defaultLanguage
|
||||
})) {
|
||||
if (button) {
|
||||
button.addEventListener("click", toggle);
|
||||
}
|
||||
|
||||
return apply(initialLanguage, "init");
|
||||
}
|
||||
|
||||
return {
|
||||
apply,
|
||||
getCurrentLanguage: () => currentLanguage,
|
||||
getPreferredLanguage: (fallbackLanguage = defaultLanguage) => getPreferredLanguage({
|
||||
supportedLanguages,
|
||||
defaultLanguage,
|
||||
storageKey,
|
||||
fallbackLanguage
|
||||
}),
|
||||
init,
|
||||
toggle
|
||||
};
|
||||
}
|
||||
|
||||
window.AppLanguage = {
|
||||
DEFAULT_LANGUAGE,
|
||||
DEFAULT_STORAGE_KEY,
|
||||
DEFAULT_SUPPORTED_LANGUAGES: DEFAULT_SUPPORTED_LANGUAGES.slice(),
|
||||
applyAttributeTranslations,
|
||||
applyTextTranslations,
|
||||
applyTranslations,
|
||||
createController,
|
||||
detectBrowserLanguage,
|
||||
getNextLanguage,
|
||||
getPreferredLanguage,
|
||||
getStoredLanguage,
|
||||
normalizeLanguage,
|
||||
setDocumentLanguage,
|
||||
storeLanguage,
|
||||
updateLanguageSwitch
|
||||
};
|
||||
})(window, document);
|
||||
Reference in New Issue
Block a user