feat: Building the app in it's first version

This commit is contained in:
gauvainboiche
2026-09-15 23:12:57 +02:00
parent 34792e2782
commit 64a3d9b556
42 changed files with 2699 additions and 0 deletions
+93
View File
@@ -0,0 +1,93 @@
'use strict';
const I18N = (() => {
const SUPPORTED_LANGS = ['fr', 'en'];
const DEFAULT_LANG = 'fr';
const STORAGE_KEY = 'republican-calendar-lang';
let currentLang = DEFAULT_LANG;
let common = {};
let months = {};
let about = {};
const changeListeners = [];
function detectInitialLang() {
try {
const stored = localStorage.getItem(STORAGE_KEY);
if (stored && SUPPORTED_LANGS.includes(stored)) return stored;
} catch (error) {
// localStorage unavailable (private mode, etc.): fall through to default.
}
return DEFAULT_LANG;
}
function getByPath(object, path) {
return path.split('.').reduce((node, key) => (node && node[key] !== undefined ? node[key] : undefined), object);
}
function t(path, fallback) {
const value = getByPath(common, path);
return value !== undefined ? value : (fallback !== undefined ? fallback : path);
}
function applyStaticTranslations() {
document.documentElement.lang = currentLang;
document.querySelectorAll('[data-i18n]').forEach((element) => {
const key = element.getAttribute('data-i18n');
const value = getByPath(common, key);
if (value !== undefined) {
element.textContent = value;
}
});
}
async function fetchJson(url) {
const response = await fetch(url, { cache: 'no-store' });
if (!response.ok) {
throw new Error(`Failed to load ${url}: ${response.status}`);
}
return response.json();
}
async function load(lang) {
const targetLang = SUPPORTED_LANGS.includes(lang) ? lang : DEFAULT_LANG;
const [commonData, monthsData, aboutData] = await Promise.all([
fetchJson(`locales/${targetLang}/common.json`),
fetchJson(`locales/${targetLang}/months.json`),
fetchJson(`locales/${targetLang}/about.json`),
]);
currentLang = targetLang;
common = commonData;
months = monthsData;
about = aboutData;
applyStaticTranslations();
changeListeners.forEach((listener) => listener(currentLang));
}
async function setLang(lang) {
if (!SUPPORTED_LANGS.includes(lang) || lang === currentLang) return;
try {
localStorage.setItem(STORAGE_KEY, lang);
} catch (error) {
// Ignore storage failures; language just won't persist across reloads.
}
await load(lang);
}
function onChange(listener) {
changeListeners.push(listener);
}
return {
SUPPORTED_LANGS,
get currentLang() { return currentLang; },
get common() { return common; },
get months() { return months; },
get about() { return about; },
detectInitialLang,
load,
setLang,
onChange,
t,
};
})();