160 lines
5.4 KiB
JavaScript
160 lines
5.4 KiB
JavaScript
(function () {
|
|
var STORAGE_KEY = 'hyapp_h5_lang';
|
|
var DEFAULT_LANG = 'en';
|
|
var SUPPORTED = ['en', 'ar', 'tr', 'es'];
|
|
var messages = {};
|
|
var currentLang = '';
|
|
|
|
function queryLang() {
|
|
return new URLSearchParams(window.location.search).get('lang') || '';
|
|
}
|
|
|
|
function normalizeLang(value) {
|
|
var lang = String(value || '')
|
|
.trim()
|
|
.toLowerCase()
|
|
.replace('_', '-');
|
|
if (!lang) return '';
|
|
if (lang.indexOf('ar') === 0) return 'ar';
|
|
if (lang.indexOf('tr') === 0) return 'tr';
|
|
if (lang.indexOf('es') === 0) return 'es';
|
|
return SUPPORTED.indexOf(lang) >= 0 ? lang : '';
|
|
}
|
|
|
|
function resolveLang() {
|
|
return (
|
|
normalizeLang(queryLang()) ||
|
|
normalizeLang(window.localStorage.getItem(STORAGE_KEY)) ||
|
|
normalizeLang(window.navigator.language) ||
|
|
DEFAULT_LANG
|
|
);
|
|
}
|
|
|
|
function load(lang) {
|
|
var normalized = normalizeLang(lang) || DEFAULT_LANG;
|
|
return window
|
|
.fetch('../common/locales/' + normalized + '.json', {
|
|
cache: 'no-store',
|
|
})
|
|
.then(function (response) {
|
|
if (!response.ok) throw new Error('locale_not_found');
|
|
return response.json();
|
|
})
|
|
.then(function (json) {
|
|
messages = json || {};
|
|
currentLang = normalized;
|
|
window.localStorage.setItem(STORAGE_KEY, currentLang);
|
|
apply();
|
|
return messages;
|
|
})
|
|
.catch(function () {
|
|
if (normalized === DEFAULT_LANG) {
|
|
messages = {};
|
|
currentLang = DEFAULT_LANG;
|
|
apply();
|
|
return messages;
|
|
}
|
|
return load(DEFAULT_LANG);
|
|
});
|
|
}
|
|
|
|
function t(key, fallback) {
|
|
return Object.prototype.hasOwnProperty.call(messages, key)
|
|
? messages[key]
|
|
: fallback || key;
|
|
}
|
|
|
|
function apply(root) {
|
|
var scope = root || document;
|
|
document.documentElement.lang = currentLang || DEFAULT_LANG;
|
|
document.documentElement.dir = currentLang === 'ar' ? 'rtl' : 'ltr';
|
|
scope.querySelectorAll('[data-i18n]').forEach(function (node) {
|
|
node.textContent = t(
|
|
node.getAttribute('data-i18n'),
|
|
node.textContent
|
|
);
|
|
});
|
|
scope
|
|
.querySelectorAll('[data-i18n-placeholder]')
|
|
.forEach(function (node) {
|
|
node.setAttribute(
|
|
'placeholder',
|
|
t(
|
|
node.getAttribute('data-i18n-placeholder'),
|
|
node.getAttribute('placeholder') || ''
|
|
)
|
|
);
|
|
});
|
|
scope.querySelectorAll('[data-i18n-aria]').forEach(function (node) {
|
|
node.setAttribute(
|
|
'aria-label',
|
|
t(
|
|
node.getAttribute('data-i18n-aria'),
|
|
node.getAttribute('aria-label') || ''
|
|
)
|
|
);
|
|
});
|
|
scope.querySelectorAll('[data-lang-option]').forEach(function (node) {
|
|
node.classList.toggle(
|
|
'is-active',
|
|
node.getAttribute('data-lang-option') === currentLang
|
|
);
|
|
});
|
|
scope.querySelectorAll('[data-current-lang]').forEach(function (node) {
|
|
node.textContent = (currentLang || DEFAULT_LANG).toUpperCase();
|
|
});
|
|
window.dispatchEvent(
|
|
new CustomEvent('hyapp:i18n-ready', {
|
|
detail: { lang: currentLang, messages: messages },
|
|
})
|
|
);
|
|
}
|
|
|
|
function initLanguageMenu() {
|
|
document.addEventListener('click', function (event) {
|
|
var toggle = event.target.closest('[data-language-toggle]');
|
|
var menu = document.querySelector('[data-language-menu]');
|
|
if (toggle && menu) {
|
|
var expanded = toggle.getAttribute('aria-expanded') === 'true';
|
|
toggle.setAttribute(
|
|
'aria-expanded',
|
|
expanded ? 'false' : 'true'
|
|
);
|
|
menu.hidden = expanded;
|
|
return;
|
|
}
|
|
var option = event.target.closest('[data-lang-option]');
|
|
if (option) {
|
|
if (menu) menu.hidden = true;
|
|
var button = document.querySelector('[data-language-toggle]');
|
|
if (button) button.setAttribute('aria-expanded', 'false');
|
|
load(option.getAttribute('data-lang-option'));
|
|
return;
|
|
}
|
|
if (menu && !event.target.closest('.language-switcher')) {
|
|
menu.hidden = true;
|
|
var languageButton = document.querySelector(
|
|
'[data-language-toggle]'
|
|
);
|
|
if (languageButton)
|
|
languageButton.setAttribute('aria-expanded', 'false');
|
|
}
|
|
});
|
|
}
|
|
|
|
window.HyAppI18n = {
|
|
load: load,
|
|
apply: apply,
|
|
t: t,
|
|
lang: function () {
|
|
return currentLang || DEFAULT_LANG;
|
|
},
|
|
supported: SUPPORTED.slice(),
|
|
};
|
|
|
|
document.addEventListener('DOMContentLoaded', function () {
|
|
initLanguageMenu();
|
|
load(resolveLang());
|
|
});
|
|
})();
|