new site
This commit is contained in:
@@ -0,0 +1,299 @@
|
||||
// Language Router - Multi-language URL management for Odoo Expertos
|
||||
// Supports: ES (default, no prefix), EN, DE, FR
|
||||
|
||||
const LanguageRouter = {
|
||||
// Supported languages with their configurations
|
||||
languages: {
|
||||
es: { code: 'es', name: 'Español', prefix: '', flag: '🇪🇸', hreflang: 'es' },
|
||||
en: { code: 'en', name: 'English', prefix: '/en', flag: '🇬🇧', hreflang: 'en' },
|
||||
de: { code: 'de', name: 'Deutsch', prefix: '/de', flag: '🇩🇪', hreflang: 'de' },
|
||||
fr: { code: 'fr', name: 'Français', prefix: '/fr', flag: '🇫🇷', hreflang: 'fr' },
|
||||
pt: { code: 'pt', name: 'Português', prefix: '/pt', flag: '🇧🇷', hreflang: 'pt' },
|
||||
ar: { code: 'ar', name: 'العربية', prefix: '/ar', flag: '🇸🇦', hreflang: 'ar', rtl: true }
|
||||
},
|
||||
|
||||
// Navigation labels per language
|
||||
navLabels: {
|
||||
es: { home: 'Inicio', odoo: 'Odoo', odooIA: 'Odoo IA', hosting: 'Hosting Odoo' },
|
||||
en: { home: 'Home', odoo: 'Odoo', odooIA: 'Odoo AI', hosting: 'Odoo Hosting' },
|
||||
de: { home: 'Startseite', odoo: 'Odoo', odooIA: 'Odoo KI', hosting: 'Odoo Hosting' },
|
||||
fr: { home: 'Accueil', odoo: 'Odoo', odooIA: 'Odoo IA', hosting: 'Hébergement Odoo' },
|
||||
pt: { home: 'Início', odoo: 'Odoo', odooIA: 'Odoo IA', hosting: 'Hospedagem Odoo' },
|
||||
ar: { home: 'الرئيسية', odoo: 'Odoo', odooIA: 'Odoo AI', hosting: 'استضافة Odoo' }
|
||||
},
|
||||
|
||||
// Footer labels per language
|
||||
footerLabels: {
|
||||
es: {
|
||||
contact: 'Contacto',
|
||||
quickLinks: 'Enlaces Rápidos',
|
||||
legal: 'Legal',
|
||||
modules: 'Módulos Odoo',
|
||||
benefits: 'Beneficios',
|
||||
community: 'Comunidad',
|
||||
legalNotice: 'Aviso Legal',
|
||||
privacy: 'Política de Privacidad',
|
||||
cookies: 'Política de Cookies',
|
||||
terms: 'Términos de Uso',
|
||||
copyright: 'Todos los derechos reservados.',
|
||||
experts: 'Expertos en soluciones Odoo ERP'
|
||||
},
|
||||
en: {
|
||||
contact: 'Contact',
|
||||
quickLinks: 'Quick Links',
|
||||
legal: 'Legal',
|
||||
modules: 'Odoo Modules',
|
||||
benefits: 'Benefits',
|
||||
community: 'Community',
|
||||
legalNotice: 'Legal Notice',
|
||||
privacy: 'Privacy Policy',
|
||||
cookies: 'Cookie Policy',
|
||||
terms: 'Terms of Use',
|
||||
copyright: 'All rights reserved.',
|
||||
experts: 'Odoo ERP Solutions Experts'
|
||||
},
|
||||
de: {
|
||||
contact: 'Kontakt',
|
||||
quickLinks: 'Schnelllinks',
|
||||
legal: 'Rechtliches',
|
||||
modules: 'Odoo Module',
|
||||
benefits: 'Vorteile',
|
||||
community: 'Community',
|
||||
legalNotice: 'Impressum',
|
||||
privacy: 'Datenschutzerklärung',
|
||||
cookies: 'Cookie-Richtlinie',
|
||||
terms: 'Nutzungsbedingungen',
|
||||
copyright: 'Alle Rechte vorbehalten.',
|
||||
experts: 'Odoo ERP Lösungsexperten'
|
||||
},
|
||||
fr: {
|
||||
contact: 'Contact',
|
||||
quickLinks: 'Liens Rapides',
|
||||
legal: 'Mentions Légales',
|
||||
modules: 'Modules Odoo',
|
||||
benefits: 'Avantages',
|
||||
community: 'Communauté',
|
||||
legalNotice: 'Mentions Légales',
|
||||
privacy: 'Politique de Confidentialité',
|
||||
cookies: 'Politique des Cookies',
|
||||
terms: "Conditions d'Utilisation",
|
||||
copyright: 'Tous droits réservés.',
|
||||
experts: 'Experts en solutions Odoo ERP'
|
||||
},
|
||||
pt: {
|
||||
contact: 'Contato',
|
||||
quickLinks: 'Links Rápidos',
|
||||
legal: 'Legal',
|
||||
modules: 'Módulos Odoo',
|
||||
benefits: 'Benefícios',
|
||||
community: 'Comunidade',
|
||||
legalNotice: 'Aviso Legal',
|
||||
privacy: 'Política de Privacidade',
|
||||
cookies: 'Política de Cookies',
|
||||
terms: 'Termos de Uso',
|
||||
copyright: 'Todos os direitos reservados.',
|
||||
experts: 'Especialistas em soluções Odoo ERP'
|
||||
},
|
||||
ar: {
|
||||
contact: 'اتصل بنا',
|
||||
quickLinks: 'روابط سريعة',
|
||||
legal: 'قانوني',
|
||||
modules: 'وحدات Odoo',
|
||||
benefits: 'المزايا',
|
||||
community: 'المجتمع',
|
||||
legalNotice: 'إشعار قانوني',
|
||||
privacy: 'سياسة الخصوصية',
|
||||
cookies: 'سياسة ملفات تعريف الارتباط',
|
||||
terms: 'شروط الاستخدام',
|
||||
copyright: 'جميع الحقوق محفوظة.',
|
||||
experts: 'خبراء حلول Odoo ERP'
|
||||
}
|
||||
},
|
||||
|
||||
// Detect current language from URL
|
||||
detectLanguage: function() {
|
||||
const path = window.location.pathname;
|
||||
if (path.startsWith('/en/') || path === '/en') return 'en';
|
||||
if (path.startsWith('/de/') || path === '/de') return 'de';
|
||||
if (path.startsWith('/fr/') || path === '/fr') return 'fr';
|
||||
if (path.startsWith('/pt/') || path === '/pt') return 'pt';
|
||||
if (path.startsWith('/ar/') || path === '/ar') return 'ar';
|
||||
return 'es'; // Default
|
||||
},
|
||||
|
||||
// Get current language config
|
||||
getCurrentLanguage: function() {
|
||||
const lang = this.detectLanguage();
|
||||
return this.languages[lang];
|
||||
},
|
||||
|
||||
// Get base path (without language prefix)
|
||||
getBasePath: function() {
|
||||
const path = window.location.pathname;
|
||||
const lang = this.detectLanguage();
|
||||
|
||||
if (lang === 'es') return path;
|
||||
|
||||
const prefix = this.languages[lang].prefix;
|
||||
if (path.startsWith(prefix)) {
|
||||
const basePath = path.substring(prefix.length);
|
||||
return basePath || '/';
|
||||
}
|
||||
return path;
|
||||
},
|
||||
|
||||
// Build URL for a specific language
|
||||
buildLanguageUrl: function(targetLang) {
|
||||
const basePath = this.getBasePath();
|
||||
const config = this.languages[targetLang];
|
||||
|
||||
if (targetLang === 'es') {
|
||||
return basePath;
|
||||
}
|
||||
|
||||
return config.prefix + (basePath === '/' ? '/' : basePath);
|
||||
},
|
||||
|
||||
// Generate all alternate URLs for hreflang
|
||||
getAlternateUrls: function() {
|
||||
const basePath = this.getBasePath();
|
||||
const baseUrl = 'https://odoo-expertos.com';
|
||||
const alternates = [];
|
||||
|
||||
Object.keys(this.languages).forEach(lang => {
|
||||
const config = this.languages[lang];
|
||||
let url;
|
||||
|
||||
if (lang === 'es') {
|
||||
url = baseUrl + basePath;
|
||||
} else {
|
||||
url = baseUrl + config.prefix + (basePath === '/' ? '/' : basePath);
|
||||
}
|
||||
|
||||
alternates.push({
|
||||
lang: config.hreflang,
|
||||
url: url
|
||||
});
|
||||
});
|
||||
|
||||
// Add x-default (Spanish)
|
||||
alternates.push({
|
||||
lang: 'x-default',
|
||||
url: baseUrl + basePath
|
||||
});
|
||||
|
||||
return alternates;
|
||||
},
|
||||
|
||||
// Generate hreflang link tags HTML
|
||||
generateHreflangTags: function() {
|
||||
const alternates = this.getAlternateUrls();
|
||||
return alternates.map(alt =>
|
||||
`<link rel="alternate" hreflang="${alt.lang}" href="${alt.url}" />`
|
||||
).join('\n ');
|
||||
},
|
||||
|
||||
// Inject hreflang tags into document head
|
||||
injectHreflangTags: function() {
|
||||
// Remove existing hreflang tags
|
||||
document.querySelectorAll('link[hreflang]').forEach(el => el.remove());
|
||||
|
||||
const alternates = this.getAlternateUrls();
|
||||
alternates.forEach(alt => {
|
||||
const link = document.createElement('link');
|
||||
link.rel = 'alternate';
|
||||
link.hreflang = alt.lang;
|
||||
link.href = alt.url;
|
||||
document.head.appendChild(link);
|
||||
});
|
||||
},
|
||||
|
||||
// Get navigation labels for current language
|
||||
getNavLabels: function() {
|
||||
const lang = this.detectLanguage();
|
||||
return this.navLabels[lang];
|
||||
},
|
||||
|
||||
// Get footer labels for current language
|
||||
getFooterLabels: function() {
|
||||
const lang = this.detectLanguage();
|
||||
return this.footerLabels[lang];
|
||||
},
|
||||
|
||||
// Get link prefix for current language
|
||||
getLinkPrefix: function() {
|
||||
const lang = this.detectLanguage();
|
||||
return this.languages[lang].prefix;
|
||||
},
|
||||
|
||||
// Switch to another language
|
||||
switchLanguage: function(targetLang) {
|
||||
const newUrl = this.buildLanguageUrl(targetLang);
|
||||
window.location.href = newUrl;
|
||||
},
|
||||
|
||||
// Create language switcher HTML
|
||||
createLanguageSwitcher: function() {
|
||||
const currentLang = this.detectLanguage();
|
||||
const currentConfig = this.languages[currentLang];
|
||||
|
||||
let dropdownItems = '';
|
||||
Object.keys(this.languages).forEach(lang => {
|
||||
const config = this.languages[lang];
|
||||
const isActive = lang === currentLang ? ' active' : '';
|
||||
const url = this.buildLanguageUrl(lang);
|
||||
dropdownItems += `
|
||||
<a href="${url}" class="lang-option${isActive}" data-lang="${lang}">
|
||||
<span class="lang-flag">${config.flag}</span>
|
||||
<span class="lang-name">${config.name}</span>
|
||||
</a>`;
|
||||
});
|
||||
|
||||
return `
|
||||
<div class="language-switcher">
|
||||
<button class="lang-toggle" aria-label="Select language">
|
||||
<span class="lang-flag">${currentConfig.flag}</span>
|
||||
<span class="lang-code">${currentLang.toUpperCase()}</span>
|
||||
<svg class="lang-arrow" width="12" height="12" viewBox="0 0 12 12" fill="currentColor">
|
||||
<path d="M2 4L6 8L10 4" stroke="currentColor" stroke-width="2" fill="none"/>
|
||||
</svg>
|
||||
</button>
|
||||
<div class="lang-dropdown">
|
||||
${dropdownItems}
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
},
|
||||
|
||||
// Initialize language switcher functionality
|
||||
initLanguageSwitcher: function() {
|
||||
document.addEventListener('click', (e) => {
|
||||
const toggle = e.target.closest('.lang-toggle');
|
||||
const switcher = document.querySelector('.language-switcher');
|
||||
|
||||
if (toggle) {
|
||||
e.preventDefault();
|
||||
switcher.classList.toggle('open');
|
||||
} else if (!e.target.closest('.language-switcher')) {
|
||||
if (switcher) switcher.classList.remove('open');
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
// Initialize all language features
|
||||
init: function() {
|
||||
this.injectHreflangTags();
|
||||
this.initLanguageSwitcher();
|
||||
|
||||
// Set html lang attribute
|
||||
const lang = this.detectLanguage();
|
||||
document.documentElement.lang = lang;
|
||||
}
|
||||
};
|
||||
|
||||
// Auto-initialize when DOM is ready
|
||||
if (document.readyState === 'loading') {
|
||||
document.addEventListener('DOMContentLoaded', () => LanguageRouter.init());
|
||||
} else {
|
||||
LanguageRouter.init();
|
||||
}
|
||||
Reference in New Issue
Block a user