import type { Lang } from '@/lib/i18n' /** * Zentrale Sprach-Architektur. * * `routeGroups`: echte Übersetzungspaare. Sie steuern den Sprachumschalter * UND erzeugen die hreflang-Alternates in der Metadata. * * `fuzzyTargets`: thematisch nächstliegende Seite, wenn es keine echte * Übersetzung gibt. Nur der Umschalter nutzt sie — hreflang ignoriert sie, * damit Google keine falschen Übersetzungspaare gemeldet bekommt. * * Neue Subpage? Echte Übersetzung in routeGroups eintragen, sonst * fuzzyTargets ergänzen (oder weglassen, dann geht's zur Locale-Startseite). */ const routeGroups: Partial>[] = [ { de: '/', en: '/en', es: '/es' }, { de: '/pflanzen-erkennen-app', en: '/plant-identifier-app', es: '/es/identificador-de-plantas' }, { de: '/blumen-scanner', en: '/flower-scanner' }, { de: '/pflanzen-bestimmen', en: '/identify-plant-photo' }, { de: '/zimmerpflanzen-bestimmen', en: '/houseplant-identifier' }, { de: '/pflanzen-pflege-app', en: '/plant-care-app', es: '/es/app-para-cuidar-plantas' }, { de: '/pflanzen-krankheiten-erkennen', en: '/plant-disease-identifier', es: '/es/diagnosticar-enfermedades-plantas' }, { de: '/pflanzen-erkennen-kostenlos', en: '/best-plant-identification-app' }, { en: '/plant-scanner', es: '/es/escaner-de-plantas' }, { de: '/vs/google-lens', es: '/es/comparar/google-lens' }, // Ratgeber-Cluster: deutsche SEO-Seite und englischer Blogpost sind echte // Übersetzungspaare, auch wenn die Templates unterschiedlich sind. { de: '/giessplan-zimmerpflanzen', en: '/blog/houseplant-watering-schedule' }, { de: '/pflanzen-diagnose', en: '/blog/plant-health-diagnosis-guide' }, { de: '/welche-pflanze-ist-das', en: '/blog/which-plant-is-this-guide' }, ] const fuzzyTargets: Record>> = { '/blumen-scanner': { es: '/es/escaner-de-plantas' }, '/flower-scanner': { es: '/es/escaner-de-plantas' }, '/plant-scanner': { de: '/blumen-scanner' }, '/pflanzen-bestimmen': { es: '/es/identificador-de-plantas' }, '/identify-plant-photo': { es: '/es/identificador-de-plantas' }, '/zimmerpflanzen-bestimmen': { es: '/es/identificador-de-plantas' }, '/houseplant-identifier': { es: '/es/identificador-de-plantas' }, '/pflanzen-erkennen-kostenlos': { es: '/es/identificador-de-plantas' }, '/best-plant-identification-app': { es: '/es/identificador-de-plantas' }, '/giess-erinnerung-app': { en: '/plant-care-app', es: '/es/app-para-cuidar-plantas' }, '/plant-health-app': { de: '/pflanzen-krankheiten-erkennen', es: '/es/diagnosticar-enfermedades-plantas' }, '/succulent-identifier': { de: '/zimmerpflanzen-bestimmen', es: '/es/identificador-de-plantas' }, '/es/escaner-de-plantas': { de: '/blumen-scanner' }, '/es/identificador-de-plantas': { de: '/pflanzen-erkennen-app' }, '/vs/picturethis': { de: '/pflanzen-erkennen-app', es: '/es/identificador-de-plantas' }, '/vs/plantum': { de: '/pflanzen-erkennen-app', es: '/es/identificador-de-plantas' }, '/vs/inaturalist': { de: '/pflanzen-erkennen-app', es: '/es/identificador-de-plantas' }, } /** Seiten, die in allen Sprachen unter derselben URL leben (Client-Übersetzung). */ const sharedPaths = new Set(['/support', '/imprint', '/privacy', '/terms']) export const localeHome: Record = { de: '/', en: '/en', es: '/es' } const englishPaths = new Set([ '/en', '/best-plant-identification-app', '/plant-identifier-app', '/plant-scanner', '/flower-scanner', '/houseplant-identifier', '/succulent-identifier', '/identify-plant-photo', '/plant-disease-identifier', '/plant-health-app', '/plant-care-app', ]) export function getLocaleForPath(pathname: string): Lang { if (pathname === '/es' || pathname.startsWith('/es/')) return 'es' if (pathname === '/vs/google-lens') return 'de' if (englishPaths.has(pathname) || pathname.startsWith('/vs/') || pathname.startsWith('/blog')) return 'en' return 'de' } function findGroup(pathname: string): Partial> | undefined { return routeGroups.find((group) => Object.values(group).includes(pathname)) } /** Ziel-URL beim Sprachwechsel: Übersetzung, thematischer Fallback oder Locale-Home. */ export function getAlternatePath(pathname: string, target: Lang): string { if (sharedPaths.has(pathname)) return pathname if (getLocaleForPath(pathname) === target) return pathname return findGroup(pathname)?.[target] ?? fuzzyTargets[pathname]?.[target] ?? localeHome[target] } /** hreflang-Alternates für die Metadata einer Seite (nur echte Übersetzungen). */ export function getHreflangAlternates(pathname: string): Record | undefined { const group = findGroup(pathname) if (!group || Object.keys(group).length < 2) return undefined return { ...(group.de && { de: group.de }), ...(group.en && { en: group.en }), ...(group.es && { es: group.es }), 'x-default': group.de ?? group.en ?? '/', } }