feat(i18n): Spanish localization (phase 4)
CI / Lint e auditorias (push) Successful in 1m31s
CI / Trivy (dependências e segredos) (push) Successful in 10s
CI / Imagem Docker (linux/arm64) (push) Successful in 2m23s

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:
Lucas RayanandAntigravity committed 2026-11-01 19:50:20 -03:00
1 parent 0940814522
commit 660b28c09d
72 files changed
+17848 -947

No files matched your search

+36 -9
View File
@@ -3,14 +3,19 @@ import { paginaMeta, jsonLd } from "@/lib/seo";
export async function generateMetadata({ params }) {
const { locale } = await params;
const isEn = locale === "en";
const isEs = locale === "es";
return paginaMeta({
titulo: isEn ? "Which ESP32 to Choose" : "Qual ESP32 escolher",
descricao: isEn
titulo: isEs ? "Qué ESP32 elegir" : isEn ? "Which ESP32 to Choose" : "Qual ESP32 escolher",
descricao: isEs
? "Responda a preguntas sencillas sobre conectividad (Wi-Fi 6, 5GHz, Matter), energía, periféricos y seguridad o use el filtro paramétrico para encontrar el ESP32 perfecto."
: isEn
? "Answer simple questions about connectivity (Wi-Fi 6, 5GHz, Matter), power, peripherals, and security or use the parametric filter to find the perfect ESP32."
: "Responda a perguntas simples sobre conectividade (Wi-Fi 6, 5GHz, Matter), energia, periféricos e segurança ou use o filtro paramétrico para encontrar o ESP32 perfeito.",
caminho: "/seletor",
locale,
keywords: isEn
keywords: isEs
? ["qué ESP32 elegir", "cuál ESP32 usar", "elegir microcontrolador", "ESP32 para mi proyecto", "comparar ESP32"]
: isEn
? ["which ESP32 to choose", "which ESP32 to use", "choose microcontroller", "ESP32 for my project", "compare ESP32"]
: ["qual ESP32 escolher", "qual ESP32 usar", "escolher microcontrolador", "ESP32 para meu projeto", "comparar ESP32"],
});
@@ -54,10 +59,30 @@ const faqsEn = [
},
];
const faqsEs = [
{
pergunta: "¿Cuál ESP32 elegir para principiantes?",
resposta: "Para quienes se inician en el mundo Maker e IoT, el ESP32 clásico (NodeMCU/DevKitC) o el ESP32-C3 son las mejores opciones gracias al amplio soporte de bibliotecas, ejemplos listos en Arduino IDE y abundante documentación.",
},
{
pergunta: "¿Cuál ESP32 soporta Wi-Fi 6, Bluetooth 6 y Thread/Zigbee/Matter?",
resposta: "El ESP32-C6 y el ESP32-C5 son las series destacadas para redes modernas. El ESP32-C6 ofrece Wi-Fi 6 (2.4 GHz) y radio 802.15.4 (Zigbee 3.0 / Thread / Matter). El ESP32-C5 es el primero en ofrecer soporte para Wi-Fi 6 de doble banda operando en 2.4 GHz y 5 GHz simultáneamente.",
},
{
pergunta: "¿Cuál es el ESP32 más potente para Inteligencia Artificial (TinyML) y Pantallas?",
resposta: "El ESP32-P4 (dual-core RISC-V a 400 MHz con extensiones vectoriales de IA, interfaces MIPI-CSI/DSI para cámaras/pantallas y hasta 64 MB de PSRAM) y el ESP32-S3 (dual-core Xtensa a 240 MHz con aceleradores vectoriales para redes neuronales y soporte para LCD RGB) son los más rápidos para IA en el borde e interfaces gráficas avanzadas.",
},
{
pergunta: "¿Cuál ESP32 consume menos energía para proyectos a batería?",
resposta: "Los microcontroladores con arquitectura RISC-V compacta y coprocesador ULP, como el ESP32-C2, ESP32-C3 y ESP32-H2 (dedicado a 802.15.4 sin radio Wi-Fi), ofrecen corrientes de deep sleep extremadamente bajas (en el rango de 5 µA a 10 µA).",
},
];
export default async function Layout({ children, params }) {
const { locale } = await params;
const isEn = locale === "en";
const faqs = isEn ? faqsEn : faqsPt;
const isEs = locale === "es";
const faqs = isEs ? faqsEs : isEn ? faqsEn : faqsPt;
return (
<>
@@ -66,11 +91,13 @@ export default async function Layout({ children, params }) {
dangerouslySetInnerHTML={{
__html: JSON.stringify(
jsonLd.aplicacaoWeb({
nome: isEn ? "Intelligent ESP32 Selector" : "Seletor Inteligente de ESP32",
descricao: isEn
nome: isEs ? "Selector Inteligente de ESP32" : isEn ? "Intelligent ESP32 Selector" : "Seletor Inteligente de ESP32",
descricao: isEs
? "Herramienta interactiva que analiza conectividad, consumo, periféricos y seguridad para recomendar la serie ideal de ESP32."
: isEn
? "Interactive tool analyzing connectivity, power consumption, peripherals, and security to recommend the ideal ESP32 series."
: "Ferramenta interativa que analisa conectividade, consumo, periféricos e segurança para indicar a série ideal de ESP32.",
caminho: isEn ? "/en/selector" : "/seletor",
caminho: isEs ? "/es/selector" : isEn ? "/en/selector" : "/seletor",
locale,
})
),
@@ -81,8 +108,8 @@ export default async function Layout({ children, params }) {
dangerouslySetInnerHTML={{
__html: JSON.stringify(
jsonLd.trilha([
{ nome: isEn ? "Home" : "Início", caminho: isEn ? "/en" : "/" },
{ nome: isEn ? "ESP32 Selector" : "Seletor de ESP32", caminho: isEn ? "/en/selector" : "/seletor" },
{ nome: isEs ? "Inicio" : isEn ? "Home" : "Início", caminho: isEs ? "/es" : isEn ? "/en" : "/" },
{ nome: isEs ? "Selector de ESP32" : isEn ? "ESP32 Selector" : "Seletor de ESP32", caminho: isEs ? "/es/selector" : isEn ? "/en/selector" : "/seletor" },
])
),
}}
File diff suppressed because it is too large. Load diff