81 lines
2.6 KiB
JavaScript
81 lines
2.6 KiB
JavaScript
/** Foodlinkk i18n — edit /static/i18n/nl.json and en.json to translate. */
|
|
window.I18n = (function () {
|
|
var locale = 'nl';
|
|
var strings = {};
|
|
|
|
function t(key, fallback) {
|
|
if (!key) return fallback || '';
|
|
var parts = String(key).split('.');
|
|
var o = strings;
|
|
for (var i = 0; i < parts.length; i++) {
|
|
if (o == null || typeof o !== 'object') return fallback != null ? fallback : key;
|
|
o = o[parts[i]];
|
|
}
|
|
return typeof o === 'string' ? o : (fallback != null ? fallback : key);
|
|
}
|
|
|
|
function applyDom() {
|
|
document.querySelectorAll('[data-i18n]').forEach(function (el) {
|
|
var k = el.getAttribute('data-i18n');
|
|
if (k) el.textContent = t(k);
|
|
});
|
|
document.querySelectorAll('[data-i18n-placeholder]').forEach(function (el) {
|
|
var k = el.getAttribute('data-i18n-placeholder');
|
|
if (k) el.placeholder = t(k);
|
|
});
|
|
document.querySelectorAll('[data-i18n-title]').forEach(function (el) {
|
|
var k = el.getAttribute('data-i18n-title');
|
|
if (k) el.title = t(k);
|
|
});
|
|
document.documentElement.lang = locale;
|
|
}
|
|
|
|
async function loadBundle(loc) {
|
|
var r = await fetch('/static/i18n/' + loc + '.json?v=2');
|
|
if (!r.ok) throw new Error('Locale ' + loc + ' not found');
|
|
strings = await r.json();
|
|
}
|
|
|
|
async function setLocale(loc, persist) {
|
|
if (persist == null) persist = true;
|
|
locale = loc === 'en' ? 'en' : 'nl';
|
|
try {
|
|
await loadBundle(locale);
|
|
} catch (e) {
|
|
if (locale !== 'nl') {
|
|
locale = 'nl';
|
|
await loadBundle('nl');
|
|
}
|
|
}
|
|
localStorage.setItem('foodlinkk_locale', locale);
|
|
applyDom();
|
|
window.dispatchEvent(new CustomEvent('foodlinkk:locale', { detail: { locale: locale } }));
|
|
if (persist) {
|
|
fetch('/api/preferences/ui', {
|
|
method: 'PUT',
|
|
headers: { 'Content-Type': 'application/json' },
|
|
body: JSON.stringify({ locale: locale }),
|
|
}).catch(function () {});
|
|
}
|
|
return locale;
|
|
}
|
|
|
|
async function init() {
|
|
var loc = localStorage.getItem('foodlinkk_locale') || 'nl';
|
|
try {
|
|
var prefs = await fetch('/api/preferences/ui').then(function (r) { return r.json(); });
|
|
if (prefs.locale) loc = prefs.locale;
|
|
} catch (e) { /* ignore */ }
|
|
await setLocale(loc, false);
|
|
}
|
|
|
|
return { t: t, init: init, setLocale: setLocale, locale: function () { return locale; }, applyDom: applyDom };
|
|
})();
|
|
|
|
document.addEventListener('alpine:init', function () {
|
|
if (!window.Alpine) return;
|
|
Alpine.magic('t', function () {
|
|
return function (key, fallback) { return window.I18n.t(key, fallback); };
|
|
});
|
|
});
|