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

-168
View File
@@ -1,168 +0,0 @@
import { paginaMeta, jsonLd, SITE } from "@/lib/seo";
import Header from "@/components/Header";
import Footer from "@/components/Footer";
import PageHero from "@/components/PageHero";
import Image from "next/image";
import GiteaMark from "@/components/GiteaMark";
import { ArrowUpRight, Code, Globe, GitCompare, Info, Languages } from "lucide-react";
const REPOSITORIO = SITE.repositorio;
export const metadata = paginaMeta({
titulo: "Sobre o projeto",
descricao: "O ESPDocs é uma plataforma independente que reúne a documentação do ecossistema ESP32 em português brasileiro. Saiba como o projeto nasceu e como contribuir.",
caminho: "/sobre",
keywords: ["ESPDocs", "documentação ESP32 português", "projeto open source ESP32"],
});
export default function Sobre() {
const features = [
{ icon: Languages, title: "Em português", desc: "Dados técnicos organizados e apresentados em português do Brasil." },
{ icon: GitCompare, title: "Comparações visuais", desc: "Tabelas e diagramas para escolher a série certa sem abrir dez datasheets." },
{ icon: Globe, title: "Acesso centralizado", desc: "Links diretos para a documentação oficial, repositórios e exemplos." },
{ icon: Code, title: "Código aberto", desc: "Contribuições são bem-vindas no Gitea." },
];
return (
<div className="site-canvas min-h-screen">
{/* Metadados E-E-A-T de autoria e organização para o Google */}
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd.paginaSobre()) }}
/>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify(
jsonLd.trilha([
{ nome: "Início", caminho: "/" },
{ nome: "Sobre o Projeto", caminho: "/sobre" },
])
),
}}
/>
<Header />
<main id="conteudo">
<PageHero
trail={[{ label: "Sobre" }]}
icon={Info}
label="Projeto independente"
title="Sobre o ESPDocs"
lede="Uma plataforma não oficial, em português, que organiza as informações técnicas do ESP32 e leva você à documentação oficial da Espressif. Feita para a comunidade de hardware livre."
>
<a href={REPOSITORIO} target="_blank" rel="noopener noreferrer" className="btn btn-primary">
<GiteaMark className="h-4 w-4" />
Ver o repositório
<ArrowUpRight className="h-4 w-4" aria-hidden="true" />
</a>
</PageHero>
<div className="shell section grid grid-cols-1 gap-10 pt-12 sm:pt-16 lg:grid-cols-[1fr_22rem] lg:gap-14">
<div className="min-w-0 max-w-3xl space-y-12">
<section aria-labelledby="missao">
<h2 id="missao" className="section-title">Missão</h2>
<p className="mt-4 text-base leading-relaxed text-muted">
Facilitar o acesso e a compreensão do ecossistema ESP32 com uma interface em português que organiza
especificações, compara séries, apresenta frameworks e centraliza os links da documentação oficial.
O objetivo é economizar o seu tempo no desenvolvimento de firmware e IoT.
</p>
</section>
<section aria-labelledby="porque">
<h2 id="porque" className="section-title">Por que o ESPDocs existe</h2>
<p className="mt-4 text-base leading-relaxed text-muted">
As informações sobre os ESP32 costumam estar espalhadas entre datasheets densos, manuais de referência
(TRM) e repositórios secundários, tudo em inglês. O ESPDocs condensa e estrutura esses dados para a
triagem rápida, antes de você aprofundar na engenharia oficial.
</p>
<ul className="mt-6 grid gap-3 sm:grid-cols-2">
{features.map(({ icon: Icon, title, desc }) => (
<li key={title} className="card flex 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>
<div>
<h3 className="font-semibold text-ink">{title}</h3>
<p className="mt-1 text-sm leading-relaxed text-muted">{desc}</p>
</div>
</li>
))}
</ul>
</section>
<section aria-labelledby="contribuir">
<h2 id="contribuir" className="section-title">Como contribuir</h2>
<p className="mt-4 text-base leading-relaxed text-muted">
Correções de tradução, ajustes em tabelas e novos exemplos de código são muito bem-vindos. O projeto
cresce com a comunidade.
</p>
<ol className="mt-6 space-y-3">
{[
"Faça o fork do repositório no Gitea.",
"Implemente as melhorias e confira as referências técnicas oficiais.",
"Abra um Pull Request descrevendo os ajustes feitos.",
].map((passo, i) => (
<li key={passo} className="card flex items-center gap-4 px-5 py-4">
<span className="grid h-8 w-8 shrink-0 place-items-center rounded-full bg-ink text-sm font-semibold text-canvas" aria-hidden="true">
{i + 1}
</span>
<span className="text-sm text-ink-soft sm:text-base">{passo}</span>
</li>
))}
</ol>
</section>
<section aria-labelledby="acessibilidade">
<h2 id="acessibilidade" className="section-title">Acessibilidade</h2>
<p className="mt-4 text-base leading-relaxed text-muted">
O ESPDocs prioriza a legibilidade, o contraste alto (nível AAA da WCAG) e a navegação completa por
teclado. Se encontrar alguma barreira de leitura ou navegação, abra uma issue no repositório.
</p>
</section>
</div>
<aside className="space-y-5 lg:sticky lg:top-28 lg:self-start" aria-label="Autor e aviso legal">
<div className="panel p-6 sm:p-7">
<div className="flex items-center gap-4">
<span className="grid h-16 w-16 shrink-0 place-items-center rounded-2xl border border-line bg-white">
<Image src="/logo.png" alt="" aria-hidden="true" width={48} height={48} className="h-12 w-12 object-contain" />
</span>
<div>
<h2 className="font-display text-lg font-semibold text-ink">Lucas Rayan Guerra</h2>
<p className="text-sm text-muted">Criador do Ciência Embarcada</p>
</div>
</div>
<div className="mt-5 space-y-3 text-sm leading-relaxed text-muted">
<p>
Técnico em Desenvolvimento de Sistemas, estudante de Ciência da Computação na UFRPE e pesquisador de
Blockchain e Criptografia.
</p>
<p>
Diretor de Software na Semine AgriTech e palestrante em eventos como o REC&apos;n&apos;Play, compartilha
conteúdo sobre hardware, IoT e cibersegurança.
</p>
</div>
<a href="https://cienciaembarcada.com.br" target="_blank" rel="noopener noreferrer" className="btn btn-ghost mt-6 w-full">
Visitar o Ciência Embarcada
<ArrowUpRight className="h-4 w-4" aria-hidden="true" />
</a>
</div>
<div className="callout callout-warn">
<p className="font-semibold text-ink">Aviso legal</p>
<p className="mt-1">
O ESPDocs é um agregador e organizador. Os manuais e repositórios referenciados pertencem à Espressif
Systems. Em projetos críticos ou comerciais, consulte sempre a documentação oficial.
</p>
</div>
</aside>
</div>
</main>
<Footer />
</div>
);
}