Complete implementation of Spanish (es-419) language support: - Canonical catalogs and data: messages/es.json, data/es/**, lib/data/es/**, public/exemplos/es/** - Canonical slugs: /es/series, /es/catalogo, /es/comparacion, /es/componentes, /es/diagnostico, /es/frameworks, /es/glosario, /es/selector, /es/acerca - Dedicated search index at /api/busca/es with Spanish accent normalization - Strict exclusion of book references in Spanish routes and catalogs - Language selector and root negotiation with es active (ENABLED_LOCALES = ['pt', 'en', 'es']) - Extended verification suite: check-i18n, smoke-imagem and verifica-vazamentos Co-Authored-By: Antigravity <noreply@google.com>
72 lines
2.3 KiB
React
72 lines
2.3 KiB
React
import Link from "next/link";
|
|
|
|
/**
|
|
* Abertura padrão das páginas internas: trilha, rótulo, título, frase de apoio
|
|
* e ações. Mesma voz da /livro e da home, para que nenhuma página pareça
|
|
* de outro produto.
|
|
*/
|
|
export default function PageHero({
|
|
trail = [],
|
|
icon: Icon,
|
|
label,
|
|
title,
|
|
lede,
|
|
align = "left",
|
|
children,
|
|
isEn: isEnProp,
|
|
isEs: isEsProp,
|
|
locale: localeProp,
|
|
}) {
|
|
const center = align === "center";
|
|
const isEn =
|
|
isEnProp !== undefined
|
|
? isEnProp
|
|
: localeProp
|
|
? localeProp === "en"
|
|
: trail.some((t) => t.isEn || (t.href && t.href.startsWith("/en")));
|
|
const isEs =
|
|
isEsProp !== undefined
|
|
? isEsProp
|
|
: localeProp
|
|
? localeProp === "es"
|
|
: trail.some((t) => t.isEs || (t.href && t.href.startsWith("/es")));
|
|
|
|
return (
|
|
<section className="shell pt-8 sm:pt-12">
|
|
{trail.length > 0 && (
|
|
<nav aria-label={isEn ? "Breadcrumb navigation" : isEs ? "Navegación por migas de pan" : "Trilha de navegação"} className="flex flex-wrap items-center gap-2 text-sm text-muted">
|
|
<Link href={isEn ? "/en" : isEs ? "/es" : "/"} className="inline-flex min-h-11 min-w-11 items-center justify-center transition-colors hover:text-accent">
|
|
{isEn ? "Home" : isEs ? "Inicio" : "Início"}
|
|
</Link>
|
|
{trail.map((item, i) => (
|
|
<span key={item.label} className="flex min-h-11 items-center gap-2">
|
|
<span aria-hidden="true" className="text-line-strong">/</span>
|
|
{item.href && i < trail.length - 1 ? (
|
|
<Link href={item.href} className="inline-flex min-h-11 min-w-11 items-center justify-center transition-colors hover:text-accent">
|
|
{item.label}
|
|
</Link>
|
|
) : (
|
|
<span aria-current="page" className="text-ink">
|
|
{item.label}
|
|
</span>
|
|
)}
|
|
</span>
|
|
))}
|
|
</nav>
|
|
)}
|
|
|
|
<div className={`${trail.length ? "mt-8 sm:mt-10" : ""} max-w-3xl ${center ? "mx-auto text-center" : ""}`}>
|
|
{label && (
|
|
<span className="chip chip-accent">
|
|
{Icon && <Icon className="h-3.5 w-3.5" aria-hidden="true" />}
|
|
{label}
|
|
</span>
|
|
)}
|
|
<h1 className={`page-title ${label ? "mt-5" : ""}`}>{title}</h1>
|
|
{lede && <p className={`lede mt-5 max-w-2xl ${center ? "mx-auto" : ""}`}>{lede}</p>}
|
|
{children && <div className={`mt-7 flex flex-wrap gap-3 ${center ? "justify-center" : ""}`}>{children}</div>}
|
|
</div>
|
|
</section>
|
|
);
|
|
}
|