// Static Internationalization system for GoodMeal landing pages class StaticI18n { constructor() { this.supportedLanguages = ['uk', 'en']; this.currentLanguage = this.detectLanguage(); this.init(); } init() { this.setupLanguageSelector(); this.updateNavigationLinks(); this.setCanonicalAndHreflang(); this.saveLanguagePreference(); } detectLanguage() { // Get language from URL path const pathSegments = window.location.pathname.split('/').filter(segment => segment); const urlLanguage = pathSegments[0]; if (this.supportedLanguages.includes(urlLanguage)) { return urlLanguage; } // Default to Ukrainian if no language detected return 'uk'; } saveLanguagePreference() { localStorage.setItem('goodmeal-language', this.currentLanguage); } setupLanguageSelector() { // Check if language selector already exists to prevent duplicates if (document.querySelector('.language-selector')) { return; } // Get current language flag and name const languageData = { 'uk': { flag: '🇺🇦', name: 'Українська' }, 'en': { flag: '🇺🇸', name: 'English' } }; const currentLangData = languageData[this.currentLanguage]; // Create desktop language selector HTML const desktopLanguageSelector = document.createElement('div'); desktopLanguageSelector.className = 'language-selector'; desktopLanguageSelector.innerHTML = `
`; // Add to header navigation const header = document.querySelector('header .nav-container'); if (header) { header.appendChild(desktopLanguageSelector); } // Create separate mobile language selector const mobileNav = document.querySelector('.menu-modal nav'); if (mobileNav) { const mobileLanguageSelector = document.createElement('div'); mobileLanguageSelector.className = 'language-selector mobile-language-selector'; mobileLanguageSelector.innerHTML = `
`; mobileNav.appendChild(mobileLanguageSelector); } // Setup event listeners this.setupLanguageSelectorEvents(); } setupLanguageSelectorEvents() { document.addEventListener('click', (e) => { // Toggle dropdown if (e.target.closest('.language-toggle')) { e.preventDefault(); const dropdown = e.target.closest('.language-dropdown'); // Close all other dropdowns first document.querySelectorAll('.language-dropdown').forEach(otherDropdown => { if (otherDropdown !== dropdown) { otherDropdown.classList.remove('active'); } }); dropdown.classList.toggle('active'); e.stopPropagation(); } // Select language else if (e.target.closest('.language-option')) { e.preventDefault(); const option = e.target.closest('.language-option'); const selectedLang = option.dataset.lang; if (selectedLang && selectedLang !== this.currentLanguage) { this.changeLanguage(selectedLang); } e.stopPropagation(); } // Close dropdown when clicking outside else { document.querySelectorAll('.language-dropdown').forEach(dropdown => { dropdown.classList.remove('active'); }); } }); // Close dropdown on escape key document.addEventListener('keydown', (e) => { if (e.key === 'Escape') { document.querySelectorAll('.language-dropdown').forEach(dropdown => { dropdown.classList.remove('active'); }); } }); // Prevent form submission if language selector is inside a form document.addEventListener('submit', (e) => { if (e.target.closest('.language-selector')) { e.preventDefault(); } }); } changeLanguage(newLanguage) { if (!this.supportedLanguages.includes(newLanguage) || newLanguage === this.currentLanguage) { return; } // Save to localStorage localStorage.setItem('goodmeal-language', newLanguage); // Get current page name const currentPath = window.location.pathname; const pathSegments = currentPath.split('/').filter(segment => segment); // Remove current language prefix if present if (this.supportedLanguages.includes(pathSegments[0])) { pathSegments.shift(); } // Get page name (default to index.html if root) const pageName = pathSegments.length > 0 ? pathSegments[pathSegments.length - 1] : 'index.html'; // Create new URL with selected language const newUrl = `/${newLanguage}/${pageName}${window.location.search}${window.location.hash}`; // Navigate to new URL window.location.href = newUrl; } updateNavigationLinks() { // Update all internal links to include current language prefix document.querySelectorAll('a[href]').forEach(link => { const href = link.getAttribute('href'); // Skip external links, anchors, and already prefixed links if (href.startsWith('http') || href.startsWith('#') || href.startsWith('mailto:') || href.startsWith('tel:')) { return; } // Skip if already has language prefix if (href.startsWith('/uk/') || href.startsWith('/en/') || href.startsWith('../')) { return; } // Update relative links to include language prefix if (href.endsWith('.html') || href === '/' || !href.includes('.')) { let newHref; if (href === '/') { newHref = `/${this.currentLanguage}/index.html`; } else if (href.startsWith('./')) { newHref = href.substring(2); } else { newHref = href; } // Don't add language prefix if we're already in a language directory if (!window.location.pathname.includes(`/${this.currentLanguage}/`)) { link.setAttribute('href', `/${this.currentLanguage}/${newHref}`); } } }); } setCanonicalAndHreflang() { // Get current page name const currentPath = window.location.pathname; const pathSegments = currentPath.split('/').filter(segment => segment); // Remove language prefix to get page name if (this.supportedLanguages.includes(pathSegments[0])) { pathSegments.shift(); } const pageName = pathSegments.length > 0 ? pathSegments.join('/') : 'index.html'; const baseUrl = window.location.origin; // Set canonical URL for current language let canonical = document.querySelector('link[rel="canonical"]'); if (!canonical) { canonical = document.createElement('link'); canonical.rel = 'canonical'; document.head.appendChild(canonical); } canonical.href = `${baseUrl}/${this.currentLanguage}/${pageName}`; // Remove existing hreflang tags document.querySelectorAll('link[rel="alternate"][hreflang]').forEach(link => { link.remove(); }); // Add hreflang tags for all supported languages this.supportedLanguages.forEach(lang => { const hreflang = document.createElement('link'); hreflang.rel = 'alternate'; hreflang.hreflang = lang; hreflang.href = `${baseUrl}/${lang}/${pageName}`; document.head.appendChild(hreflang); }); // Add x-default hreflang pointing to Ukrainian version const xDefault = document.createElement('link'); xDefault.rel = 'alternate'; xDefault.hreflang = 'x-default'; xDefault.href = `${baseUrl}/uk/${pageName}`; document.head.appendChild(xDefault); } // Helper method to redirect user to their preferred language on landing static redirectToPreferredLanguage() { const currentPath = window.location.pathname; const pathSegments = currentPath.split('/').filter(segment => segment); const urlLanguage = pathSegments[0]; const supportedLanguages = ['uk', 'en']; // If already on a language-specific URL, do nothing if (supportedLanguages.includes(urlLanguage)) { return; } // If on root or a page without language prefix, redirect to preferred language const savedLanguage = localStorage.getItem('goodmeal-language') || 'uk'; const pageName = currentPath === '/' ? 'index.html' : currentPath.substring(1); const newUrl = `/${savedLanguage}/${pageName}${window.location.search}${window.location.hash}`; window.location.replace(newUrl); } // Get current language getCurrentLanguage() { return this.currentLanguage; } } // Initialize on DOM load document.addEventListener('DOMContentLoaded', () => { window.staticI18n = new StaticI18n(); }); // Auto-redirect from root pages to language-specific versions if (typeof module === 'undefined') { // Only run redirect logic if not in a module environment const pathSegments = window.location.pathname.split('/').filter(segment => segment); const supportedLanguages = ['uk', 'en']; if (pathSegments.length === 0 || !supportedLanguages.includes(pathSegments[0])) { // We're on a root page or non-language page, redirect to language version StaticI18n.redirectToPreferredLanguage(); } } // Export for use in other scripts if (typeof module !== 'undefined' && module.exports) { module.exports = StaticI18n; }