Files
reactShop/src/i18n/index.js

221 lines
6.5 KiB
JavaScript

import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';
// Note: LanguageDetector not used - we have custom detector
// Only import German translations by default
import translationDE from './locales/de/index.js';
import legalAgbDE from './locales/de/legal-agb.js';
import legalDatenschutzDE from './locales/de/legal-datenschutz.js';
import legalImpressumDE from './locales/de/legal-impressum.js';
import legalWiderrufDE from './locales/de/legal-widerruf.js';
import legalBatterieDE from './locales/de/legal-batterie.js';
// Language loading cache to prevent duplicate loads
const languageCache = new Set(['de']);
const loadingPromises = new Map();
// Lazy loading function for languages
const loadLanguage = async (language) => {
if (languageCache.has(language)) {
return; // Already loaded
}
if (loadingPromises.has(language)) {
return loadingPromises.get(language); // Already loading
}
const loadingPromise = (async () => {
try {
console.log(`🌍 Lazy loading language: ${language}`);
// Dynamic imports for lazy loading
const [
translation,
legalAgb,
legalDatenschutz,
legalImpressum,
legalWiderruf,
legalBatterie
] = await Promise.all([
import(`./locales/${language}/index.js`),
import(`./locales/${language}/legal-agb.js`),
import(`./locales/${language}/legal-datenschutz.js`),
import(`./locales/${language}/legal-impressum.js`),
import(`./locales/${language}/legal-widerruf.js`),
import(`./locales/${language}/legal-batterie.js`)
]);
// Add the loaded resources to i18n
i18n.addResourceBundle(language, 'translation', translation.default);
i18n.addResourceBundle(language, 'legal-agb', legalAgb.default);
i18n.addResourceBundle(language, 'legal-datenschutz', legalDatenschutz.default);
i18n.addResourceBundle(language, 'legal-impressum', legalImpressum.default);
i18n.addResourceBundle(language, 'legal-widerruf', legalWiderruf.default);
i18n.addResourceBundle(language, 'legal-batterie', legalBatterie.default);
languageCache.add(language);
console.log(`✅ Language ${language} loaded successfully`);
} catch (error) {
console.error(`❌ Failed to load language ${language}:`, error);
throw error;
} finally {
loadingPromises.delete(language);
}
})();
loadingPromises.set(language, loadingPromise);
return loadingPromise;
};
// Custom language detector that prioritizes session storage and defaults to German
const customDetector = {
name: 'customDetector',
lookup() {
// Only try storage in browser environment
if (typeof window === 'undefined') {
return 'de';
}
// 1. Check session storage first
try {
if (typeof sessionStorage !== 'undefined') {
const sessionLang = sessionStorage.getItem('i18nextLng');
if (sessionLang && sessionLang !== 'de') {
return sessionLang;
}
}
} catch {
// Session storage not available
}
// 2. Check localStorage
try {
if (typeof localStorage !== 'undefined') {
const localLang = localStorage.getItem('i18nextLng');
if (localLang && localLang !== 'de') {
return localLang;
}
}
} catch {
// LocalStorage not available
}
// 3. Always default to German (don't detect browser language)
return 'de';
},
cacheUserLanguage(lng) {
// Only cache in browser environment
if (typeof window === 'undefined') {
return;
}
try {
if (typeof sessionStorage !== 'undefined') {
sessionStorage.setItem('i18nextLng', lng);
}
if (typeof localStorage !== 'undefined') {
localStorage.setItem('i18nextLng', lng);
}
} catch {
// Storage not available
}
}
};
// Initialize i18n with only German resources
const resources = {
de: {
translation: translationDE,
'legal-agb': legalAgbDE,
'legal-datenschutz': legalDatenschutzDE,
'legal-impressum': legalImpressumDE,
'legal-widerruf': legalWiderrufDE,
'legal-batterie': legalBatterieDE
}
};
i18n
.use({
type: 'languageDetector',
async: false,
detect: customDetector.lookup,
init() {},
cacheUserLanguage: customDetector.cacheUserLanguage
})
.use(initReactI18next)
.init({
resources,
lng: 'de', // Force German as default
fallbackLng: 'de',
debug: process.env.NODE_ENV === 'development',
// Disable automatic language detection from browser
detection: {
order: ['customDetector'],
caches: ['localStorage', 'sessionStorage']
},
interpolation: {
escapeValue: false // React already escapes values
},
// Namespace configuration
defaultNS: 'translation',
// React-specific options
react: {
useSuspense: false // Disable suspense for class components compatibility
},
// Load missing keys as fallback
saveMissing: process.env.NODE_ENV === 'development'
});
// Override changeLanguage to load languages on demand
const originalChangeLanguage = i18n.changeLanguage.bind(i18n);
i18n.changeLanguage = async (language) => {
if (language !== 'de' && !languageCache.has(language)) {
try {
await loadLanguage(language);
} catch {
console.error(`Failed to load language ${language}, falling back to German`);
language = 'de';
}
}
return originalChangeLanguage(language);
};
// Check session storage on initialization and load language if needed
const initializeLanguage = async () => {
// Only run in browser environment
if (typeof window === 'undefined' || typeof sessionStorage === 'undefined') {
return;
}
try {
const sessionLang = sessionStorage.getItem('i18nextLng');
if (sessionLang && sessionLang !== 'de' && !languageCache.has(sessionLang)) {
console.log(`🔄 Restoring session language: ${sessionLang}`);
await loadLanguage(sessionLang);
await i18n.changeLanguage(sessionLang);
}
} catch {
console.warn('Failed to restore session language');
}
};
// Initialize language on DOM ready (browser only)
if (typeof window !== 'undefined' && typeof document !== 'undefined') {
if (document.readyState === 'loading') {
document.addEventListener('DOMContentLoaded', initializeLanguage);
} else {
initializeLanguage();
}
}
export default i18n;
export { loadLanguage };
// Re-export withI18n and other utilities for compatibility
export { withI18n, withTranslation, withLanguage, LanguageContext, LanguageProvider } from './withTranslation.js';