"use client"; import { useEffect, useRef, useState } from "react"; import { usePathname } from "next/navigation"; import { ChevronDown, Globe } from "lucide-react"; export const LOCALES = [ { code: "pt", label: "Português", short: "PT", lang: "pt-BR" }, { code: "en", label: "English", short: "EN", lang: "en" }, { code: "es", label: "Español", short: "ES", lang: "es-419" }, { code: "fr", label: "Français", short: "FR", lang: "fr" }, { code: "de", label: "Deutsch", short: "DE", lang: "de" }, { code: "zh-CN", label: "简体中文", short: "中", lang: "zh-CN" }, ]; 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 === "/" || pathname === `/${targetLocale}` || pathname === `/${targetLocale}/`) { return `/${targetLocale}/`; } for (const route of CANONICAL_ROUTES) { const m = pathname.match(route.match); if (m) { const slug = route.getSlug(targetLocale, m[1]); return slug ? `/${targetLocale}${slug}` : `/${targetLocale}/`; } } return `/${targetLocale}/`; } export default function LanguageSelector() { const pathname = usePathname() || ""; const [open, setOpen] = useState(false); const [hash, setHash] = useState(""); const containerRef = useRef(null); // Detecta locale da URL atual const currentLocaleCode = LOCALES.find((l) => pathname === `/${l.code}` || pathname.startsWith(`/${l.code}/`))?.code || "pt"; const currentLocale = LOCALES.find((l) => l.code === currentLocaleCode) || LOCALES[0]; useEffect(() => { if (typeof window !== "undefined") { setHash(window.location.hash || ""); } }, [pathname]); useEffect(() => { function onPointerDown(e) { if (containerRef.current && !containerRef.current.contains(e.target)) { setOpen(false); } } function onKeyDown(e) { if (e.key === "Escape") { setOpen(false); } } document.addEventListener("mousedown", onPointerDown); document.addEventListener("keydown", onKeyDown); return () => { document.removeEventListener("mousedown", onPointerDown); document.removeEventListener("keydown", onKeyDown); }; }, []); const handleSelect = (code) => { if (typeof document !== "undefined") { document.cookie = `NEXT_LOCALE=${code}; path=/; max-age=31536000; SameSite=Lax`; } setOpen(false); }; return (
{open && (
{LOCALES.map((loc) => { const isActive = loc.code === currentLocaleCode; const href = `${getLocalizedHref(pathname, loc.code)}${hash}`; return ( handleSelect(loc.code)} className={`flex min-h-[44px] items-center justify-between rounded-xl px-3 py-2 text-sm transition-colors ${ isActive ? "bg-accent-soft text-accent font-semibold" : "text-ink-soft hover:bg-surface-2 hover:text-ink" }`} > {loc.label} {loc.short} ); })}
)}
); }