// Comprehensive Language switching functionality for M2 Marketing website let currentLanguage = 'fi'; // Default to Finnish since the website is now in Finnish let languageEventListeners = []; let navigationEventListeners = []; // English translations (reverse mapping since we're starting with Finnish) const englishTranslations = { // Header Navigation 'Koti': 'Home', 'Palvelut': 'Services', 'Meistä': 'About', 'Arvostelut': 'Reviews', 'Yhteystiedot': 'Contact', 'Aloita': 'Get Started', 'Elite Markkinointi': 'Elite Marketing', 'Premium sosiaalisen median strategiat': 'Premium social media strategies', 'Verkkosivuratkaisut': 'Web Solutions', 'Luksus verkkosivujen kehitys': 'Luxury website development', 'Katso kaikki palvelut': 'View All Services', 'Kaikki palvelut': 'All Services', 'Kieli': 'Language', 'Englanti': 'English', 'Suomi': 'Finnish', // Common CTA and buttons 'Varaa ilmainen konsultaatio': 'Book Free Consultation', 'Aloita projektisi': 'Start Your Project', 'Ota yhteyttä tänään': 'Contact Us Today', 'Pyydä ilmainen tarjous': 'Get Free Quote', 'Lue lisää': 'Learn More', 'Katso portfolio': 'View Portfolio', 'Varaa nyt': 'Book Now', 'Soita nyt': 'Call Now', 'Lähetä sähköposti': 'Send Email', 'Katso menestystarinat': 'View Success Stories', 'Hanki ilmainen strategiakeskustelu': 'Get Your Free Strategy Call', 'Varaa konsultaatio': 'Schedule Consultation', 'Pyydä tarjous': 'Get Quote', 'Ota yhteyttä': 'Contact Us', // Home page hero content 'Kasvata liiketoimintaasi': 'Grow Your Business with', 'Elite digitaalisella markkinoinnilla': 'Elite Digital Marketing', 'Muuta brändisi kattavilla digitaalisen markkinoinnin ratkaisuillamme. Sosiaalisen median hallinnasta premium verkkosivujen kehitykseen, toimitamme tuloksia, jotka merkitsevät.': 'Transform your brand with our comprehensive digital marketing solutions. From social media management to premium website development, we deliver results that matter.', 'Digitaalisen markkinoinnin asiantuntijat': 'Digital Marketing Experts', 'Tuloshakuniset ratkaisut': 'Results-Driven Solutions', // Services section 'Palvelumme': 'Our Services', 'Mitä tarjoamme': 'What We Offer', 'Sosiaalisen median markkinointi': 'Social Media Marketing', 'Strategiset sosiaalisen median kampanjat, jotka rakentavat bränditietoisuutta, sitouttavat yleisöä ja lisäävät konversioita kaikilla alustoilla.': 'Strategic social media campaigns that build brand awareness, engage audiences, and drive conversions across all platforms.', 'Verkkosivujen kehitys': 'Website Development', 'Mukautetut, responsiiviset verkkosivut, jotka lumoavat vierailijat ja muuttavat heidät asiakkaiksi. Rakennettu suorituskyvylle ja optimoitu hakukoneille.': 'Custom, responsive websites that captivate visitors and convert them into customers. Built for performance and optimized for search.', 'Brändistrategia': 'Brand Strategy', 'Täydellinen brändi-identiteetin kehitys, joka resonoi kohdeyleisösi kanssa ja erottaa sinut kilpailijoista.': 'Complete brand identity development that resonates with your target audience and sets you apart from competitors.', 'Digitaalinen konsultointi': 'Digital Consulting', 'Asiantuntevaa ohjausta digitaalisen muutoksen strategioihin': 'Expert guidance on digital transformation strategies', 'Sisällöntuotanto': 'Content Creation', 'Ammattimaista sisältöä, joka sitouttaa ja muuntaa': 'Professional content that engages and converts', 'SEO-palvelut': 'SEO Services', 'Hakukoneoptimointi parempaa näkyvyyttä varten': 'Search engine optimization for better visibility', // About section 'Miksi valita M2 Marketing?': 'Why Choose M2 Marketing?', 'Todistetut tulokset': 'Proven Results', 'Asiantuntijatiimi': 'Expert Team', 'Henkilökohtainen palvelu': 'Personal Service', // Contact section 'Valmis aloittamaan?': 'Ready to Get Started?', 'Lähetä viesti': 'Send Message', 'Puhelin': 'Phone', 'Sähköposti': 'Email', 'Osoite': 'Address', 'Kalajoki, Suomi': 'Kalajoki, Finland', // Footer 'Pikalinkit': 'Quick Links', 'Seuraa meitä': 'Follow Us', 'Tilaa': 'Subscribe', 'Syötä sähköpostiosoitteesi': 'Enter your email address' }; // Finnish translations (for switching from English to Finnish) const finnishTranslations = {}; Object.entries(englishTranslations).forEach(([finnish, english]) => { finnishTranslations[english] = finnish; }); function translatePage() { // Store original texts if not already stored if (!window.originalTexts) { window.originalTexts = new Map(); } // More comprehensive text element selection const textElements = document.querySelectorAll('h1, h2, h3, h4, h5, h6, p, span, a, button, div, li, td, th, label, legend, caption'); textElements.forEach(element => { const text = element.textContent.trim(); // Skip empty elements, elements with only numbers/symbols, or elements that contain other elements if (!text || element.children.length > 0 || /^[\d\s\-\+\(\)\[\]]+$/.test(text)) return; // Store original text if not stored if (!window.originalTexts.has(element)) { window.originalTexts.set(element, text); } if (currentLanguage === 'en' && englishTranslations[text]) { element.textContent = englishTranslations[text]; } else if (currentLanguage === 'fi' && finnishTranslations[text]) { element.textContent = finnishTranslations[text]; } }); // Translate placeholders and input labels const inputElements = document.querySelectorAll('input[placeholder], textarea[placeholder], input[title], textarea[title]'); inputElements.forEach(element => { // Handle placeholders if (element.placeholder) { const placeholder = element.getAttribute('data-original-placeholder') || element.placeholder; if (!element.getAttribute('data-original-placeholder')) { element.setAttribute('data-original-placeholder', placeholder); } if (currentLanguage === 'en' && englishTranslations[placeholder]) { element.placeholder = englishTranslations[placeholder]; } else if (currentLanguage === 'fi' && finnishTranslations[placeholder]) { element.placeholder = finnishTranslations[placeholder]; } } // Handle titles if (element.title) { const title = element.getAttribute('data-original-title') || element.title; if (!element.getAttribute('data-original-title')) { element.setAttribute('data-original-title', title); } if (currentLanguage === 'en' && englishTranslations[title]) { element.title = englishTranslations[title]; } else if (currentLanguage === 'fi' && finnishTranslations[title]) { element.title = finnishTranslations[title]; } } }); // Update language switcher display const langSwitchers = document.querySelectorAll('header .group button span'); langSwitchers.forEach(span => { if (span.textContent === 'EN' || span.textContent === 'FI') { span.textContent = currentLanguage === 'fi' ? 'FI' : 'EN'; } }); // Translate alt attributes for images const images = document.querySelectorAll('img[alt]'); images.forEach(img => { const altText = img.getAttribute('data-original-alt') || img.alt; if (!img.getAttribute('data-original-alt')) { img.setAttribute('data-original-alt', altText); } if (currentLanguage === 'en' && englishTranslations[altText]) { img.alt = englishTranslations[altText]; } else if (currentLanguage === 'fi' && finnishTranslations[altText]) { img.alt = finnishTranslations[altText]; } }); // Save language preference localStorage.setItem('selectedLanguage', currentLanguage); console.log('Page translated to:', currentLanguage); } function switchLanguage(lang) { console.log('Switching language to:', lang); currentLanguage = lang; translatePage(); } function handleLanguageClick(event) { event.preventDefault(); console.log('Language button clicked:', event.currentTarget.textContent); const button = event.currentTarget; const isEnglish = button.textContent.includes('English') || button.textContent.includes('Englanti'); switchLanguage(isEnglish ? 'en' : 'fi'); } function setupLanguageSwitcher() { console.log('Setting up language switcher...'); // Clean up existing listeners languageEventListeners.forEach(cleanup => cleanup()); languageEventListeners = []; // Desktop and mobile language buttons const langButtons = document.querySelectorAll('header button, [data-landingsite-mobile-menu] button'); langButtons.forEach(button => { const buttonText = button.textContent.toLowerCase(); if (buttonText.includes('english') || buttonText.includes('englanti') || buttonText.includes('suomi') || buttonText.includes('finnish')) { console.log('Adding listener to language button:', button.textContent); button.addEventListener('click', handleLanguageClick); languageEventListeners.push(() => button.removeEventListener('click', handleLanguageClick)); } }); console.log('Language switcher setup complete. Total listeners:', languageEventListeners.length); } function loadSavedLanguage() { const savedLang = localStorage.getItem('selectedLanguage'); console.log('Loading saved language:', savedLang); if (savedLang && savedLang !== currentLanguage) { currentLanguage = savedLang; // Immediate translation for saved language setTimeout(() => { translatePage(); }, 200); } } // Navigation functionality function smoothScrollToSection(targetId) { const targetElement = document.querySelector(`[data-anchor-id="${targetId}"]`) || document.getElementById(targetId); if (targetElement) { targetElement.scrollIntoView({ behavior: 'smooth', block: 'start' }); return true; } return false; } function handleNavigationClick(event) { const link = event.currentTarget; const href = link.getAttribute('href'); console.log('Navigation clicked:', href); // Handle hash links for same-page navigation if (href && href.startsWith('#')) { event.preventDefault(); const targetId = href.substring(1); // Try to scroll to section with matching data-anchor-id or id const scrolled = smoothScrollToSection(targetId); // If section not found on current page, navigate to appropriate page if (!scrolled) { if (targetId === 'testimonials') { window.location.href = '/testimonials'; } else if (targetId === 'services') { window.location.href = '/services'; } } // Close mobile menu after navigation const mobileMenu = document.querySelector('[data-landingsite-mobile-menu]'); if (mobileMenu && !mobileMenu.classList.contains('hidden')) { mobileMenu.classList.add('hidden'); const menuButton = document.querySelector('[data-landingsite-mobile-menu-toggle]'); if (menuButton) { menuButton.setAttribute('aria-expanded', 'false'); } } } } function setupNavigation() { console.log('Setting up navigation...'); // Clean up existing listeners navigationEventListeners.forEach(cleanup => cleanup()); navigationEventListeners = []; // Setup navigation links in header and mobile menu const navLinks = document.querySelectorAll('header a[href^="#"], [data-landingsite-mobile-menu] a[href^="#"]'); navLinks.forEach(link => { const href = link.getAttribute('href'); console.log('Adding navigation listener to:', href); link.addEventListener('click', handleNavigationClick); navigationEventListeners.push(() => link.removeEventListener('click', handleNavigationClick)); }); console.log('Navigation setup complete. Total listeners:', navigationEventListeners.length); } function init() { console.log('Initializing language and navigation system...'); // Load saved language preference first loadSavedLanguage(); // Setup language switcher and navigation with delay to ensure DOM is ready setTimeout(() => { setupLanguageSwitcher(); setupNavigation(); }, 500); // Set up observer for dynamic content changes const observer = new MutationObserver(function(mutations) { let shouldSetup = false; mutations.forEach(function(mutation) { if (mutation.type === 'childList' && mutation.addedNodes.length > 0) { mutation.addedNodes.forEach(node => { if (node.nodeType === Node.ELEMENT_NODE) { shouldSetup = true; } }); } }); if (shouldSetup) { setTimeout(() => { setupLanguageSwitcher(); setupNavigation(); translatePage(); }, 300); } }); observer.observe(document.body, { childList: true, subtree: true }); // Make language switcher globally available window.LanguageSwitcher = { switchLanguage: switchLanguage, currentLanguage: () => currentLanguage, translatePage: translatePage }; console.log('Language and navigation system initialized successfully'); } function teardown() { console.log('Tearing down language and navigation system...'); // Clean up event listeners languageEventListeners.forEach(cleanup => cleanup()); languageEventListeners = []; navigationEventListeners.forEach(cleanup => cleanup()); navigationEventListeners = []; } export { init, teardown };