- 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.
278 lines
8.0 KiB
JavaScript
278 lines
8.0 KiB
JavaScript
import React, { Component } from 'react';
|
|
import Box from '@mui/material/Box';
|
|
import Button from '@mui/material/Button';
|
|
import Menu from '@mui/material/Menu';
|
|
import MenuItem from '@mui/material/MenuItem';
|
|
import Typography from '@mui/material/Typography';
|
|
import { withI18n } from '../i18n/withTranslation.js';
|
|
|
|
class LanguageSwitcher extends Component {
|
|
constructor(props) {
|
|
super(props);
|
|
|
|
this.state = {
|
|
anchorEl: null,
|
|
loadedFlags: {}
|
|
};
|
|
}
|
|
|
|
handleClick = (event) => {
|
|
this.setState({ anchorEl: event.currentTarget });
|
|
};
|
|
|
|
handleClose = () => {
|
|
this.setState({ anchorEl: null });
|
|
};
|
|
|
|
handleLanguageChange = async (language) => {
|
|
const { languageContext } = this.props;
|
|
if (languageContext) {
|
|
try {
|
|
await languageContext.changeLanguage(language);
|
|
} catch (error) {
|
|
console.error('Failed to change language:', error);
|
|
}
|
|
}
|
|
this.handleClose();
|
|
};
|
|
|
|
// Lazy load flag components
|
|
loadFlagComponent = async (lang) => {
|
|
if (this.state.loadedFlags[lang]) {
|
|
return this.state.loadedFlags[lang];
|
|
}
|
|
|
|
try {
|
|
const flagMap = {
|
|
'ar': () => import('country-flag-icons/react/3x2').then(m => m.EG),
|
|
'bg': () => import('country-flag-icons/react/3x2').then(m => m.BG),
|
|
'cs': () => import('country-flag-icons/react/3x2').then(m => m.CZ),
|
|
'de': () => import('country-flag-icons/react/3x2').then(m => m.DE),
|
|
'el': () => import('country-flag-icons/react/3x2').then(m => m.GR),
|
|
'en': () => import('country-flag-icons/react/3x2').then(m => m.US),
|
|
'es': () => import('country-flag-icons/react/3x2').then(m => m.ES),
|
|
'fr': () => import('country-flag-icons/react/3x2').then(m => m.FR),
|
|
'hr': () => import('country-flag-icons/react/3x2').then(m => m.HR),
|
|
'hu': () => import('country-flag-icons/react/3x2').then(m => m.HU),
|
|
'it': () => import('country-flag-icons/react/3x2').then(m => m.IT),
|
|
'pl': () => import('country-flag-icons/react/3x2').then(m => m.PL),
|
|
'ro': () => import('country-flag-icons/react/3x2').then(m => m.RO),
|
|
'ru': () => import('country-flag-icons/react/3x2').then(m => m.RU),
|
|
'sk': () => import('country-flag-icons/react/3x2').then(m => m.SK),
|
|
'sl': () => import('country-flag-icons/react/3x2').then(m => m.SI),
|
|
'sq': () => import('country-flag-icons/react/3x2').then(m => m.AL),
|
|
'sr': () => import('country-flag-icons/react/3x2').then(m => m.RS),
|
|
'sv': () => import('country-flag-icons/react/3x2').then(m => m.SE),
|
|
'tr': () => import('country-flag-icons/react/3x2').then(m => m.TR),
|
|
'uk': () => import('country-flag-icons/react/3x2').then(m => m.UA),
|
|
'zh': () => import('country-flag-icons/react/3x2').then(m => m.CN)
|
|
};
|
|
|
|
const flagLoader = flagMap[lang];
|
|
if (flagLoader) {
|
|
const FlagComponent = await flagLoader();
|
|
this.setState(prevState => ({
|
|
loadedFlags: {
|
|
...prevState.loadedFlags,
|
|
[lang]: FlagComponent
|
|
}
|
|
}));
|
|
return FlagComponent;
|
|
}
|
|
} catch (error) {
|
|
console.warn(`Failed to load flag for language: ${lang}`, error);
|
|
}
|
|
return null;
|
|
};
|
|
|
|
getLanguageFlag = (lang) => {
|
|
const FlagComponent = this.state.loadedFlags[lang];
|
|
|
|
if (FlagComponent) {
|
|
return (
|
|
<FlagComponent
|
|
style={{
|
|
width: '20px',
|
|
height: '14px',
|
|
borderRadius: '2px',
|
|
border: '1px solid #ddd'
|
|
}}
|
|
/>
|
|
);
|
|
}
|
|
|
|
// Loading placeholder or fallback
|
|
return (
|
|
<Box
|
|
component="span"
|
|
sx={{
|
|
display: 'inline-flex',
|
|
alignItems: 'center',
|
|
justifyContent: 'center',
|
|
minWidth: '20px',
|
|
height: '14px',
|
|
backgroundColor: '#f5f5f5',
|
|
color: '#666',
|
|
fontSize: '8px',
|
|
fontWeight: 'bold',
|
|
borderRadius: '2px',
|
|
fontFamily: 'monospace',
|
|
border: '1px solid #ddd'
|
|
}}
|
|
>
|
|
{this.getLanguageLabel(lang)}
|
|
</Box>
|
|
);
|
|
};
|
|
|
|
// Load flags when menu opens
|
|
componentDidUpdate(prevProps, prevState) {
|
|
const { anchorEl } = this.state;
|
|
const { languageContext } = this.props;
|
|
|
|
if (anchorEl && !prevState.anchorEl && languageContext) {
|
|
// 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);
|
|
}
|
|
});
|
|
}
|
|
}
|
|
|
|
getLanguageLabel = (lang) => {
|
|
const labels = {
|
|
'ar': 'EG',
|
|
'bg': 'BG',
|
|
'cs': 'CZ',
|
|
'de': 'DE',
|
|
'el': 'GR',
|
|
'en': 'US',
|
|
'es': 'ES',
|
|
'fr': 'FR',
|
|
'hr': 'HR',
|
|
'hu': 'HU',
|
|
'it': 'IT',
|
|
'pl': 'PL',
|
|
'ro': 'RO',
|
|
'ru': 'RU',
|
|
'sk': 'SK',
|
|
'sl': 'SI',
|
|
'sq': 'AL',
|
|
'sr': 'RS',
|
|
'sv': 'SE',
|
|
'tr': 'TR',
|
|
'uk': 'UA',
|
|
'zh': 'CN'
|
|
};
|
|
return labels[lang] || lang.toUpperCase();
|
|
};
|
|
|
|
getLanguageName = (lang) => {
|
|
const names = {
|
|
'ar': 'العربية',
|
|
'bg': 'Български',
|
|
'cs': 'Čeština',
|
|
'de': 'Deutsch',
|
|
'el': 'Ελληνικά',
|
|
'en': 'English',
|
|
'es': 'Español',
|
|
'fr': 'Français',
|
|
'hr': 'Hrvatski',
|
|
'hu': 'Magyar',
|
|
'it': 'Italiano',
|
|
'pl': 'Polski',
|
|
'ro': 'Română',
|
|
'ru': 'Русский',
|
|
'sk': 'Slovenčina',
|
|
'sl': 'Slovenščina',
|
|
'sq': 'Shqip',
|
|
'sr': 'Српски',
|
|
'sv': 'Svenska',
|
|
'tr': 'Türkçe',
|
|
'uk': 'Українська',
|
|
'zh': '中文'
|
|
};
|
|
return names[lang] || lang;
|
|
};
|
|
|
|
render() {
|
|
const { languageContext } = this.props;
|
|
const { anchorEl } = this.state;
|
|
|
|
if (!languageContext) {
|
|
return null;
|
|
}
|
|
|
|
const { currentLanguage, allLanguages } = languageContext;
|
|
const open = Boolean(anchorEl);
|
|
|
|
return (
|
|
<Box sx={{ display: 'flex', alignItems: 'center' }}>
|
|
<Button
|
|
aria-controls={open ? 'language-menu' : undefined}
|
|
aria-haspopup="true"
|
|
aria-expanded={open ? 'true' : undefined}
|
|
onClick={this.handleClick}
|
|
color="inherit"
|
|
size="small"
|
|
sx={{
|
|
my: 1,
|
|
mx: 0.5,
|
|
minWidth: 'auto',
|
|
textTransform: 'none',
|
|
fontSize: '0.875rem'
|
|
}}
|
|
>
|
|
{this.getLanguageLabel(currentLanguage)}
|
|
</Button>
|
|
<Menu
|
|
id="language-menu"
|
|
anchorEl={anchorEl}
|
|
open={open}
|
|
onClose={this.handleClose}
|
|
disableScrollLock={true}
|
|
MenuListProps={{
|
|
'aria-labelledby': 'language-button',
|
|
}}
|
|
anchorOrigin={{
|
|
vertical: 'bottom',
|
|
horizontal: 'right',
|
|
}}
|
|
transformOrigin={{
|
|
vertical: 'top',
|
|
horizontal: 'right',
|
|
}}
|
|
>
|
|
{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>
|
|
</MenuItem>
|
|
);
|
|
})}
|
|
</Menu>
|
|
</Box>
|
|
);
|
|
}
|
|
}
|
|
|
|
export default withI18n()(LanguageSwitcher);
|