feat: implement lazy loading for languages in i18n, enhance LanguageSwitcher to handle language changes asynchronously, and update available languages management
This commit is contained in:
@@ -24,10 +24,14 @@ class LanguageSwitcher extends Component {
|
||||
this.setState({ anchorEl: null });
|
||||
};
|
||||
|
||||
handleLanguageChange = (language) => {
|
||||
handleLanguageChange = async (language) => {
|
||||
const { languageContext } = this.props;
|
||||
if (languageContext) {
|
||||
languageContext.changeLanguage(language);
|
||||
try {
|
||||
await languageContext.changeLanguage(language);
|
||||
} catch (error) {
|
||||
console.error('Failed to change language:', error);
|
||||
}
|
||||
}
|
||||
this.handleClose();
|
||||
};
|
||||
@@ -126,8 +130,8 @@ class LanguageSwitcher extends Component {
|
||||
const { languageContext } = this.props;
|
||||
|
||||
if (anchorEl && !prevState.anchorEl && languageContext) {
|
||||
// Menu just opened, lazy load all flags
|
||||
languageContext.availableLanguages.forEach(lang => {
|
||||
// Menu just opened, lazy load flags for all languages (not just available ones)
|
||||
languageContext.allLanguages.forEach(lang => {
|
||||
if (!this.state.loadedFlags[lang]) {
|
||||
this.loadFlagComponent(lang);
|
||||
}
|
||||
@@ -197,7 +201,7 @@ class LanguageSwitcher extends Component {
|
||||
return null;
|
||||
}
|
||||
|
||||
const { currentLanguage, availableLanguages } = languageContext;
|
||||
const { currentLanguage, allLanguages } = languageContext;
|
||||
const open = Boolean(anchorEl);
|
||||
|
||||
return (
|
||||
@@ -237,29 +241,31 @@ class LanguageSwitcher extends Component {
|
||||
horizontal: 'right',
|
||||
}}
|
||||
>
|
||||
{availableLanguages.map((language) => (
|
||||
<MenuItem
|
||||
key={language}
|
||||
onClick={() => this.handleLanguageChange(language)}
|
||||
selected={language === currentLanguage}
|
||||
sx={{
|
||||
minWidth: 160,
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
gap: 2
|
||||
}}
|
||||
>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
||||
{this.getLanguageFlag(language)}
|
||||
<Typography variant="body2">
|
||||
{this.getLanguageName(language)}
|
||||
{allLanguages.map((language) => {
|
||||
return (
|
||||
<MenuItem
|
||||
key={language}
|
||||
onClick={() => this.handleLanguageChange(language)}
|
||||
selected={language === currentLanguage}
|
||||
sx={{
|
||||
minWidth: 160,
|
||||
display: 'flex',
|
||||
justifyContent: 'space-between',
|
||||
gap: 2
|
||||
}}
|
||||
>
|
||||
<Box sx={{ display: 'flex', alignItems: 'center', gap: 1 }}>
|
||||
{this.getLanguageFlag(language)}
|
||||
<Typography variant="body2">
|
||||
{this.getLanguageName(language)}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Typography variant="caption" color="text.secondary" sx={{ ml: 'auto' }}>
|
||||
{this.getLanguageLabel(language)}
|
||||
</Typography>
|
||||
</Box>
|
||||
<Typography variant="caption" color="text.secondary" sx={{ ml: 'auto' }}>
|
||||
{this.getLanguageLabel(language)}
|
||||
</Typography>
|
||||
</MenuItem>
|
||||
))}
|
||||
</MenuItem>
|
||||
);
|
||||
})}
|
||||
</Menu>
|
||||
</Box>
|
||||
);
|
||||
|
||||
@@ -1,178 +1,128 @@
|
||||
import i18n from 'i18next';
|
||||
import { initReactI18next } from 'react-i18next';
|
||||
import LanguageDetector from 'i18next-browser-languagedetector';
|
||||
// Note: LanguageDetector not used - we have custom detector
|
||||
|
||||
// Import all translation files
|
||||
// Only import German translations by default
|
||||
import translationDE from './locales/de/index.js';
|
||||
import translationEN from './locales/en/index.js';
|
||||
import translationAR from './locales/ar/translation.js';
|
||||
import translationBG from './locales/bg/translation.js';
|
||||
import translationCS from './locales/cs/translation.js';
|
||||
import translationEL from './locales/el/translation.js';
|
||||
import translationES from './locales/es/translation.js';
|
||||
import translationFR from './locales/fr/translation.js';
|
||||
import translationHR from './locales/hr/translation.js';
|
||||
import translationHU from './locales/hu/translation.js';
|
||||
import translationIT from './locales/it/translation.js';
|
||||
import translationPL from './locales/pl/translation.js';
|
||||
import translationRO from './locales/ro/translation.js';
|
||||
import translationRU from './locales/ru/translation.js';
|
||||
import translationSK from './locales/sk/translation.js';
|
||||
import translationSL from './locales/sl/translation.js';
|
||||
import translationSR from './locales/sr/translation.js';
|
||||
import translationSV from './locales/sv/translation.js';
|
||||
import translationTR from './locales/tr/translation.js';
|
||||
import translationUK from './locales/uk/translation.js';
|
||||
import translationZH from './locales/zh/translation.js';
|
||||
|
||||
// Import legal translations for all languages
|
||||
// German
|
||||
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';
|
||||
|
||||
// English
|
||||
import legalAgbEN from './locales/en/legal-agb.js';
|
||||
import legalDatenschutzEN from './locales/en/legal-datenschutz.js';
|
||||
import legalImpressumEN from './locales/en/legal-impressum.js';
|
||||
import legalWiderrufEN from './locales/en/legal-widerruf.js';
|
||||
import legalBatterieEN from './locales/en/legal-batterie.js';
|
||||
// Language loading cache to prevent duplicate loads
|
||||
const languageCache = new Set(['de']);
|
||||
const loadingPromises = new Map();
|
||||
|
||||
// Arabic
|
||||
import legalAgbAR from './locales/ar/legal-agb.js';
|
||||
import legalDatenschutzAR from './locales/ar/legal-datenschutz.js';
|
||||
import legalImpressumAR from './locales/ar/legal-impressum.js';
|
||||
import legalWiderrufAR from './locales/ar/legal-widerruf.js';
|
||||
import legalBatterieAR from './locales/ar/legal-batterie.js';
|
||||
// Lazy loading function for languages
|
||||
const loadLanguage = async (language) => {
|
||||
if (languageCache.has(language)) {
|
||||
return; // Already loaded
|
||||
}
|
||||
|
||||
// Bulgarian
|
||||
import legalAgbBG from './locales/bg/legal-agb.js';
|
||||
import legalDatenschutzBG from './locales/bg/legal-datenschutz.js';
|
||||
import legalImpressumBG from './locales/bg/legal-impressum.js';
|
||||
import legalWiderrufBG from './locales/bg/legal-widerruf.js';
|
||||
import legalBatterieBG from './locales/bg/legal-batterie.js';
|
||||
if (loadingPromises.has(language)) {
|
||||
return loadingPromises.get(language); // Already loading
|
||||
}
|
||||
|
||||
// Czech
|
||||
import legalAgbCS from './locales/cs/legal-agb.js';
|
||||
import legalDatenschutzCS from './locales/cs/legal-datenschutz.js';
|
||||
import legalImpressumCS from './locales/cs/legal-impressum.js';
|
||||
import legalWiderrufCS from './locales/cs/legal-widerruf.js';
|
||||
import legalBatterieCS from './locales/cs/legal-batterie.js';
|
||||
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`)
|
||||
]);
|
||||
|
||||
// Greek
|
||||
import legalAgbEL from './locales/el/legal-agb.js';
|
||||
import legalDatenschutzEL from './locales/el/legal-datenschutz.js';
|
||||
import legalImpressumEL from './locales/el/legal-impressum.js';
|
||||
import legalWiderrufEL from './locales/el/legal-widerruf.js';
|
||||
import legalBatterieEL from './locales/el/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);
|
||||
|
||||
// Spanish
|
||||
import legalAgbES from './locales/es/legal-agb.js';
|
||||
import legalDatenschutzES from './locales/es/legal-datenschutz.js';
|
||||
import legalImpressumES from './locales/es/legal-impressum.js';
|
||||
import legalWiderrufES from './locales/es/legal-widerruf.js';
|
||||
import legalBatterieES from './locales/es/legal-batterie.js';
|
||||
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);
|
||||
}
|
||||
})();
|
||||
|
||||
// French
|
||||
import legalAgbFR from './locales/fr/legal-agb.js';
|
||||
import legalDatenschutzFR from './locales/fr/legal-datenschutz.js';
|
||||
import legalImpressumFR from './locales/fr/legal-impressum.js';
|
||||
import legalWiderrufFR from './locales/fr/legal-widerruf.js';
|
||||
import legalBatterieFR from './locales/fr/legal-batterie.js';
|
||||
loadingPromises.set(language, loadingPromise);
|
||||
return loadingPromise;
|
||||
};
|
||||
|
||||
// Croatian
|
||||
import legalAgbHR from './locales/hr/legal-agb.js';
|
||||
import legalDatenschutzHR from './locales/hr/legal-datenschutz.js';
|
||||
import legalImpressumHR from './locales/hr/legal-impressum.js';
|
||||
import legalWiderrufHR from './locales/hr/legal-widerruf.js';
|
||||
import legalBatterieHR from './locales/hr/legal-batterie.js';
|
||||
// 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';
|
||||
}
|
||||
|
||||
// Hungarian
|
||||
import legalAgbHU from './locales/hu/legal-agb.js';
|
||||
import legalDatenschutzHU from './locales/hu/legal-datenschutz.js';
|
||||
import legalImpressumHU from './locales/hu/legal-impressum.js';
|
||||
import legalWiderrufHU from './locales/hu/legal-widerruf.js';
|
||||
import legalBatterieHU from './locales/hu/legal-batterie.js';
|
||||
// 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
|
||||
}
|
||||
|
||||
// Italian
|
||||
import legalAgbIT from './locales/it/legal-agb.js';
|
||||
import legalDatenschutzIT from './locales/it/legal-datenschutz.js';
|
||||
import legalImpressumIT from './locales/it/legal-impressum.js';
|
||||
import legalWiderrufIT from './locales/it/legal-widerruf.js';
|
||||
import legalBatterieIT from './locales/it/legal-batterie.js';
|
||||
// 2. Check localStorage
|
||||
try {
|
||||
if (typeof localStorage !== 'undefined') {
|
||||
const localLang = localStorage.getItem('i18nextLng');
|
||||
if (localLang && localLang !== 'de') {
|
||||
return localLang;
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// LocalStorage not available
|
||||
}
|
||||
|
||||
// Polish
|
||||
import legalAgbPL from './locales/pl/legal-agb.js';
|
||||
import legalDatenschutzPL from './locales/pl/legal-datenschutz.js';
|
||||
import legalImpressumPL from './locales/pl/legal-impressum.js';
|
||||
import legalWiderrufPL from './locales/pl/legal-widerruf.js';
|
||||
import legalBatteriePL from './locales/pl/legal-batterie.js';
|
||||
// 3. Always default to German (don't detect browser language)
|
||||
return 'de';
|
||||
},
|
||||
cacheUserLanguage(lng) {
|
||||
// Only cache in browser environment
|
||||
if (typeof window === 'undefined') {
|
||||
return;
|
||||
}
|
||||
|
||||
// Romanian
|
||||
import legalAgbRO from './locales/ro/legal-agb.js';
|
||||
import legalDatenschutzRO from './locales/ro/legal-datenschutz.js';
|
||||
import legalImpressumRO from './locales/ro/legal-impressum.js';
|
||||
import legalWiderrufRO from './locales/ro/legal-widerruf.js';
|
||||
import legalBatterieRO from './locales/ro/legal-batterie.js';
|
||||
|
||||
// Russian
|
||||
import legalAgbRU from './locales/ru/legal-agb.js';
|
||||
import legalDatenschutzRU from './locales/ru/legal-datenschutz.js';
|
||||
import legalImpressumRU from './locales/ru/legal-impressum.js';
|
||||
import legalWiderrufRU from './locales/ru/legal-widerruf.js';
|
||||
import legalBatterieRU from './locales/ru/legal-batterie.js';
|
||||
|
||||
// Slovak
|
||||
import legalAgbSK from './locales/sk/legal-agb.js';
|
||||
import legalDatenschutzSK from './locales/sk/legal-datenschutz.js';
|
||||
import legalImpressumSK from './locales/sk/legal-impressum.js';
|
||||
import legalWiderrufSK from './locales/sk/legal-widerruf.js';
|
||||
import legalBatterieSK from './locales/sk/legal-batterie.js';
|
||||
|
||||
// Slovenian
|
||||
import legalAgbSL from './locales/sl/legal-agb.js';
|
||||
import legalDatenschutzSL from './locales/sl/legal-datenschutz.js';
|
||||
import legalImpressumSL from './locales/sl/legal-impressum.js';
|
||||
import legalWiderrufSL from './locales/sl/legal-widerruf.js';
|
||||
import legalBatterieSL from './locales/sl/legal-batterie.js';
|
||||
|
||||
// Serbian
|
||||
import legalAgbSR from './locales/sr/legal-agb.js';
|
||||
import legalDatenschutzSR from './locales/sr/legal-datenschutz.js';
|
||||
import legalImpressumSR from './locales/sr/legal-impressum.js';
|
||||
import legalWiderrufSR from './locales/sr/legal-widerruf.js';
|
||||
import legalBatterieSR from './locales/sr/legal-batterie.js';
|
||||
|
||||
// Swedish
|
||||
import legalAgbSV from './locales/sv/legal-agb.js';
|
||||
import legalDatenschutzSV from './locales/sv/legal-datenschutz.js';
|
||||
import legalImpressumSV from './locales/sv/legal-impressum.js';
|
||||
import legalWiderrufSV from './locales/sv/legal-widerruf.js';
|
||||
import legalBatterieSV from './locales/sv/legal-batterie.js';
|
||||
|
||||
// Turkish
|
||||
import legalAgbTR from './locales/tr/legal-agb.js';
|
||||
import legalDatenschutzTR from './locales/tr/legal-datenschutz.js';
|
||||
import legalImpressumTR from './locales/tr/legal-impressum.js';
|
||||
import legalWiderrufTR from './locales/tr/legal-widerruf.js';
|
||||
import legalBatterieTR from './locales/tr/legal-batterie.js';
|
||||
|
||||
// Ukrainian
|
||||
import legalAgbUK from './locales/uk/legal-agb.js';
|
||||
import legalDatenschutzUK from './locales/uk/legal-datenschutz.js';
|
||||
import legalImpressumUK from './locales/uk/legal-impressum.js';
|
||||
import legalWiderrufUK from './locales/uk/legal-widerruf.js';
|
||||
import legalBatterieUK from './locales/uk/legal-batterie.js';
|
||||
|
||||
// Chinese
|
||||
import legalAgbZH from './locales/zh/legal-agb.js';
|
||||
import legalDatenschutzZH from './locales/zh/legal-datenschutz.js';
|
||||
import legalImpressumZH from './locales/zh/legal-impressum.js';
|
||||
import legalWiderrufZH from './locales/zh/legal-widerruf.js';
|
||||
import legalBatterieZH from './locales/zh/legal-batterie.js';
|
||||
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,
|
||||
@@ -181,185 +131,28 @@ const resources = {
|
||||
'legal-impressum': legalImpressumDE,
|
||||
'legal-widerruf': legalWiderrufDE,
|
||||
'legal-batterie': legalBatterieDE
|
||||
},
|
||||
en: {
|
||||
translation: translationEN,
|
||||
'legal-agb': legalAgbEN,
|
||||
'legal-datenschutz': legalDatenschutzEN,
|
||||
'legal-impressum': legalImpressumEN,
|
||||
'legal-widerruf': legalWiderrufEN,
|
||||
'legal-batterie': legalBatterieEN
|
||||
},
|
||||
ar: {
|
||||
translation: translationAR,
|
||||
'legal-agb': legalAgbAR,
|
||||
'legal-datenschutz': legalDatenschutzAR,
|
||||
'legal-impressum': legalImpressumAR,
|
||||
'legal-widerruf': legalWiderrufAR,
|
||||
'legal-batterie': legalBatterieAR
|
||||
},
|
||||
bg: {
|
||||
translation: translationBG,
|
||||
'legal-agb': legalAgbBG,
|
||||
'legal-datenschutz': legalDatenschutzBG,
|
||||
'legal-impressum': legalImpressumBG,
|
||||
'legal-widerruf': legalWiderrufBG,
|
||||
'legal-batterie': legalBatterieBG
|
||||
},
|
||||
cs: {
|
||||
translation: translationCS,
|
||||
'legal-agb': legalAgbCS,
|
||||
'legal-datenschutz': legalDatenschutzCS,
|
||||
'legal-impressum': legalImpressumCS,
|
||||
'legal-widerruf': legalWiderrufCS,
|
||||
'legal-batterie': legalBatterieCS
|
||||
},
|
||||
el: {
|
||||
translation: translationEL,
|
||||
'legal-agb': legalAgbEL,
|
||||
'legal-datenschutz': legalDatenschutzEL,
|
||||
'legal-impressum': legalImpressumEL,
|
||||
'legal-widerruf': legalWiderrufEL,
|
||||
'legal-batterie': legalBatterieEL
|
||||
},
|
||||
es: {
|
||||
translation: translationES,
|
||||
'legal-agb': legalAgbES,
|
||||
'legal-datenschutz': legalDatenschutzES,
|
||||
'legal-impressum': legalImpressumES,
|
||||
'legal-widerruf': legalWiderrufES,
|
||||
'legal-batterie': legalBatterieES
|
||||
},
|
||||
fr: {
|
||||
translation: translationFR,
|
||||
'legal-agb': legalAgbFR,
|
||||
'legal-datenschutz': legalDatenschutzFR,
|
||||
'legal-impressum': legalImpressumFR,
|
||||
'legal-widerruf': legalWiderrufFR,
|
||||
'legal-batterie': legalBatterieFR
|
||||
},
|
||||
hr: {
|
||||
translation: translationHR,
|
||||
'legal-agb': legalAgbHR,
|
||||
'legal-datenschutz': legalDatenschutzHR,
|
||||
'legal-impressum': legalImpressumHR,
|
||||
'legal-widerruf': legalWiderrufHR,
|
||||
'legal-batterie': legalBatterieHR
|
||||
},
|
||||
hu: {
|
||||
translation: translationHU,
|
||||
'legal-agb': legalAgbHU,
|
||||
'legal-datenschutz': legalDatenschutzHU,
|
||||
'legal-impressum': legalImpressumHU,
|
||||
'legal-widerruf': legalWiderrufHU,
|
||||
'legal-batterie': legalBatterieHU
|
||||
},
|
||||
it: {
|
||||
translation: translationIT,
|
||||
'legal-agb': legalAgbIT,
|
||||
'legal-datenschutz': legalDatenschutzIT,
|
||||
'legal-impressum': legalImpressumIT,
|
||||
'legal-widerruf': legalWiderrufIT,
|
||||
'legal-batterie': legalBatterieIT
|
||||
},
|
||||
pl: {
|
||||
translation: translationPL,
|
||||
'legal-agb': legalAgbPL,
|
||||
'legal-datenschutz': legalDatenschutzPL,
|
||||
'legal-impressum': legalImpressumPL,
|
||||
'legal-widerruf': legalWiderrufPL,
|
||||
'legal-batterie': legalBatteriePL
|
||||
},
|
||||
ro: {
|
||||
translation: translationRO,
|
||||
'legal-agb': legalAgbRO,
|
||||
'legal-datenschutz': legalDatenschutzRO,
|
||||
'legal-impressum': legalImpressumRO,
|
||||
'legal-widerruf': legalWiderrufRO,
|
||||
'legal-batterie': legalBatterieRO
|
||||
},
|
||||
ru: {
|
||||
translation: translationRU,
|
||||
'legal-agb': legalAgbRU,
|
||||
'legal-datenschutz': legalDatenschutzRU,
|
||||
'legal-impressum': legalImpressumRU,
|
||||
'legal-widerruf': legalWiderrufRU,
|
||||
'legal-batterie': legalBatterieRU
|
||||
},
|
||||
sk: {
|
||||
translation: translationSK,
|
||||
'legal-agb': legalAgbSK,
|
||||
'legal-datenschutz': legalDatenschutzSK,
|
||||
'legal-impressum': legalImpressumSK,
|
||||
'legal-widerruf': legalWiderrufSK,
|
||||
'legal-batterie': legalBatterieSK
|
||||
},
|
||||
sl: {
|
||||
translation: translationSL,
|
||||
'legal-agb': legalAgbSL,
|
||||
'legal-datenschutz': legalDatenschutzSL,
|
||||
'legal-impressum': legalImpressumSL,
|
||||
'legal-widerruf': legalWiderrufSL,
|
||||
'legal-batterie': legalBatterieSL
|
||||
},
|
||||
sr: {
|
||||
translation: translationSR,
|
||||
'legal-agb': legalAgbSR,
|
||||
'legal-datenschutz': legalDatenschutzSR,
|
||||
'legal-impressum': legalImpressumSR,
|
||||
'legal-widerruf': legalWiderrufSR,
|
||||
'legal-batterie': legalBatterieSR
|
||||
},
|
||||
sv: {
|
||||
translation: translationSV,
|
||||
'legal-agb': legalAgbSV,
|
||||
'legal-datenschutz': legalDatenschutzSV,
|
||||
'legal-impressum': legalImpressumSV,
|
||||
'legal-widerruf': legalWiderrufSV,
|
||||
'legal-batterie': legalBatterieSV
|
||||
},
|
||||
tr: {
|
||||
translation: translationTR,
|
||||
'legal-agb': legalAgbTR,
|
||||
'legal-datenschutz': legalDatenschutzTR,
|
||||
'legal-impressum': legalImpressumTR,
|
||||
'legal-widerruf': legalWiderrufTR,
|
||||
'legal-batterie': legalBatterieTR
|
||||
},
|
||||
uk: {
|
||||
translation: translationUK,
|
||||
'legal-agb': legalAgbUK,
|
||||
'legal-datenschutz': legalDatenschutzUK,
|
||||
'legal-impressum': legalImpressumUK,
|
||||
'legal-widerruf': legalWiderrufUK,
|
||||
'legal-batterie': legalBatterieUK
|
||||
},
|
||||
zh: {
|
||||
translation: translationZH,
|
||||
'legal-agb': legalAgbZH,
|
||||
'legal-datenschutz': legalDatenschutzZH,
|
||||
'legal-impressum': legalImpressumZH,
|
||||
'legal-widerruf': legalWiderrufZH,
|
||||
'legal-batterie': legalBatterieZH
|
||||
}
|
||||
};
|
||||
|
||||
i18n
|
||||
.use(LanguageDetector)
|
||||
.use({
|
||||
type: 'languageDetector',
|
||||
async: false,
|
||||
detect: customDetector.lookup,
|
||||
init() {},
|
||||
cacheUserLanguage: customDetector.cacheUserLanguage
|
||||
})
|
||||
.use(initReactI18next)
|
||||
.init({
|
||||
resources,
|
||||
fallbackLng: 'de', // German as fallback since it's your primary language
|
||||
lng: 'de', // Force German as default
|
||||
fallbackLng: 'de',
|
||||
debug: process.env.NODE_ENV === 'development',
|
||||
|
||||
// Language detection options
|
||||
// Disable automatic language detection from browser
|
||||
detection: {
|
||||
// Order of language detection methods
|
||||
order: ['localStorage', 'navigator', 'htmlTag'],
|
||||
// Cache the language selection
|
||||
caches: ['localStorage'],
|
||||
// Check for language in localStorage
|
||||
lookupLocalStorage: 'i18nextLng'
|
||||
order: ['customDetector'],
|
||||
caches: ['localStorage', 'sessionStorage']
|
||||
},
|
||||
|
||||
interpolation: {
|
||||
@@ -372,10 +165,57 @@ i18n
|
||||
// React-specific options
|
||||
react: {
|
||||
useSuspense: false // Disable suspense for class components compatibility
|
||||
}
|
||||
},
|
||||
|
||||
// Load missing keys as fallback
|
||||
saveMissing: process.env.NODE_ENV === 'development'
|
||||
});
|
||||
|
||||
// Export withI18n and other utilities for easy access
|
||||
export { withI18n, withTranslation, withLanguage, LanguageContext, LanguageProvider } from './withTranslation.js';
|
||||
// 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);
|
||||
};
|
||||
|
||||
export default i18n;
|
||||
// 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';
|
||||
@@ -1,5 +1,6 @@
|
||||
import React, { Component } from 'react';
|
||||
import { withTranslation as reactI18nextWithTranslation } from 'react-i18next';
|
||||
import { loadLanguage } from './index.js';
|
||||
|
||||
// HOC to provide translation functions to class components
|
||||
export const withTranslation = (namespaces = 'translation') => (WrappedComponent) => {
|
||||
@@ -10,7 +11,7 @@ export const withTranslation = (namespaces = 'translation') => (WrappedComponent
|
||||
export const LanguageContext = React.createContext({
|
||||
currentLanguage: 'de',
|
||||
changeLanguage: () => {},
|
||||
availableLanguages: ['ar', 'bg', 'cs', 'de', 'el', 'en', 'es', 'fr', 'hr', 'hu', 'it', 'pl', 'ro', 'ru', 'sk', 'sl', 'sr', 'sv', 'tr', 'uk', 'zh']
|
||||
availableLanguages: ['de'] // Start with only German
|
||||
});
|
||||
|
||||
// Provider component for language management
|
||||
@@ -18,14 +19,16 @@ export class LanguageProvider extends Component {
|
||||
constructor(props) {
|
||||
super(props);
|
||||
|
||||
// Get initial language from i18n instance
|
||||
const currentLanguage = props.i18n?.language || 'de';
|
||||
// Always start with German
|
||||
const currentLanguage = 'de';
|
||||
|
||||
this.state = {
|
||||
currentLanguage,
|
||||
availableLanguages: ['ar', 'bg', 'cs', 'de', 'el', 'en', 'es', 'fr', 'hr', 'hu', 'it', 'pl', 'ro', 'ru', 'sk', 'sl', 'sr', 'sv', 'tr', 'uk', 'zh'],
|
||||
demoMode: false, // Enable demo mode
|
||||
currentLanguageIndex: 0
|
||||
availableLanguages: ['de'], // Start with only German visible
|
||||
allLanguages: ['ar', 'bg', 'cs', 'de', 'el', 'en', 'es', 'fr', 'hr', 'hu', 'it', 'pl', 'ro', 'ru', 'sk', 'sl', 'sr', 'sv', 'tr', 'uk', 'zh'],
|
||||
demoMode: false,
|
||||
currentLanguageIndex: 0,
|
||||
loadingLanguages: new Set()
|
||||
};
|
||||
|
||||
this.demoInterval = null;
|
||||
@@ -124,14 +127,47 @@ export class LanguageProvider extends Component {
|
||||
}
|
||||
};
|
||||
|
||||
changeLanguage = (language) => {
|
||||
if (this.props.i18n && this.state.availableLanguages.includes(language)) {
|
||||
changeLanguage = async (language) => {
|
||||
if (this.props.i18n && this.state.allLanguages.includes(language)) {
|
||||
// Stop demo mode if user manually changes language
|
||||
if (this.state.demoMode) {
|
||||
this.stopDemo();
|
||||
}
|
||||
|
||||
this.props.i18n.changeLanguage(language);
|
||||
// If language is not German and not already available, load it
|
||||
if (language !== 'de' && !this.state.availableLanguages.includes(language)) {
|
||||
// Check if already loading
|
||||
if (this.state.loadingLanguages.has(language)) {
|
||||
return; // Already loading
|
||||
}
|
||||
|
||||
// Mark as loading
|
||||
this.setState(prevState => ({
|
||||
loadingLanguages: new Set([...prevState.loadingLanguages, language])
|
||||
}));
|
||||
|
||||
try {
|
||||
console.log(`🌍 Loading language: ${language}`);
|
||||
await loadLanguage(language);
|
||||
|
||||
// Add to available languages after successful load
|
||||
this.setState(prevState => ({
|
||||
availableLanguages: [...prevState.availableLanguages, language],
|
||||
loadingLanguages: new Set([...prevState.loadingLanguages].filter(l => l !== language))
|
||||
}));
|
||||
|
||||
console.log(`✅ Language ${language} now available`);
|
||||
} catch (error) {
|
||||
console.error(`❌ Failed to load language ${language}:`, error);
|
||||
this.setState(prevState => ({
|
||||
loadingLanguages: new Set([...prevState.loadingLanguages].filter(l => l !== language))
|
||||
}));
|
||||
return; // Don't change language if loading failed
|
||||
}
|
||||
}
|
||||
|
||||
// Change the language
|
||||
await this.props.i18n.changeLanguage(language);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -140,6 +176,8 @@ export class LanguageProvider extends Component {
|
||||
currentLanguage: this.state.currentLanguage,
|
||||
changeLanguage: this.changeLanguage,
|
||||
availableLanguages: this.state.availableLanguages,
|
||||
allLanguages: this.state.allLanguages,
|
||||
loadingLanguages: this.state.loadingLanguages,
|
||||
demoMode: this.state.demoMode,
|
||||
stopDemo: this.stopDemo
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user