feat(i18n): Spanish localization (phase 4)
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>
This commit is contained in:
1 parent
0940814522
commit
660b28c09d
72 files changed
+17848
-947
No files matched your search
@@ -22,9 +22,29 @@ const HEADER_MAP_EN = {
|
||||
"LEDs": "LEDs",
|
||||
};
|
||||
|
||||
const HEADER_MAP_ES = {
|
||||
"Nome": "Nombre",
|
||||
"Descrição": "Descripción",
|
||||
"Série": "Serie",
|
||||
"Loja Oficial": "Tienda oficial",
|
||||
"Fabricante": "Fabricante",
|
||||
"Processador": "Procesador",
|
||||
"Memória Flash": "Memoria flash",
|
||||
"PSRAM": "PSRAM",
|
||||
"Conector USB": "Conector USB",
|
||||
"Interface USB": "Interfaz USB",
|
||||
"Antena": "Antena",
|
||||
"Bateria": "Batería",
|
||||
"Display": "Pantalla",
|
||||
"Sensores": "Sensores",
|
||||
"Botões": "Botones",
|
||||
"LEDs": "LEDs",
|
||||
};
|
||||
|
||||
export default function BoardCard({ board }) {
|
||||
const pathname = usePathname() || "";
|
||||
const isEn = pathname === "/en" || pathname.startsWith("/en/");
|
||||
const isEs = pathname === "/es" || pathname.startsWith("/es/");
|
||||
|
||||
const mainFields = ["Nome", "Link", "Imagem", "Loja Oficial"];
|
||||
|
||||
@@ -47,21 +67,21 @@ export default function BoardCard({ board }) {
|
||||
{lojaOficial && (
|
||||
<span className="chip chip-accent mb-3 w-fit">
|
||||
<Award className="h-3.5 w-3.5" aria-hidden="true" />
|
||||
{isEn ? "Official store" : "Loja oficial"}
|
||||
{isEn ? "Official store" : isEs ? "Tienda oficial" : "Loja oficial"}
|
||||
</span>
|
||||
)}
|
||||
|
||||
<h3 className="line-clamp-2 font-display text-lg font-semibold leading-snug tracking-[-0.02em] text-ink">
|
||||
{board.Nome || (isEn ? "Generic board" : "Placa genérica")}
|
||||
{board.Nome || (isEn ? "Generic board" : isEs ? "Placa genérica" : "Placa genérica")}
|
||||
</h3>
|
||||
|
||||
{recursos.length > 0 && (
|
||||
<div className="mt-4">
|
||||
<p className="text-xs font-medium text-muted">{isEn ? "On-board features" : "Recursos embarcados"}</p>
|
||||
<p className="text-xs font-medium text-muted">{isEn ? "On-board features" : isEs ? "Recursos integrados" : "Recursos embarcados"}</p>
|
||||
<ul className="mt-2 flex flex-wrap gap-1.5">
|
||||
{recursos.map((campo) => {
|
||||
const opcional = valor(campo) === "opcional";
|
||||
const label = isEn ? (HEADER_MAP_EN[campo] || campo) : campo;
|
||||
const label = isEn ? (HEADER_MAP_EN[campo] || campo) : isEs ? (HEADER_MAP_ES[campo] || campo) : campo;
|
||||
return (
|
||||
<li key={campo} className={`chip ${opcional ? "text-gold" : "text-ink-soft"}`}>
|
||||
{opcional ? (
|
||||
@@ -80,9 +100,9 @@ export default function BoardCard({ board }) {
|
||||
|
||||
{board.Link && (
|
||||
<a href={board.Link} target="_blank" rel="noopener noreferrer" className="btn btn-primary mt-6 w-full">
|
||||
{isEn ? "View on AliExpress" : "Ver no AliExpress"}
|
||||
{isEn ? "View on AliExpress" : isEs ? "Ver en AliExpress" : "Ver no AliExpress"}
|
||||
<ArrowUpRight className="h-4 w-4" aria-hidden="true" />
|
||||
<span className="sr-only">{isEn ? " (opens in new tab)" : " (abre em nova aba)"}</span>
|
||||
<span className="sr-only">{isEn ? " (opens in new tab)" : isEs ? " (abre en una pestaña nueva)" : " (abre em nova aba)"}</span>
|
||||
</a>
|
||||
)}
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user