**Motivations:** - Allow users to set their preferred language (fr/en) in the settings page - Load language preference from localStorage at startup to configure the application locale **Root causes:** - Language preference was only available in the header via LanguageSelector component - Language preference was stored in IndexedDB instead of localStorage - No centralized language settings management in the settings page **Correctifs:** - Created LanguageSettingsManager component for settings page - Migrated language storage from IndexedDB to localStorage for consistency - Updated _app.tsx to load locale from localStorage synchronously at startup - Updated useI18n hook to use localStorage instead of IndexedDB - Updated LanguageSelector component to use localStorage instead of IndexedDB **Evolutions:** - Added language preference section in settings page (displayed first) - Language preference is now loaded at application startup from localStorage - Added translations for language settings (settings.language.*) **Pages affectées:** - components/LanguageSettingsManager.tsx (new) - pages/settings.tsx - pages/_app.tsx - hooks/useI18n.ts - components/LanguageSelector.tsx - locales/fr.txt - locales/en.txt
53 lines
1.7 KiB
TypeScript
53 lines
1.7 KiB
TypeScript
import { useEffect, useState } from 'react'
|
|
import { setLocale, getLocale, loadTranslations, t, type Locale } from '@/lib/i18n'
|
|
|
|
export function useI18n(locale: Locale = 'fr'): {
|
|
loaded: boolean
|
|
locale: Locale
|
|
t: (key: string, params?: Record<string, string | number>) => string
|
|
} {
|
|
const [loaded, setLoaded] = useState(false)
|
|
const [currentLocale, setCurrentLocale] = useState<Locale>(getLocale())
|
|
|
|
useEffect(() => {
|
|
const load = async (): Promise<void> => {
|
|
try {
|
|
// Get saved locale from localStorage or use provided locale
|
|
let savedLocale: Locale | null = null
|
|
try {
|
|
if (typeof window !== 'undefined') {
|
|
savedLocale = localStorage.getItem('zapwall-locale') as Locale | null
|
|
}
|
|
} catch {
|
|
// Fallback to provided locale
|
|
}
|
|
const initialLocale = savedLocale && (savedLocale === 'fr' || savedLocale === 'en') ? savedLocale : locale
|
|
|
|
// Load translations from files in public directory
|
|
const frResponse = await fetch('/locales/fr.txt')
|
|
const enResponse = await fetch('/locales/en.txt')
|
|
|
|
if (frResponse.ok) {
|
|
const frText = await frResponse.text()
|
|
await loadTranslations('fr', frText)
|
|
}
|
|
|
|
if (enResponse.ok) {
|
|
const enText = await enResponse.text()
|
|
await loadTranslations('en', enText)
|
|
}
|
|
|
|
setLocale(initialLocale)
|
|
setCurrentLocale(initialLocale)
|
|
setLoaded(true)
|
|
} catch (e) {
|
|
console.error('Error loading translations:', e)
|
|
setLoaded(true) // Continue even if translations fail to load
|
|
}
|
|
}
|
|
void load()
|
|
}, [locale])
|
|
|
|
return { loaded, locale: currentLocale, t }
|
|
}
|