- Replaced the existing legal document files with more specific ones for delivery, payment, and consumer rights. - Added new legal documents related to data protection, including basic, customer, Google orders, newsletter, chatbot, cookies, and rights. - Introduced Albanian language support in the translation files and language switcher component. - Enhanced the translation functions to ensure structural files are copied correctly for new languages.
247 lines
8.2 KiB
JavaScript
247 lines
8.2 KiB
JavaScript
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 (
|
|
<LanguageContext.Provider value={contextValue}>
|
|
{this.props.children}
|
|
</LanguageContext.Provider>
|
|
);
|
|
}
|
|
}
|
|
|
|
// HOC to inject language context into class components
|
|
export const withLanguage = (WrappedComponent) => {
|
|
return class extends Component {
|
|
render() {
|
|
return (
|
|
<LanguageContext.Consumer>
|
|
{(languageContext) => (
|
|
<WrappedComponent {...this.props} languageContext={languageContext} />
|
|
)}
|
|
</LanguageContext.Consumer>
|
|
);
|
|
}
|
|
};
|
|
};
|
|
|
|
// Combined HOC that provides both translation and language context
|
|
export const withI18n = (namespaces = 'translation') => (WrappedComponent) => {
|
|
const WithTranslationComponent = withTranslation(namespaces)(WrappedComponent);
|
|
return withLanguage(WithTranslationComponent);
|
|
};
|