83 lines
2.3 KiB
JavaScript
83 lines
2.3 KiB
JavaScript
import React, { createContext, useContext, useState, useCallback, useMemo } from 'react';
|
|
import en from './i18n/en.json';
|
|
import de from './i18n/de.json';
|
|
|
|
const translations = { en, de };
|
|
|
|
// Cookie helpers
|
|
function getCookie(name) {
|
|
const match = document.cookie.match(new RegExp('(^| )' + name + '=([^;]+)'));
|
|
return match ? match[2] : null;
|
|
}
|
|
|
|
function setCookie(name, value, days = 365) {
|
|
const expires = new Date(Date.now() + days * 864e5).toUTCString();
|
|
document.cookie = `${name}=${value}; expires=${expires}; path=/; SameSite=Lax`;
|
|
}
|
|
|
|
// Get initial language from cookie or browser preference
|
|
function getInitialLanguage() {
|
|
const cookieLang = getCookie('lang');
|
|
if (cookieLang && translations[cookieLang]) {
|
|
return cookieLang;
|
|
}
|
|
// Check browser preference
|
|
const browserLang = navigator.language?.slice(0, 2);
|
|
if (browserLang === 'de') return 'de';
|
|
return 'en';
|
|
}
|
|
|
|
const I18nContext = createContext(null);
|
|
|
|
export function I18nProvider({ children }) {
|
|
const [language, setLanguageState] = useState(getInitialLanguage);
|
|
|
|
const setLanguage = useCallback((lang) => {
|
|
if (translations[lang]) {
|
|
setLanguageState(lang);
|
|
setCookie('lang', lang);
|
|
}
|
|
}, []);
|
|
|
|
// Translation function with nested key support (e.g., 'app.title')
|
|
const t = useCallback((key, params = {}) => {
|
|
const keys = key.split('.');
|
|
let value = translations[language];
|
|
|
|
for (const k of keys) {
|
|
if (value && typeof value === 'object') {
|
|
value = value[k];
|
|
} else {
|
|
return key; // fallback to key if not found
|
|
}
|
|
}
|
|
|
|
if (typeof value !== 'string') return key;
|
|
|
|
// Replace {param} placeholders
|
|
return value.replace(/\{(\w+)\}/g, (_, param) =>
|
|
params[param] !== undefined ? params[param] : `{${param}}`
|
|
);
|
|
}, [language]);
|
|
|
|
const value = useMemo(() => ({
|
|
language,
|
|
setLanguage,
|
|
t
|
|
}), [language, setLanguage, t]);
|
|
|
|
return (
|
|
<I18nContext.Provider value={value}>
|
|
{children}
|
|
</I18nContext.Provider>
|
|
);
|
|
}
|
|
|
|
export function useI18n() {
|
|
const context = useContext(I18nContext);
|
|
if (!context) {
|
|
throw new Error('useI18n must be used within an I18nProvider');
|
|
}
|
|
return context;
|
|
}
|