This repository has been archived on 2025-11-17. You can view files and clone it, but cannot push or open issues or pull requests.
Files
pypages/static/components/LanguageSelector.js
2025-11-16 18:01:30 +01:00

135 lines
4.4 KiB
JavaScript

// Language Selector Component with Emojis
export class LanguageSelector {
constructor(onLanguageChange) {
this.onLanguageChange = onLanguageChange;
this.currentLang = '';
this.languages = [
{ code: '', name: 'English', emoji: '🇬🇧', native: 'English' },
{ code: 'de', name: 'German', emoji: '🇩🇪', native: 'Deutsch' },
{ code: 'fr', name: 'French', emoji: '🇫🇷', native: 'Français' },
{ code: 'es', name: 'Spanish', emoji: '🇪🇸', native: 'Español' },
{ code: 'it', name: 'Italian', emoji: '🇮🇹', native: 'Italiano' },
{ code: 'pt', name: 'Portuguese', emoji: '🇵🇹', native: 'Português' },
{ code: 'ru', name: 'Russian', emoji: '🇷🇺', native: 'Русский' }
];
this.init();
}
init() {
// Load saved language preference
const savedLang = localStorage.getItem('preferredLanguage') || '';
this.currentLang = savedLang;
this.createSelector();
}
createSelector() {
// Create floating language selector
const selector = document.createElement('div');
selector.className = 'language-selector';
selector.id = 'languageSelector';
const button = document.createElement('button');
button.className = 'language-selector-button';
button.setAttribute('aria-label', 'Select language');
button.setAttribute('aria-haspopup', 'true');
const currentLang = this.languages.find(lang => lang.code === this.currentLang) || this.languages[0];
button.innerHTML = `
<span class="language-emoji">${currentLang.emoji}</span>
<span class="language-name">${currentLang.native}</span>
<span class="language-arrow">▼</span>
`;
const dropdown = document.createElement('div');
dropdown.className = 'language-dropdown';
dropdown.id = 'languageDropdown';
this.languages.forEach(lang => {
const option = document.createElement('button');
option.className = `language-option ${lang.code === this.currentLang ? 'active' : ''}`;
option.dataset.code = lang.code;
option.innerHTML = `
<span class="language-emoji">${lang.emoji}</span>
<span class="language-name">${lang.native}</span>
<span class="language-name-en">${lang.name}</span>
`;
option.addEventListener('click', () => {
this.selectLanguage(lang.code);
dropdown.classList.remove('active');
});
dropdown.appendChild(option);
});
button.addEventListener('click', (e) => {
e.stopPropagation();
const isActive = dropdown.classList.contains('active');
dropdown.classList.toggle('active');
// Update arrow rotation
const arrow = button.querySelector('.language-arrow');
if (arrow) {
arrow.style.transform = isActive ? 'rotate(0deg)' : 'rotate(180deg)';
}
});
selector.appendChild(button);
selector.appendChild(dropdown);
// Store reference for arrow rotation
this.button = button;
this.dropdown = dropdown;
// Insert into content area (top right)
const content = document.getElementById('content');
if (content) {
content.insertBefore(selector, content.firstChild);
}
// Close dropdown when clicking outside
document.addEventListener('click', (e) => {
if (!selector.contains(e.target)) {
dropdown.classList.remove('active');
const arrow = button.querySelector('.language-arrow');
if (arrow) {
arrow.style.transform = 'rotate(0deg)';
}
}
});
}
selectLanguage(code) {
this.currentLang = code;
localStorage.setItem('preferredLanguage', code);
// Update button display
const currentLang = this.languages.find(lang => lang.code === code) || this.languages[0];
const button = document.querySelector('.language-selector-button');
if (button) {
button.innerHTML = `
<span class="language-emoji">${currentLang.emoji}</span>
<span class="language-name">${currentLang.native}</span>
<span class="language-arrow">▼</span>
`;
}
// Update active option
document.querySelectorAll('.language-option').forEach(option => {
if (option.dataset.code === code) {
option.classList.add('active');
} else {
option.classList.remove('active');
}
});
if (this.onLanguageChange) {
this.onLanguageChange(code);
}
}
getCurrentLanguage() {
return this.currentLang;
}
}