Feat: intégration multilingue FR/EN (i18n)
All checks were successful
Deploy / Deploy to Production (push) Successful in 18s
All checks were successful
Deploy / Deploy to Production (push) Successful in 18s
- Ajout de src/i18n/index.js : dictionnaire centralisé + fonction t(key, vars) - Ajout de LanguageSwitcher.svelte : toggle FR/EN avec persistance localStorage - Router : normalizePath strip /en/, apiPrefix() pour les fetches, détection langue (URL > localStorage > navigator) - Tous les composants (Header, Menu, Footer, Article, Blog, Play) migrent vers t() depuis @i18n - Blog : navigation interne (fetch, history, getSlugFromUrl) locale-aware Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
parent
3bd410cc02
commit
517143fe60
11 changed files with 162 additions and 59 deletions
|
|
@ -5,7 +5,12 @@ import { locale } from "@state/locale.svelte";
|
|||
let siteInitialized = false;
|
||||
|
||||
function normalizePath(path) {
|
||||
return path === "/" ? "/home" : path;
|
||||
const stripped = path.replace(/^\/en(\/|$)/, '$1') || '/';
|
||||
return stripped === '/' ? '/home' : stripped;
|
||||
}
|
||||
|
||||
function apiPrefix() {
|
||||
return locale.current === 'en' ? '/en' : '';
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
@ -47,8 +52,7 @@ async function loadSlide(path) {
|
|||
}
|
||||
|
||||
try {
|
||||
// Fetch the actual slide path (parent), not the sub-page
|
||||
const response = await fetch(`${slidePath}.json`);
|
||||
const response = await fetch(`${apiPrefix()}${slidePath}.json`);
|
||||
if (!response.ok) throw new Error(`HTTP ${response.status}`);
|
||||
const data = await response.json();
|
||||
|
||||
|
|
@ -76,7 +80,10 @@ export function slideTo(path, { skipHistory = false } = {}) {
|
|||
path = normalizePath(path);
|
||||
|
||||
if (!skipHistory) {
|
||||
history.pushState({}, "", path === "/home" ? "/" : path);
|
||||
const historyPath = locale.current === 'en'
|
||||
? (path === '/home' ? '/en' : `/en${path}`)
|
||||
: (path === '/home' ? '/' : path);
|
||||
history.pushState({}, '', historyPath);
|
||||
}
|
||||
|
||||
const idx = findSlideIndex(path);
|
||||
|
|
@ -94,6 +101,22 @@ export function slideTo(path, { skipHistory = false } = {}) {
|
|||
}
|
||||
|
||||
export async function initRouter() {
|
||||
// Language detection: URL prefix > localStorage > navigator
|
||||
const hasEnPrefix = window.location.pathname.startsWith('/en');
|
||||
if (hasEnPrefix) {
|
||||
locale.setLanguage('en');
|
||||
localStorage.setItem('wg_lang', 'en');
|
||||
} else if (!localStorage.getItem('wg_lang')) {
|
||||
const navLang = navigator.language || navigator.languages?.[0] || 'fr';
|
||||
if (navLang.startsWith('en')) {
|
||||
window.location.replace('/en' + window.location.pathname);
|
||||
return;
|
||||
}
|
||||
} else if (localStorage.getItem('wg_lang') === 'en') {
|
||||
window.location.replace('/en' + window.location.pathname);
|
||||
return;
|
||||
}
|
||||
|
||||
const initialPath = normalizePath(window.location.pathname);
|
||||
|
||||
await loadSlide(initialPath);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue