/** * Utilitários de rotas e navegação internacionalizada. * Módulo puro (sem 'use client') seguro para Server e Client Components. */ // Ponto único de configuração de idiomas ATIVOS. // Para ativar um novo idioma no site, basta adicionar seu código aqui (ex.: ["pt", "en"]). export const ENABLED_LOCALES = ["pt", "en"]; export const ALL_LOCALES = [ { code: "pt", label: "Português", short: "PT", lang: "pt-BR", og: "pt_BR" }, { code: "en", label: "English", short: "EN", lang: "en", og: "en_US" }, { code: "es", label: "Español", short: "ES", lang: "es-419", og: "es_419" }, { code: "fr", label: "Français", short: "FR", lang: "fr", og: "fr_FR" }, { code: "de", label: "Deutsch", short: "DE", lang: "de", og: "de_DE" }, { code: "zh-CN", label: "简体中文", short: "中", lang: "zh-CN", og: "zh_CN" }, ]; export const ALL_LOCALE_CODES = ALL_LOCALES.map((l) => l.code); export const LOCALES = ALL_LOCALES.filter((l) => ENABLED_LOCALES.includes(l.code)); export const CANONICAL_ROUTES = [ { id: "series_item", match: /^(?:\/(?:pt|en|es|fr|de|zh-CN))?\/(?:series|serien)\/([^/?#]+)/, getSlug: (loc, key) => (loc === "de" ? `/serien/${key}` : `/series/${key}`), }, { id: "frameworks_item", match: /^(?:\/(?:pt|en|es|fr|de|zh-CN))?\/frameworks\/([^/?#]+)/, getSlug: (loc, key) => `/frameworks/${key}`, }, { id: "series", match: /^(?:\/(?:pt|en|es|fr|de|zh-CN))?\/(?:series|serien)(?:\/|$)/, getSlug: (loc) => (loc === "de" ? "/serien" : "/series"), }, { id: "catalogo", match: /^(?:\/(?:pt|en|es|fr|de|zh-CN))?\/(?:catalogo|catalog|catalogue|katalog)(?:\/|$)/, getSlug: (loc) => { if (loc === "de") return "/katalog"; if (loc === "fr") return "/catalogue"; if (loc === "en" || loc === "zh-CN") return "/catalog"; return "/catalogo"; }, }, { id: "comparacao", match: /^(?:\/(?:pt|en|es|fr|de|zh-CN))?\/(?:comparacao|compare|comparacion|comparaison|vergleich)(?:\/|$)/, getSlug: (loc) => { if (loc === "en" || loc === "zh-CN") return "/compare"; if (loc === "es") return "/comparacion"; if (loc === "fr") return "/comparaison"; if (loc === "de") return "/vergleich"; return "/comparacao"; }, }, { id: "componentes", match: /^(?:\/(?:pt|en|es|fr|de|zh-CN))?\/(?:componentes|components|composants|komponenten)(?:\/|$)/, getSlug: (loc) => { if (loc === "en" || loc === "zh-CN") return "/components"; if (loc === "fr") return "/composants"; if (loc === "de") return "/komponenten"; return "/componentes"; }, }, { id: "diagnostico", match: /^(?:\/(?:pt|en|es|fr|de|zh-CN))?\/(?:diagnostico|diagnostics|diagnostic|diagnose)(?:\/|$)/, getSlug: (loc) => { if (loc === "en" || loc === "zh-CN") return "/diagnostics"; if (loc === "fr") return "/diagnostic"; if (loc === "de") return "/diagnose"; return "/diagnostico"; }, }, { id: "frameworks", match: /^(?:\/(?:pt|en|es|fr|de|zh-CN))?\/frameworks(?:\/|$)/, getSlug: () => "/frameworks", }, { id: "glossario", match: /^(?:\/(?:pt|en|es|fr|de|zh-CN))?\/(?:glossario|glossary|glosario|glossaire|glossar)(?:\/|$)/, getSlug: (loc) => { if (loc === "en" || loc === "zh-CN") return "/glossary"; if (loc === "es") return "/glosario"; if (loc === "fr") return "/glossaire"; if (loc === "de") return "/glossar"; return "/glossario"; }, }, { id: "seletor", match: /^(?:\/(?:pt|en|es|fr|de|zh-CN))?\/(?:seletor|selector|selecteur|auswahl)(?:\/|$)/, getSlug: (loc) => { if (loc === "en" || loc === "es" || loc === "zh-CN") return "/selector"; if (loc === "fr") return "/selecteur"; if (loc === "de") return "/auswahl"; return "/seletor"; }, }, { id: "sobre", match: /^(?:\/(?:pt|en|es|fr|de|zh-CN))?\/(?:sobre|about|acerca|a-propos|ueber-uns)(?:\/|$)/, getSlug: (loc) => { if (loc === "en" || loc === "zh-CN") return "/about"; if (loc === "es") return "/acerca"; if (loc === "fr") return "/a-propos"; if (loc === "de") return "/ueber-uns"; return "/sobre"; }, }, { id: "livro", match: /^(?:\/(?:pt|en|es|fr|de|zh-CN))?\/livro(?:\/|$)/, getSlug: (loc) => (loc === "pt" ? "/livro" : ""), }, ]; export function getLocalizedHref(pathname, targetLocale) { if (!pathname || pathname === "/") { return `/${targetLocale}`; } const [cleanPath, ...queryParts] = pathname.split("?"); const query = queryParts.length > 0 ? `?${queryParts.join("?")}` : ""; for (const loc of ALL_LOCALE_CODES) { if (cleanPath === `/${loc}` || cleanPath === `/${loc}/`) { return `/${targetLocale}${query}`; } } for (const route of CANONICAL_ROUTES) { const m = cleanPath.match(route.match); if (m) { const slug = route.getSlug(targetLocale, m[1]); return slug ? `/${targetLocale}${slug}${query}` : `/${targetLocale}${query}`; } } return `/${targetLocale}${query}`; } export function getPtPath(pathname) { return getLocalizedHref(pathname, "pt"); }