feat(i18n): routing and localization infrastructure (phase 1)

Implement Phase 1 of i18n spec:
- Configure next-intl with 6 locales (pt, en, es, fr, de, zh-CN) and pathnames
- Move routes to app/[locale] structure with localized layouts and metadata
- Add middleware for root language negotiation (307), legacy redirects (308), and 404 for non-pt book
- Implement language selector dropdown in header with cookie persistence
- Add system typography rules for zh-CN and word-break/hyphenation for de/fr

Co-Authored-By: Antigravity <noreply@google.com>
This commit is contained in:
Lucas RayanandAntigravity committed 2026-11-01 09:31:22 -03:00
1 parent e92aea0c84
commit 83c0ba3e74
38 files changed
+1699 -324

No files matched your search

+58
View File
@@ -0,0 +1,58 @@
import Header from "@/components/Header";
import Footer from "@/components/Footer";
import Link from "next/link";
import { ArrowRight, BookOpen, Compass, Scale, SlidersHorizontal } from "lucide-react";
export const metadata = {
title: "Página não encontrada",
robots: { index: false, follow: false },
};
const CAMINHOS = [
{ href: "/series", icon: Compass, titulo: "Séries ESP32", texto: "As 12 famílias, com pinagem e especificações." },
{ href: "/seletor", icon: SlidersHorizontal, titulo: "Seletor de chip", texto: "Responda a oito perguntas e receba os modelos indicados." },
{ href: "/comparacao", icon: Scale, titulo: "Comparador", texto: "Até quatro séries lado a lado." },
{ href: "/glossario", icon: BookOpen, titulo: "Glossário", texto: "Termos de hardware explicados em português." },
];
export default function NotFound() {
return (
<div className="site-canvas min-h-screen">
<Header />
<main id="conteudo" className="shell section">
<div className="mx-auto max-w-2xl text-center">
<p className="eyebrow justify-center">Erro 404</p>
<h1 className="page-title mt-4">Essa página não existe.</h1>
<p className="lede mx-auto mt-5 max-w-xl">
O endereço pode ter mudado ou estar digitado errado. Escolha um destes caminhos para continuar.
</p>
<div className="mt-8 flex justify-center">
<Link href="/" className="btn btn-primary">
Voltar ao início
<ArrowRight className="h-4 w-4" aria-hidden="true" />
</Link>
</div>
</div>
<ul className="mx-auto mt-14 grid max-w-4xl gap-3 sm:grid-cols-2">
{CAMINHOS.map(({ href, icon: Icon, titulo, texto }) => (
<li key={href}>
<Link href={href} className="card card-interactive group flex h-full items-start gap-4 p-5">
<span className="grid h-10 w-10 shrink-0 place-items-center rounded-full bg-accent-soft text-accent">
<Icon className="h-5 w-5" aria-hidden="true" />
</span>
<span>
<span className="block font-semibold text-ink">{titulo}</span>
<span className="mt-0.5 block text-sm text-muted">{texto}</span>
</span>
</Link>
</li>
))}
</ul>
</main>
<Footer />
</div>
);
}