web/public/res/locale.js
2025-03-25 22:46:50 +01:00

103 lines
No EOL
3.6 KiB
JavaScript

(() => {
const getLocale = () => {
const cacheLocale = localStorage.getItem('preferredLocale')
if (cacheLocale) return cacheLocale
localStorage.setItem('preferredLocale', navigator.language);
return locale
}
const setPreferredLocale = (locale) => {
localStorage.setItem('preferredLocale', locale);
setLocale()
}
const getLocaleURL = (locale = getLocale()) => {
const lang = locale.split('-')[0];
return `/res/locale/${lang}.json`
}
const loadLocale = async (locale = getLocale()) => {
// check localStorage
const cacheDate = localStorage.getItem(`locale-${locale}`)
if (cacheDate) {
if (Date.now() - cacheDate < 1000 * 60 * 60 * 24) { // 1 day
return JSON.parse(localStorage.getItem(`locale-${locale}-data`))
}
}
try {
const response = await fetch(getLocaleURL(locale), { cache: 'no-store' })
if (response.ok) {
const data = await response.json()
localStorage.setItem(`locale-${locale}`, Date.now())
localStorage.setItem(`locale-${locale}-data`, JSON.stringify(data))
return data
}
} catch (error) {
console.error(error)
if (cacheDate) { // if error then return cache even if expired
return JSON.parse(localStorage.getItem(`locale-${locale}-data`))
} else {
if (locale !== 'en') return await loadLocale('en');
}
}
return {}
}
const setLocale = async (locale = getLocale()) => {
const data = await loadLocale(locale)
document.querySelectorAll('[data-i18n]').forEach(async (element) => {
try {
// main.intro.title => {main: {intro: {title: 'value'}}}
const keys = element.getAttribute('data-i18n').split('.');
console.log(keys)
let value = data;
keys.forEach((key) => value = value[key]);
console.log(value)
// if array then into ul list
if (Array.isArray(value)) {
element.innerHTML = ''
const ul = document.createElement('ul')
value.forEach((item) => {
const li = document.createElement('li')
li.innerHTML = item
ul.appendChild(li)
})
element.appendChild(ul)
} else {
element.innerHTML = value ?? '###';
}
} catch (error) {
console.error(error)
element.innerHTML = '###';
}
});
document.querySelectorAll('[data-i18n-show').forEach(el => el.removeAttribute('data-i18n-show'))
}
window.locale = {
setPreferredLocale,
getLocale,
getLocaleURL,
loadLocale,
setLocale,
expireLocale: () => {
localStorage.removeItem(`locale-${getLocale()}`)
localStorage.removeItem(`locale-${getLocale()}-data`)
setLocale()
}
}
window.locale.setLocale();
// expiry management
// check if locale is older than EXPIRY_TIME then fetch again
function checkExpiry() {
const cacheDate = localStorage.getItem(`locale-${getLocale()}`)
if (cacheDate) {
if (Date.now() - cacheDate > 1000 * 60 * 60 * 24) { // 1 day
window.locale.expireLocale()
}
}
}
setInterval(checkExpiry, 1000 * 60 * 60); // 1 hour
checkExpiry()
})()