// 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;
}