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) => { return reactI18nextWithTranslation(namespaces)(WrappedComponent); }; // Context for language switching export const LanguageContext = React.createContext({ currentLanguage: 'de', changeLanguage: () => {}, availableLanguages: ['de'] // Start with only German }); // Provider component for language management export class LanguageProvider extends Component { constructor(props) { super(props); // Try to get the current language from i18n or storage, fallback to German let currentLanguage = 'de'; console.log("LanguageProvider constructor - Debug info:"); console.log(" props.i18n:", props.i18n); console.log(" props.i18n.language:", props.i18n?.language); if (props.i18n && props.i18n.language) { currentLanguage = props.i18n.language; console.log(" Using language from i18n:", currentLanguage); } else if (typeof window !== 'undefined') { // Try to get from sessionStorage first, then localStorage try { const sessionLang = sessionStorage.getItem('i18nextLng'); const localLang = localStorage.getItem('i18nextLng'); console.log(" sessionStorage i18nextLng:", sessionLang); console.log(" localStorage i18nextLng:", localLang); currentLanguage = sessionLang || localLang || 'de'; console.log(" Using language from storage:", currentLanguage); } catch (error) { console.warn('Could not read language from storage:', error); } } console.log(" Final currentLanguage:", currentLanguage); this.state = { currentLanguage, availableLanguages: ['de'], // Start with only German visible allLanguages: ['ar', 'bg', 'cs', 'de', 'el', 'en', 'es', 'fr', 'hr', 'hu', 'it', 'pl', 'ro', 'ru', 'sk', 'sl', 'sq', 'sr', 'sv', 'tr', 'uk', 'zh'], demoMode: false, currentLanguageIndex: 0, loadingLanguages: new Set() }; this.demoInterval = null; } componentDidMount() { if (this.props.i18n) { this.props.i18n.on('languageChanged', this.handleLanguageChanged); console.log("LanguageProvider componentDidMount:"); console.log(" current state.currentLanguage:", this.state.currentLanguage); console.log(" props.i18n.language:", this.props.i18n.language); // Only update state if i18n language is different and not the default 'de' // This prevents overriding the language we restored from storage if (this.props.i18n.language !== this.state.currentLanguage && this.props.i18n.language !== 'de') { console.log(" Updating language from i18n:", this.props.i18n.language); this.setState({ currentLanguage: this.props.i18n.language }); document.documentElement.lang = this.props.i18n.language; } else { console.log(" Keeping language from constructor:", this.state.currentLanguage); document.documentElement.lang = this.state.currentLanguage; } // Start demo mode if (this.state.demoMode) { this.startDemo(); } } } componentWillUnmount() { if (this.props.i18n) { this.props.i18n.off('languageChanged', this.handleLanguageChanged); } // Clean up demo interval if (this.demoInterval) { clearInterval(this.demoInterval); } } startDemo = () => { // Find current language index const currentIndex = this.state.availableLanguages.indexOf(this.state.currentLanguage); this.setState({ currentLanguageIndex: currentIndex >= 0 ? currentIndex : 0 }); this.demoInterval = setInterval(() => { const nextIndex = (this.state.currentLanguageIndex + 1) % this.state.availableLanguages.length; const nextLanguage = this.state.availableLanguages[nextIndex]; this.setState({ currentLanguageIndex: nextIndex }); if (this.props.i18n) { this.props.i18n.changeLanguage(nextLanguage); } }, 5000); // Change language every 5 seconds }; stopDemo = () => { if (this.demoInterval) { clearInterval(this.demoInterval); this.demoInterval = null; } this.setState({ demoMode: false }); }; handleLanguageChanged = (lng) => { this.setState({ currentLanguage: lng }); // Update HTML lang attribute for SEO document.documentElement.lang = lng; // Ensure language is saved to localStorage try { localStorage.setItem('i18nextLng', lng); } catch (error) { console.warn('Could not save language to localStorage:', error); } // Update config if available if (window.shopConfig) { // Language code mapping for all supported languages const languageMap = { 'ar': 'ar-EG', 'bg': 'bg-BG', 'cs': 'cs-CZ', 'de': 'de-DE', 'el': 'el-GR', 'en': 'en-US', 'es': 'es-ES', 'fr': 'fr-FR', 'hr': 'hr-HR', 'hu': 'hu-HU', 'it': 'it-IT', 'pl': 'pl-PL', 'ro': 'ro-RO', 'ru': 'ru-RU', 'sk': 'sk-SK', 'sl': 'sl-SI', 'sr': 'sr-RS', 'sv': 'sv-SE', 'tr': 'tr-TR', 'uk': 'uk-UA', 'zh': 'zh-CN' }; window.shopConfig.language = languageMap[lng] || 'de-DE'; } }; 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(); } // 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); } }; render() { const contextValue = { 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 }; return ( {this.props.children} ); } } // HOC to inject language context into class components export const withLanguage = (WrappedComponent) => { return class extends Component { render() { return ( {(languageContext) => ( )} ); } }; }; // Combined HOC that provides both translation and language context export const withI18n = (namespaces = 'translation') => (WrappedComponent) => { const WithTranslationComponent = withTranslation(namespaces)(WrappedComponent); return withLanguage(WithTranslationComponent); };