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 });
|
this.setState({ anchorEl: null });
|
||||||
};
|
};
|
||||||
|
|
||||||
handleLanguageChange = (language) => {
|
handleLanguageChange = async (language) => {
|
||||||
const { languageContext } = this.props;
|
const { languageContext } = this.props;
|
||||||
if (languageContext) {
|
if (languageContext) {
|
||||||
languageContext.changeLanguage(language);
|
try {
|
||||||
|
await languageContext.changeLanguage(language);
|
||||||
|
} catch (error) {
|
||||||
|
console.error('Failed to change language:', error);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
this.handleClose();
|
this.handleClose();
|
||||||
};
|
};
|
||||||
@@ -126,8 +130,8 @@ class LanguageSwitcher extends Component {
|
|||||||
const { languageContext } = this.props;
|
const { languageContext } = this.props;
|
||||||
|
|
||||||
if (anchorEl && !prevState.anchorEl && languageContext) {
|
if (anchorEl && !prevState.anchorEl && languageContext) {
|
||||||
// Menu just opened, lazy load all flags
|
// Menu just opened, lazy load flags for all languages (not just available ones)
|
||||||
languageContext.availableLanguages.forEach(lang => {
|
languageContext.allLanguages.forEach(lang => {
|
||||||
if (!this.state.loadedFlags[lang]) {
|
if (!this.state.loadedFlags[lang]) {
|
||||||
this.loadFlagComponent(lang);
|
this.loadFlagComponent(lang);
|
||||||
}
|
}
|
||||||
@@ -197,7 +201,7 @@ class LanguageSwitcher extends Component {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
const { currentLanguage, availableLanguages } = languageContext;
|
const { currentLanguage, allLanguages } = languageContext;
|
||||||
const open = Boolean(anchorEl);
|
const open = Boolean(anchorEl);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
@@ -237,7 +241,8 @@ class LanguageSwitcher extends Component {
|
|||||||
horizontal: 'right',
|
horizontal: 'right',
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
{availableLanguages.map((language) => (
|
{allLanguages.map((language) => {
|
||||||
|
return (
|
||||||
<MenuItem
|
<MenuItem
|
||||||
key={language}
|
key={language}
|
||||||
onClick={() => this.handleLanguageChange(language)}
|
onClick={() => this.handleLanguageChange(language)}
|
||||||
@@ -259,7 +264,8 @@ class LanguageSwitcher extends Component {
|
|||||||
{this.getLanguageLabel(language)}
|
{this.getLanguageLabel(language)}
|
||||||
</Typography>
|
</Typography>
|
||||||
</MenuItem>
|
</MenuItem>
|
||||||
))}
|
);
|
||||||
|
})}
|
||||||
</Menu>
|
</Menu>
|
||||||
</Box>
|
</Box>
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -1,178 +1,128 @@
|
|||||||
import i18n from 'i18next';
|
import i18n from 'i18next';
|
||||||
import { initReactI18next } from 'react-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 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 legalAgbDE from './locales/de/legal-agb.js';
|
||||||
import legalDatenschutzDE from './locales/de/legal-datenschutz.js';
|
import legalDatenschutzDE from './locales/de/legal-datenschutz.js';
|
||||||
import legalImpressumDE from './locales/de/legal-impressum.js';
|
import legalImpressumDE from './locales/de/legal-impressum.js';
|
||||||
import legalWiderrufDE from './locales/de/legal-widerruf.js';
|
import legalWiderrufDE from './locales/de/legal-widerruf.js';
|
||||||
import legalBatterieDE from './locales/de/legal-batterie.js';
|
import legalBatterieDE from './locales/de/legal-batterie.js';
|
||||||
|
|
||||||
// English
|
// Language loading cache to prevent duplicate loads
|
||||||
import legalAgbEN from './locales/en/legal-agb.js';
|
const languageCache = new Set(['de']);
|
||||||
import legalDatenschutzEN from './locales/en/legal-datenschutz.js';
|
const loadingPromises = new Map();
|
||||||
import legalImpressumEN from './locales/en/legal-impressum.js';
|
|
||||||
import legalWiderrufEN from './locales/en/legal-widerruf.js';
|
|
||||||
import legalBatterieEN from './locales/en/legal-batterie.js';
|
|
||||||
|
|
||||||
// Arabic
|
// Lazy loading function for languages
|
||||||
import legalAgbAR from './locales/ar/legal-agb.js';
|
const loadLanguage = async (language) => {
|
||||||
import legalDatenschutzAR from './locales/ar/legal-datenschutz.js';
|
if (languageCache.has(language)) {
|
||||||
import legalImpressumAR from './locales/ar/legal-impressum.js';
|
return; // Already loaded
|
||||||
import legalWiderrufAR from './locales/ar/legal-widerruf.js';
|
}
|
||||||
import legalBatterieAR from './locales/ar/legal-batterie.js';
|
|
||||||
|
|
||||||
// Bulgarian
|
if (loadingPromises.has(language)) {
|
||||||
import legalAgbBG from './locales/bg/legal-agb.js';
|
return loadingPromises.get(language); // Already loading
|
||||||
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';
|
|
||||||
|
|
||||||
// Czech
|
const loadingPromise = (async () => {
|
||||||
import legalAgbCS from './locales/cs/legal-agb.js';
|
try {
|
||||||
import legalDatenschutzCS from './locales/cs/legal-datenschutz.js';
|
console.log(`🌍 Lazy loading language: ${language}`);
|
||||||
import legalImpressumCS from './locales/cs/legal-impressum.js';
|
|
||||||
import legalWiderrufCS from './locales/cs/legal-widerruf.js';
|
|
||||||
import legalBatterieCS from './locales/cs/legal-batterie.js';
|
|
||||||
|
|
||||||
// Greek
|
// Dynamic imports for lazy loading
|
||||||
import legalAgbEL from './locales/el/legal-agb.js';
|
const [
|
||||||
import legalDatenschutzEL from './locales/el/legal-datenschutz.js';
|
translation,
|
||||||
import legalImpressumEL from './locales/el/legal-impressum.js';
|
legalAgb,
|
||||||
import legalWiderrufEL from './locales/el/legal-widerruf.js';
|
legalDatenschutz,
|
||||||
import legalBatterieEL from './locales/el/legal-batterie.js';
|
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`)
|
||||||
|
]);
|
||||||
|
|
||||||
// Spanish
|
// Add the loaded resources to i18n
|
||||||
import legalAgbES from './locales/es/legal-agb.js';
|
i18n.addResourceBundle(language, 'translation', translation.default);
|
||||||
import legalDatenschutzES from './locales/es/legal-datenschutz.js';
|
i18n.addResourceBundle(language, 'legal-agb', legalAgb.default);
|
||||||
import legalImpressumES from './locales/es/legal-impressum.js';
|
i18n.addResourceBundle(language, 'legal-datenschutz', legalDatenschutz.default);
|
||||||
import legalWiderrufES from './locales/es/legal-widerruf.js';
|
i18n.addResourceBundle(language, 'legal-impressum', legalImpressum.default);
|
||||||
import legalBatterieES from './locales/es/legal-batterie.js';
|
i18n.addResourceBundle(language, 'legal-widerruf', legalWiderruf.default);
|
||||||
|
i18n.addResourceBundle(language, 'legal-batterie', legalBatterie.default);
|
||||||
|
|
||||||
// French
|
languageCache.add(language);
|
||||||
import legalAgbFR from './locales/fr/legal-agb.js';
|
console.log(`✅ Language ${language} loaded successfully`);
|
||||||
import legalDatenschutzFR from './locales/fr/legal-datenschutz.js';
|
} catch (error) {
|
||||||
import legalImpressumFR from './locales/fr/legal-impressum.js';
|
console.error(`❌ Failed to load language ${language}:`, error);
|
||||||
import legalWiderrufFR from './locales/fr/legal-widerruf.js';
|
throw error;
|
||||||
import legalBatterieFR from './locales/fr/legal-batterie.js';
|
} finally {
|
||||||
|
loadingPromises.delete(language);
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
|
||||||
// Croatian
|
loadingPromises.set(language, loadingPromise);
|
||||||
import legalAgbHR from './locales/hr/legal-agb.js';
|
return loadingPromise;
|
||||||
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';
|
|
||||||
|
|
||||||
// Hungarian
|
// Custom language detector that prioritizes session storage and defaults to German
|
||||||
import legalAgbHU from './locales/hu/legal-agb.js';
|
const customDetector = {
|
||||||
import legalDatenschutzHU from './locales/hu/legal-datenschutz.js';
|
name: 'customDetector',
|
||||||
import legalImpressumHU from './locales/hu/legal-impressum.js';
|
lookup() {
|
||||||
import legalWiderrufHU from './locales/hu/legal-widerruf.js';
|
// Only try storage in browser environment
|
||||||
import legalBatterieHU from './locales/hu/legal-batterie.js';
|
if (typeof window === 'undefined') {
|
||||||
|
return 'de';
|
||||||
|
}
|
||||||
|
|
||||||
// Italian
|
// 1. Check session storage first
|
||||||
import legalAgbIT from './locales/it/legal-agb.js';
|
try {
|
||||||
import legalDatenschutzIT from './locales/it/legal-datenschutz.js';
|
if (typeof sessionStorage !== 'undefined') {
|
||||||
import legalImpressumIT from './locales/it/legal-impressum.js';
|
const sessionLang = sessionStorage.getItem('i18nextLng');
|
||||||
import legalWiderrufIT from './locales/it/legal-widerruf.js';
|
if (sessionLang && sessionLang !== 'de') {
|
||||||
import legalBatterieIT from './locales/it/legal-batterie.js';
|
return sessionLang;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// Session storage not available
|
||||||
|
}
|
||||||
|
|
||||||
// Polish
|
// 2. Check localStorage
|
||||||
import legalAgbPL from './locales/pl/legal-agb.js';
|
try {
|
||||||
import legalDatenschutzPL from './locales/pl/legal-datenschutz.js';
|
if (typeof localStorage !== 'undefined') {
|
||||||
import legalImpressumPL from './locales/pl/legal-impressum.js';
|
const localLang = localStorage.getItem('i18nextLng');
|
||||||
import legalWiderrufPL from './locales/pl/legal-widerruf.js';
|
if (localLang && localLang !== 'de') {
|
||||||
import legalBatteriePL from './locales/pl/legal-batterie.js';
|
return localLang;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch {
|
||||||
|
// LocalStorage not available
|
||||||
|
}
|
||||||
|
|
||||||
// Romanian
|
// 3. Always default to German (don't detect browser language)
|
||||||
import legalAgbRO from './locales/ro/legal-agb.js';
|
return 'de';
|
||||||
import legalDatenschutzRO from './locales/ro/legal-datenschutz.js';
|
},
|
||||||
import legalImpressumRO from './locales/ro/legal-impressum.js';
|
cacheUserLanguage(lng) {
|
||||||
import legalWiderrufRO from './locales/ro/legal-widerruf.js';
|
// Only cache in browser environment
|
||||||
import legalBatterieRO from './locales/ro/legal-batterie.js';
|
if (typeof window === 'undefined') {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Russian
|
try {
|
||||||
import legalAgbRU from './locales/ru/legal-agb.js';
|
if (typeof sessionStorage !== 'undefined') {
|
||||||
import legalDatenschutzRU from './locales/ru/legal-datenschutz.js';
|
sessionStorage.setItem('i18nextLng', lng);
|
||||||
import legalImpressumRU from './locales/ru/legal-impressum.js';
|
}
|
||||||
import legalWiderrufRU from './locales/ru/legal-widerruf.js';
|
if (typeof localStorage !== 'undefined') {
|
||||||
import legalBatterieRU from './locales/ru/legal-batterie.js';
|
localStorage.setItem('i18nextLng', lng);
|
||||||
|
}
|
||||||
// Slovak
|
} catch {
|
||||||
import legalAgbSK from './locales/sk/legal-agb.js';
|
// Storage not available
|
||||||
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';
|
|
||||||
|
|
||||||
|
// Initialize i18n with only German resources
|
||||||
const resources = {
|
const resources = {
|
||||||
de: {
|
de: {
|
||||||
translation: translationDE,
|
translation: translationDE,
|
||||||
@@ -181,185 +131,28 @@ const resources = {
|
|||||||
'legal-impressum': legalImpressumDE,
|
'legal-impressum': legalImpressumDE,
|
||||||
'legal-widerruf': legalWiderrufDE,
|
'legal-widerruf': legalWiderrufDE,
|
||||||
'legal-batterie': legalBatterieDE
|
'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
|
i18n
|
||||||
.use(LanguageDetector)
|
.use({
|
||||||
|
type: 'languageDetector',
|
||||||
|
async: false,
|
||||||
|
detect: customDetector.lookup,
|
||||||
|
init() {},
|
||||||
|
cacheUserLanguage: customDetector.cacheUserLanguage
|
||||||
|
})
|
||||||
.use(initReactI18next)
|
.use(initReactI18next)
|
||||||
.init({
|
.init({
|
||||||
resources,
|
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',
|
debug: process.env.NODE_ENV === 'development',
|
||||||
|
|
||||||
// Language detection options
|
// Disable automatic language detection from browser
|
||||||
detection: {
|
detection: {
|
||||||
// Order of language detection methods
|
order: ['customDetector'],
|
||||||
order: ['localStorage', 'navigator', 'htmlTag'],
|
caches: ['localStorage', 'sessionStorage']
|
||||||
// Cache the language selection
|
|
||||||
caches: ['localStorage'],
|
|
||||||
// Check for language in localStorage
|
|
||||||
lookupLocalStorage: 'i18nextLng'
|
|
||||||
},
|
},
|
||||||
|
|
||||||
interpolation: {
|
interpolation: {
|
||||||
@@ -372,10 +165,57 @@ i18n
|
|||||||
// React-specific options
|
// React-specific options
|
||||||
react: {
|
react: {
|
||||||
useSuspense: false // Disable suspense for class components compatibility
|
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
|
// Override changeLanguage to load languages on demand
|
||||||
export { withI18n, withTranslation, withLanguage, LanguageContext, LanguageProvider } from './withTranslation.js';
|
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 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 React, { Component } from 'react';
|
||||||
import { withTranslation as reactI18nextWithTranslation } from 'react-i18next';
|
import { withTranslation as reactI18nextWithTranslation } from 'react-i18next';
|
||||||
|
import { loadLanguage } from './index.js';
|
||||||
|
|
||||||
// HOC to provide translation functions to class components
|
// HOC to provide translation functions to class components
|
||||||
export const withTranslation = (namespaces = 'translation') => (WrappedComponent) => {
|
export const withTranslation = (namespaces = 'translation') => (WrappedComponent) => {
|
||||||
@@ -10,7 +11,7 @@ export const withTranslation = (namespaces = 'translation') => (WrappedComponent
|
|||||||
export const LanguageContext = React.createContext({
|
export const LanguageContext = React.createContext({
|
||||||
currentLanguage: 'de',
|
currentLanguage: 'de',
|
||||||
changeLanguage: () => {},
|
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
|
// Provider component for language management
|
||||||
@@ -18,14 +19,16 @@ export class LanguageProvider extends Component {
|
|||||||
constructor(props) {
|
constructor(props) {
|
||||||
super(props);
|
super(props);
|
||||||
|
|
||||||
// Get initial language from i18n instance
|
// Always start with German
|
||||||
const currentLanguage = props.i18n?.language || 'de';
|
const currentLanguage = 'de';
|
||||||
|
|
||||||
this.state = {
|
this.state = {
|
||||||
currentLanguage,
|
currentLanguage,
|
||||||
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 visible
|
||||||
demoMode: false, // Enable demo mode
|
allLanguages: ['ar', 'bg', 'cs', 'de', 'el', 'en', 'es', 'fr', 'hr', 'hu', 'it', 'pl', 'ro', 'ru', 'sk', 'sl', 'sr', 'sv', 'tr', 'uk', 'zh'],
|
||||||
currentLanguageIndex: 0
|
demoMode: false,
|
||||||
|
currentLanguageIndex: 0,
|
||||||
|
loadingLanguages: new Set()
|
||||||
};
|
};
|
||||||
|
|
||||||
this.demoInterval = null;
|
this.demoInterval = null;
|
||||||
@@ -124,14 +127,47 @@ export class LanguageProvider extends Component {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
changeLanguage = (language) => {
|
changeLanguage = async (language) => {
|
||||||
if (this.props.i18n && this.state.availableLanguages.includes(language)) {
|
if (this.props.i18n && this.state.allLanguages.includes(language)) {
|
||||||
// Stop demo mode if user manually changes language
|
// Stop demo mode if user manually changes language
|
||||||
if (this.state.demoMode) {
|
if (this.state.demoMode) {
|
||||||
this.stopDemo();
|
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,
|
currentLanguage: this.state.currentLanguage,
|
||||||
changeLanguage: this.changeLanguage,
|
changeLanguage: this.changeLanguage,
|
||||||
availableLanguages: this.state.availableLanguages,
|
availableLanguages: this.state.availableLanguages,
|
||||||
|
allLanguages: this.state.allLanguages,
|
||||||
|
loadingLanguages: this.state.loadingLanguages,
|
||||||
demoMode: this.state.demoMode,
|
demoMode: this.state.demoMode,
|
||||||
stopDemo: this.stopDemo
|
stopDemo: this.stopDemo
|
||||||
};
|
};
|
||||||
|
|||||||
Reference in New Issue
Block a user