Files
ESPDocs/app/[locale]/series/[key]/page.jsx
T
Lucas RayanandClaude Sonnet 5.5 23576b5c06
Release / Plano (reaproveitar a imagem?) (push) Successful in 7s
CI / Lint e auditorias (push) Successful in 55s
CI / Trivy (dependências e segredos) (push) Successful in 12s
CI / Imagem Docker (linux/arm64) (push) Successful in 4m8s
Release / ci (push) Successful in 5m16s
Release / Publica a imagem (linux/arm64) (push) Successful in 19s
Release / Cria a release no Gitea (push) Skipped
Release / Deploy no Coolify (push) Successful in 22s
fix(placas): faixa sobe para logo abaixo da foto/diagrama e não estoura no celular
Na página de série a faixa passa a ficar entre o bloco de foto/diagrama de pinos
e as especificações. No celular o botão ocupa a largura do cartão e as setas ficam
numa linha própria; testado de 320 a 1366 px sem nada ultrapassar a área.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-11-02 19:13:07 -03:00

1099 lines
51 KiB
React
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import { paginaMeta, jsonLd } from "@/lib/seo";
import Link from "next/link";
import Image from "next/image";
import Header from "@/components/Header";
import Footer from "@/components/Footer";
import PageHero from "@/components/PageHero";
import { notFound } from "next/navigation";
import seriesDataPt from "@/public/series.json";
import seriesDataEn from "@/data/en/series.json";
import seriesDataEs from "@/data/es/series.json";
import seriesDataFr from "@/data/fr/series.json";
import seriesDataDe from "@/data/de/series.json";
import seriesDataZh from "@/data/zh-CN/series.json";
import ConnectionsDiagram from "@/components/ConnectionsDiagram";
import SeriesTabMenu from "@/components/SeriesTabMenu";
import PlacasSugeridas from "@/components/PlacasSugeridas";
import PinRestrictions from "@/components/PinRestrictions";
import { getLocalizedHref } from "@/i18n/links";
import {
AlertTriangle,
ArrowLeft,
ArrowRight,
ArrowUpRight,
Battery,
BookOpen,
Code,
Cpu,
Database,
ExternalLink,
FileText,
Lightbulb,
Package,
Scale,
ShieldCheck,
Sliders,
Thermometer,
Wifi,
} from "lucide-react";
export default async function SerieDetail({ params }) {
const { locale, key } = await params;
const isEn = locale === "en";
const isEs = locale === "es";
const isFr = locale === "fr";
const isDe = locale === "de";
const isZh = locale === "zh-CN";
const currentLocale = isZh ? "zh-CN" : isDe ? "de" : isFr ? "fr" : isEs ? "es" : isEn ? "en" : "pt";
const seriesData = isZh ? seriesDataZh : isDe ? seriesDataDe : isFr ? seriesDataFr : isEs ? seriesDataEs : isEn ? seriesDataEn : seriesDataPt;
const serie = seriesData[key];
if (!serie) {
notFound();
}
let conexoes = [];
try {
conexoes = isZh ? require(`@/data/zh-CN/conexoes/${key}.json`) : isDe
? require(`@/data/de/conexoes/${key}.json`)
: isFr
? require(`@/data/fr/conexoes/${key}.json`)
: isEs
? require(`@/data/es/conexoes/${key}.json`)
: isEn
? require(`@/data/en/conexoes/${key}.json`)
: require(`@/public/conexoes/${key}.json`);
} catch (error) {
console.log(`Arquivo de conexões não encontrado para ${key}`);
}
const seriesKeys = Object.keys(seriesData);
const currentIndex = seriesKeys.indexOf(key);
const previousKey = currentIndex > 0 ? seriesKeys[currentIndex - 1] : null;
const nextKey = currentIndex < seriesKeys.length - 1 ? seriesKeys[currentIndex + 1] : null;
const nao = isZh ? "否" : isDe ? "Nein" : isFr ? "Non" : isEs || isEn ? "No" : "Não";
const naoInformado = isZh ? "未提供" : isDe ? "Nicht angegeben" : isFr ? "Non communiqué" : isEs ? "No informado" : isEn ? "Not informed" : "Não informado";
const processadorSpecs = isZh ? [
{ label: "架构", value: serie.arquitetura },
{ label: "内核", value: serie.nucleos },
{ label: "频率", value: serie.frequencia },
{ label: "ULP 协处理器", value: serie.coprocessador_ulp || nao },
{ label: "AI 加速器", value: serie.aceleradores_ia || nao },
] : isDe
? [
{ label: "Architektur", value: serie.arquitetura },
{ label: "Kerne", value: serie.nucleos },
{ label: "Taktfrequenz", value: serie.frequencia },
{ label: "ULP-Coprozessor", value: serie.coprocessador_ulp || nao },
{ label: "KI-Beschleuniger", value: serie.aceleradores_ia || nao },
]
: isFr
? [
{ label: "Architecture", value: serie.arquitetura },
{ label: "Cœurs", value: serie.nucleos },
{ label: "Fréquence", value: serie.frequencia },
{ label: "Coprocesseur ULP", value: serie.coprocessador_ulp || nao },
{ label: "Accélérateurs IA", value: serie.aceleradores_ia || nao },
]
: isEs
? [
{ label: "Arquitectura", value: serie.arquitetura },
{ label: "Núcleos", value: serie.nucleos },
{ label: "Frecuencia", value: serie.frequencia },
{ label: "Coprocesador ULP", value: serie.coprocessador_ulp || nao },
{ label: "Aceleradores de IA", value: serie.aceleradores_ia || nao },
]
: isEn
? [
{ label: "Architecture", value: serie.arquitetura },
{ label: "Cores", value: serie.nucleos },
{ label: "Frequency", value: serie.frequencia },
{ label: "ULP Coprocessor", value: serie.coprocessador_ulp || nao },
{ label: "AI Accelerators", value: serie.aceleradores_ia || nao },
]
: [
{ label: "Arquitetura", value: serie.arquitetura },
{ label: "Núcleos", value: serie.nucleos },
{ label: "Frequência", value: serie.frequencia },
{ label: "Coprocessador ULP", value: serie.coprocessador_ulp || "Não" },
{ label: "Aceleradores IA", value: serie.aceleradores_ia || "Não" },
];
const seg = serie.seguranca || {};
const segurancaSpecs = isZh ? [
{ label: "AES", value: seg.aes || nao },
{ label: "SHA", value: seg.sha || nao },
{ label: "RSA / MPI", value: seg.rsa || nao },
{ label: "ECC(椭圆曲线)", value: seg.ecc || nao },
{ label: "硬件 ECDSA", value: seg.ecdsa || nao },
{ label: "HMAC", value: seg.hmac || nao },
{ label: "数字签名(DS)", value: seg.assinatura_digital || nao },
{ label: "密钥管理器", value: seg.key_manager || nao },
{ label: "随机数发生器(TRNG)", value: seg.rng || nao },
{ label: "闪存加密", value: seg.criptografia_flash || nao },
{ label: "安全启动", value: seg.secure_boot || nao },
{ label: "DPA 防护", value: seg.protecao_dpa || nao },
] : isDe
? [
{ label: "AES", value: seg.aes || nao },
{ label: "SHA", value: seg.sha || nao },
{ label: "RSA / MPI", value: seg.rsa || nao },
{ label: "ECC (elliptische Kurven)", value: seg.ecc || nao },
{ label: "Hardware-ECDSA", value: seg.ecdsa || nao },
{ label: "HMAC", value: seg.hmac || nao },
{ label: "Digitale Signatur (DS)", value: seg.assinatura_digital || nao },
{ label: "Key Manager", value: seg.key_manager || nao },
{ label: "Zufallszahlengenerator (TRNG)", value: seg.rng || nao },
{ label: "Flash-Verschlüsselung", value: seg.criptografia_flash || nao },
{ label: "Secure Boot", value: seg.secure_boot || nao },
{ label: "DPA-Schutz", value: seg.protecao_dpa || nao },
]
: isFr
? [
{ label: "AES", value: seg.aes || nao },
{ label: "SHA", value: seg.sha || nao },
{ label: "RSA / MPI", value: seg.rsa || nao },
{ label: "ECC (courbes elliptiques)", value: seg.ecc || nao },
{ label: "ECDSA matériel", value: seg.ecdsa || nao },
{ label: "HMAC", value: seg.hmac || nao },
{ label: "Signature numérique (DS)", value: seg.assinatura_digital || nao },
{ label: "Key Manager", value: seg.key_manager || nao },
{ label: "Générateur aléatoire (TRNG)", value: seg.rng || nao },
{ label: "Chiffrement Flash", value: seg.criptografia_flash || nao },
{ label: "Secure Boot", value: seg.secure_boot || nao },
{ label: "Protection DPA", value: seg.protecao_dpa || nao },
]
: isEs
? [
{ label: "AES", value: seg.aes || nao },
{ label: "SHA", value: seg.sha || nao },
{ label: "RSA / MPI", value: seg.rsa || nao },
{ label: "ECC (curvas elípticas)", value: seg.ecc || nao },
{ label: "ECDSA en hardware", value: seg.ecdsa || nao },
{ label: "HMAC", value: seg.hmac || nao },
{ label: "Firma digital (DS)", value: seg.assinatura_digital || nao },
{ label: "Key Manager", value: seg.key_manager || nao },
{ label: "Generador aleatorio (TRNG)", value: seg.rng || nao },
{ label: "Cifrado de flash", value: seg.criptografia_flash || nao },
{ label: "Secure Boot", value: seg.secure_boot || nao },
{ label: "Protección contra DPA", value: seg.protecao_dpa || nao },
]
: isEn
? [
{ label: "AES", value: seg.aes || nao },
{ label: "SHA", value: seg.sha || nao },
{ label: "RSA / MPI", value: seg.rsa || nao },
{ label: "ECC (elliptic curves)", value: seg.ecc || nao },
{ label: "Hardware ECDSA", value: seg.ecdsa || nao },
{ label: "HMAC", value: seg.hmac || nao },
{ label: "Digital Signature (DS)", value: seg.assinatura_digital || nao },
{ label: "Key Manager", value: seg.key_manager || nao },
{ label: "Random Generator (TRNG)", value: seg.rng || nao },
{ label: "Flash Encryption", value: seg.criptografia_flash || nao },
{ label: "Secure Boot", value: seg.secure_boot || nao },
{ label: "DPA Protection", value: seg.protecao_dpa || nao },
]
: [
{ label: "AES", value: seg.aes || "Não" },
{ label: "SHA", value: seg.sha || "Não" },
{ label: "RSA / MPI", value: seg.rsa || "Não" },
{ label: "ECC (curvas elípticas)", value: seg.ecc || "Não" },
{ label: "ECDSA em hardware", value: seg.ecdsa || "Não" },
{ label: "HMAC", value: seg.hmac || "Não" },
{ label: "Assinatura Digital (DS)", value: seg.assinatura_digital || "Não" },
{ label: "Key Manager", value: seg.key_manager || "Não" },
{ label: "Gerador aleatório (RNG)", value: seg.rng || "Não" },
{ label: "Criptografia de flash", value: seg.criptografia_flash || "Não" },
{ label: "Secure Boot", value: seg.secure_boot || "Não" },
{ label: "Proteção contra DPA", value: seg.protecao_dpa || "Não" },
];
const ferramentasSpecs = isZh ? [
{ label: "最低 ESP-IDF 版本", value: serie.esp_idf_minimo || naoInformado },
{ label: "Arduino 核心", value: serie.arduino_core || naoInformado },
{ label: "调试", value: serie.depuracao || naoInformado },
{ label: "封装", value: serie.encapsulamento || naoInformado },
{ label: "可用模组", value: serie.modulos || naoInformado },
] : isDe
? [
{ label: "Minimales ESP-IDF", value: serie.esp_idf_minimo || naoInformado },
{ label: "Arduino-Core", value: serie.arduino_core || naoInformado },
{ label: "Debugging", value: serie.depuracao || naoInformado },
{ label: "Gehäuse", value: serie.encapsulamento || naoInformado },
{ label: "Verfügbare Module", value: serie.modulos || naoInformado },
]
: isFr
? [
{ label: "ESP-IDF minimal", value: serie.esp_idf_minimo || naoInformado },
{ label: "Core Arduino", value: serie.arduino_core || naoInformado },
{ label: "Débogage", value: serie.depuracao || naoInformado },
{ label: "Boîtier", value: serie.encapsulamento || naoInformado },
{ label: "Modules disponibles", value: serie.modulos || naoInformado },
]
: isEs
? [
{ label: "ESP-IDF mínimo", value: serie.esp_idf_minimo || naoInformado },
{ label: "Core Arduino", value: serie.arduino_core || naoInformado },
{ label: "Depuración", value: serie.depuracao || naoInformado },
{ label: "Encapsulado", value: serie.encapsulamento || naoInformado },
{ label: "Módulos disponibles", value: serie.modulos || naoInformado },
]
: isEn
? [
{ label: "Minimum ESP-IDF", value: serie.esp_idf_minimo || naoInformado },
{ label: "Arduino Core", value: serie.arduino_core || naoInformado },
{ label: "Debugging", value: serie.depuracao || naoInformado },
{ label: "Package", value: serie.encapsulamento || naoInformado },
{ label: "Available Modules", value: serie.modulos || naoInformado },
]
: [
{ label: "ESP-IDF mínimo", value: serie.esp_idf_minimo || "Não informado" },
{ label: "Core Arduino", value: serie.arduino_core || "Não informado" },
{ label: "Depuração", value: serie.depuracao || "Não informado" },
{ label: "Encapsulamento", value: serie.encapsulamento || "Não informado" },
{ label: "Módulos disponíveis", value: serie.modulos || "Não informado" },
];
const conectividadeSpecs = isZh ? [
{ label: "Wi-Fi", value: serie.wifi || nao },
{ label: "蓝牙", value: serie.bluetooth || nao },
{ label: "Zigbee/Thread", value: serie.zigbee_thread || nao },
{ label: "Matter", value: serie.matter || nao },
{ label: "以太网", value: serie.ethernet || serie.ethernet_mac || nao },
{ label: "CAN", value: serie.can || nao },
] : isDe
? [
{ label: "Wi-Fi", value: serie.wifi || nao },
{ label: "Bluetooth", value: serie.bluetooth || nao },
{ label: "Zigbee/Thread", value: serie.zigbee_thread || nao },
{ label: "Matter", value: serie.matter || nao },
{ label: "Ethernet", value: serie.ethernet || serie.ethernet_mac || nao },
{ label: "CAN", value: serie.can || nao },
]
: isFr
? [
{ label: "Wi-Fi", value: serie.wifi || nao },
{ label: "Bluetooth", value: serie.bluetooth || nao },
{ label: "Zigbee/Thread", value: serie.zigbee_thread || nao },
{ label: "Matter", value: serie.matter || nao },
{ label: "Ethernet", value: serie.ethernet || serie.ethernet_mac || nao },
{ label: "CAN", value: serie.can || nao },
]
: isEs
? [
{ label: "Wi-Fi", value: serie.wifi || nao },
{ label: "Bluetooth", value: serie.bluetooth || nao },
{ label: "Zigbee/Thread", value: serie.zigbee_thread || nao },
{ label: "Matter", value: serie.matter || nao },
{ label: "Ethernet", value: serie.ethernet || serie.ethernet_mac || nao },
{ label: "CAN", value: serie.can || nao },
]
: isEn
? [
{ label: "Wi-Fi", value: serie.wifi || nao },
{ label: "Bluetooth", value: serie.bluetooth || nao },
{ label: "Zigbee/Thread", value: serie.zigbee_thread || nao },
{ label: "Matter", value: serie.matter || nao },
{ label: "Ethernet", value: serie.ethernet || serie.ethernet_mac || nao },
{ label: "CAN", value: serie.can || nao },
]
: [
{ label: "Wi-Fi", value: serie.wifi || "Não" },
{ label: "Bluetooth", value: serie.bluetooth || "Não" },
{ label: "Zigbee/Thread", value: serie.zigbee_thread || "Não" },
{ label: "Matter", value: serie.matter || "Não" },
{ label: "Ethernet", value: serie.ethernet || serie.ethernet_mac || "Não" },
{ label: "CAN", value: serie.can || "Não" },
];
const memoriaSpecs = isZh ? [
{ label: "SRAM", value: serie.memoria_sram },
{ label: "RTC SRAM", value: serie.memoria_sram_rtc },
{ label: "ROM", value: serie.memoria_rom },
{ label: "外部闪存", value: serie.flash_externa },
{ label: "外部 PSRAM", value: serie.psram_externa || nao },
] : isDe
? [
{ label: "SRAM", value: serie.memoria_sram },
{ label: "RTC-SRAM", value: serie.memoria_sram_rtc },
{ label: "ROM", value: serie.memoria_rom },
{ label: "Externer Flash", value: serie.flash_externa },
{ label: "Externer PSRAM", value: serie.psram_externa || nao },
]
: isFr
? [
{ label: "SRAM", value: serie.memoria_sram },
{ label: "SRAM RTC", value: serie.memoria_sram_rtc },
{ label: "ROM", value: serie.memoria_rom },
{ label: "Flash externe", value: serie.flash_externa },
{ label: "PSRAM externe", value: serie.psram_externa || nao },
]
: isEs
? [
{ label: "SRAM", value: serie.memoria_sram },
{ label: "SRAM RTC", value: serie.memoria_sram_rtc },
{ label: "ROM", value: serie.memoria_rom },
{ label: "Flash externa", value: serie.flash_externa },
{ label: "PSRAM externa", value: serie.psram_externa || nao },
]
: isEn
? [
{ label: "SRAM", value: serie.memoria_sram },
{ label: "RTC SRAM", value: serie.memoria_sram_rtc },
{ label: "ROM", value: serie.memoria_rom },
{ label: "External Flash", value: serie.flash_externa },
{ label: "External PSRAM", value: serie.psram_externa || nao },
]
: [
{ label: "SRAM", value: serie.memoria_sram },
{ label: "SRAM RTC", value: serie.memoria_sram_rtc },
{ label: "ROM", value: serie.memoria_rom },
{ label: "Flash Externa", value: serie.flash_externa },
{ label: "PSRAM Externa", value: serie.psram_externa || "Não" },
];
const perifericos = isZh ? [
{ label: "GPIO", value: serie.gpio },
{ label: "ADC", value: serie.adc },
{ label: "DAC", value: serie.dac || nao },
{ label: "触摸", value: serie.touch || nao },
{ label: "UART", value: serie.uart },
{ label: "SPI", value: serie.spi },
{ label: "I2C", value: serie.i2c },
{ label: "I2S", value: serie.i2s },
{ label: "PWM", value: serie.pwm },
{ label: "USB", value: serie.usb || nao },
] : isDe
? [
{ label: "GPIO", value: serie.gpio },
{ label: "ADC", value: serie.adc },
{ label: "DAC", value: serie.dac || nao },
{ label: "Touch", value: serie.touch || nao },
{ label: "UART", value: serie.uart },
{ label: "SPI", value: serie.spi },
{ label: "I2C", value: serie.i2c },
{ label: "I2S", value: serie.i2s },
{ label: "PWM", value: serie.pwm },
{ label: "USB", value: serie.usb || nao },
]
: isFr
? [
{ label: "GPIO", value: serie.gpio },
{ label: "ADC", value: serie.adc },
{ label: "DAC", value: serie.dac || nao },
{ label: "Touch", value: serie.touch || nao },
{ label: "UART", value: serie.uart },
{ label: "SPI", value: serie.spi },
{ label: "I2C", value: serie.i2c },
{ label: "I2S", value: serie.i2s },
{ label: "PWM", value: serie.pwm },
{ label: "USB", value: serie.usb || nao },
]
: isEs
? [
{ label: "GPIO", value: serie.gpio },
{ label: "ADC", value: serie.adc },
{ label: "DAC", value: serie.dac || nao },
{ label: "Touch", value: serie.touch || nao },
{ label: "UART", value: serie.uart },
{ label: "SPI", value: serie.spi },
{ label: "I2C", value: serie.i2c },
{ label: "I2S", value: serie.i2s },
{ label: "PWM", value: serie.pwm },
{ label: "USB", value: serie.usb || nao },
]
: isEn
? [
{ label: "GPIO", value: serie.gpio },
{ label: "ADC", value: serie.adc },
{ label: "DAC", value: serie.dac || nao },
{ label: "Touch", value: serie.touch || nao },
{ label: "UART", value: serie.uart },
{ label: "SPI", value: serie.spi },
{ label: "I2C", value: serie.i2c },
{ label: "I2S", value: serie.i2s },
{ label: "PWM", value: serie.pwm },
{ label: "USB", value: serie.usb || nao },
]
: [
{ label: "GPIO", value: serie.gpio },
{ label: "ADC", value: serie.adc },
{ label: "DAC", value: serie.dac || "Não" },
{ label: "Touch", value: serie.touch || "Não" },
{ label: "UART", value: serie.uart },
{ label: "SPI", value: serie.spi },
{ label: "I2C", value: serie.i2c },
{ label: "I2S", value: serie.i2s },
{ label: "PWM", value: serie.pwm },
{ label: "USB", value: serie.usb || "Não" },
];
const interfacesEspeciais = [];
if (serie.lcd) interfacesEspeciais.push({ label: "LCD", value: serie.lcd });
if (serie.camera) interfacesEspeciais.push({ label: isZh ? "摄像头" : isDe ? "Kamera" : isFr ? "Caméra" : isEs ? "Cámara" : isEn ? "Camera" : "Câmera", value: serie.camera });
if (serie.mipi_csi) interfacesEspeciais.push({ label: "MIPI CSI", value: serie.mipi_csi });
if (serie.mipi_dsi) interfacesEspeciais.push({ label: "MIPI DSI", value: serie.mipi_dsi });
if (serie.sdio) interfacesEspeciais.push({ label: "SDIO", value: serie.sdio });
if (serie.sensor_hall) interfacesEspeciais.push({ label: isZh ? "霍尔传感器" : isDe ? "Hall-Sensor" : isFr ? "Capteur Hall" : isEs ? "Sensor Hall" : isEn ? "Hall Sensor" : "Sensor Hall", value: serie.sensor_hall });
if (serie.sensor_temperatura) interfacesEspeciais.push({ label: isZh ? "温度传感器" : isDe ? "Temperatursensor" : isFr ? "Capteur de température" : isEs ? "Sensor de temperatura" : isEn ? "Temperature Sensor" : "Sensor Temperatura", value: serie.sensor_temperatura });
// Consumo de Energia
const consumoEnergia = [];
if (serie.consumo_energia) {
const modoLabelsPt = {
'active': 'Modo Ativo',
'active_cpu_240mhz': 'Ativo (CPU 240MHz)',
'active_cpu_160mhz': 'Ativo (CPU 160MHz)',
'active_wifi_tx': 'Ativo (Wi-Fi TX)',
'active_wifi_tx_peak': 'Ativo (Wi-Fi TX Pico)',
'active_wifi': 'Ativo (Wi-Fi)',
'active_wifi6': 'Ativo (Wi-Fi 6)',
'modem_sleep': 'Modem Sleep',
'modem_sleep_cpu_160mhz': 'Modem Sleep (CPU 160MHz)',
'light_sleep': 'Light Sleep',
'deep_sleep': 'Deep Sleep',
'hibernation': 'Hibernação'
};
const modoLabelsEn = {
'active': 'Active Mode',
'active_cpu_240mhz': 'Active (CPU 240MHz)',
'active_cpu_160mhz': 'Active (CPU 160MHz)',
'active_wifi_tx': 'Active (Wi-Fi TX)',
'active_wifi_tx_peak': 'Active (Wi-Fi TX Peak)',
'active_wifi': 'Active (Wi-Fi)',
'active_wifi6': 'Active (Wi-Fi 6)',
'modem_sleep': 'Modem Sleep',
'modem_sleep_cpu_160mhz': 'Modem Sleep (CPU 160MHz)',
'light_sleep': 'Light Sleep',
'deep_sleep': 'Deep Sleep',
'hibernation': 'Hibernation'
};
const modoLabelsEs = {
'active': 'Modo activo',
'active_cpu_240mhz': 'Activo (CPU 240MHz)',
'active_cpu_160mhz': 'Activo (CPU 160MHz)',
'active_wifi_tx': 'Activo (Wi-Fi TX)',
'active_wifi_tx_peak': 'Activo (Wi-Fi TX Pico)',
'active_wifi': 'Activo (Wi-Fi)',
'active_wifi6': 'Activo (Wi-Fi 6)',
'modem_sleep': 'Modem Sleep',
'modem_sleep_cpu_160mhz': 'Modem Sleep (CPU 160MHz)',
'light_sleep': 'Light Sleep',
'deep_sleep': 'Deep Sleep',
'hibernation': 'Hibernación'
};
const modoLabelsFr = {
'active': 'Mode actif',
'active_cpu_240mhz': 'Actif (CPU 240MHz)',
'active_cpu_160mhz': 'Actif (CPU 160MHz)',
'active_wifi_tx': 'Actif (Wi-Fi TX)',
'active_wifi_tx_peak': 'Actif (Wi-Fi TX Pic)',
'active_wifi': 'Actif (Wi-Fi)',
'active_wifi6': 'Actif (Wi-Fi 6)',
'modem_sleep': 'Modem Sleep',
'modem_sleep_cpu_160mhz': 'Modem Sleep (CPU 160MHz)',
'light_sleep': 'Light Sleep',
'deep_sleep': 'Deep Sleep',
'hibernation': 'Hibernation'
};
const modoLabelsDe = {
'active': 'Aktivmodus',
'active_cpu_240mhz': 'Aktiv (CPU 240MHz)',
'active_cpu_160mhz': 'Aktiv (CPU 160MHz)',
'active_wifi_tx': 'Aktiv (Wi-Fi TX)',
'active_wifi_tx_peak': 'Aktiv (Wi-Fi TX Spitze)',
'active_wifi': 'Aktiv (Wi-Fi)',
'active_wifi6': 'Aktiv (Wi-Fi 6)',
'modem_sleep': 'Modem Sleep',
'modem_sleep_cpu_160mhz': 'Modem Sleep (CPU 160MHz)',
'light_sleep': 'Light Sleep',
'deep_sleep': 'Deep Sleep',
'hibernation': 'Ruhezustand'
};
const modoLabelsZh = {
'active': '工作模式',
'active_cpu_240mhz': '工作(CPU 240MHz)',
'active_cpu_160mhz': '工作(CPU 160MHz)',
'active_wifi_tx': '工作(Wi-Fi 发射)',
'active_wifi_tx_peak': '工作(Wi-Fi 发射峰值)',
'active_wifi': '工作(Wi-Fi)',
'active_wifi6': '工作(Wi-Fi 6)',
'modem_sleep': 'Modem Sleep',
'modem_sleep_cpu_160mhz': 'Modem Sleep(CPU 160MHz)',
'light_sleep': 'Light Sleep',
'deep_sleep': 'Deep Sleep',
'hibernation': 'Hibernation'
};
const modoLabels = isZh ? modoLabelsZh : isDe ? modoLabelsDe : isFr ? modoLabelsFr : isEs ? modoLabelsEs : isEn ? modoLabelsEn : modoLabelsPt;
Object.entries(serie.consumo_energia).forEach(([modo, consumo]) => {
consumoEnergia.push({
label: modoLabels[modo] || modo.replace(/_/g, ' ').replace(/\b\w/g, (l) => l.toUpperCase()),
value: consumo
});
});
}
const tabs = [
{
id: "devboard",
label: isZh ? "开发板" : isDe ? "Entwicklungsboard" : isFr ? "Carte de développement" : isEs ? "Placa de desarrollo" : isEn ? "Development board" : "Placa de desenvolvimento",
available: serie.placa,
content: (
<div className="card p-5 sm:p-7">
<h2 className="text-lg font-semibold text-ink">
{isZh ? "官方开发套件" : isDe ? "Offizielles Development Kit" : isFr ? "Kit de développement officiel" : isEs ? "Kit de desarrollo oficial" : isEn ? "Official development kit" : "Kit de desenvolvimento oficial"}
</h2>
{/* As fotos oficiais foram feitas para fundo claro: o quadro fica branco nos dois temas. */}
<div className="mt-5 overflow-hidden rounded-xl border border-line bg-white p-4">
<Image
src={serie.placa}
alt={isZh ? `开发板 ${key}` : isDe ? `Entwicklungsboard ${key}` : isFr ? `Carte de développement ${key}` : isEs ? `Placa de desarrollo ${key}` : isEn ? `Development board ${key}` : `Placa de desenvolvimento ${key}`}
width={1200}
height={800}
className="mx-auto h-auto max-h-[28rem] w-full rounded-lg object-contain"
priority
/>
</div>
<p className="mt-3 text-sm text-muted">
{isZh ? ( <>乐鑫面向 {key} 系列的官方开发板。</> ) : isDe ? (
<>Offizielles Espressif-Board für die Serie {key}.</>
) : isFr ? (
<>Carte officielle d'Espressif pour la série {key}.</>
) : isEs ? (
<>Placa estándar de Espressif para la serie {key}.</>
) : isEn ? (
<>Official Espressif board for the {key} series.</>
) : (
<>Placa padrão da Espressif para a série {key}.</>
)}
</p>
</div>
),
},
{
id: "connections",
label: isZh ? "引脚图" : isDe ? "Pinbelegungsdiagramm" : isFr ? "Diagramme de brochage" : isEs ? "Diagrama de patillaje" : isEn ? "Pinout diagram" : "Diagrama de conexões",
available: conexoes.length > 0,
content: (
<div className="card p-5 sm:p-7">
<div className="callout callout-warn flex items-start gap-3">
<AlertTriangle className="mt-0.5 h-5 w-5 shrink-0 text-gold" aria-hidden="true" />
<div>
<p className="font-semibold text-ink">
{isZh ? "这是芯片图,不是开发板" : isDe ? "Dies ist das Diagramm des Chips, nicht des Entwicklungsboards" : isFr ? "Ceci est le schéma de la puce, pas de la carte de développement" : isEs ? "Este es el diagrama del chip, no de la placa" : isEn ? "This is the chip diagram, not the development board" : "Este é o diagrama do chip, não da placa"}
</p>
<p className="mt-1">
{isZh ? ( `该图展示了 ${key} 的芯片内部连接。每块开发板只会引出其中一部分,或做不同的走线。` ) : isDe ? (
`Das Diagramm zeigt die Silizium-Anschlüsse des ${key}. Jedes Entwicklungsboard führt nur einen Teil heraus oder leitet sie anders weiter.`
) : isFr ? (
`Le schéma montre les connexions du silicium du ${key}. Chaque carte de développement n'en expose qu'une partie ou les route différemment.`
) : isEs ? (
`El mapa muestra las conexiones del silicio del ${key}. Cada placa de desarrollo expone solo parte de ellas o las enruta de otra forma.`
) : isEn ? (
`The map shows the silicon connections for the ${key}. Each development board exposes only a subset or routes them differently.`
) : (
<>
O mapa mostra as conexões do silício do <strong>{key}</strong>. Cada placa de desenvolvimento
expõe só parte delas, ou as roteia de outra forma.
</>
)}
</p>
</div>
</div>
<div className="mt-6">
<ConnectionsDiagram connections={conexoes} serie={serie} />
</div>
<div className="callout mt-8">
<p className="flex items-center gap-2 font-semibold text-ink">
<Lightbulb className="h-4 w-4 text-accent" aria-hidden="true" />
{isZh ? "几乎每个引脚都可重新配置" : isDe ? "Nahezu jeder Pin ist rekonfigurierbar" : isFr ? "La quasi-totalité des broches est reconfigurable" : isEs ? "Casi todos los pines son reconfigurables" : isEn ? "Almost every pin is reconfigurable" : "Quase todo pino é reconfigurável"}
</p>
<p className="mt-1">
{isZh ? (
<>
{key} 的 IO 矩阵可以把 SPI、I2C、UART、PWM 以及摄像头/显示总线移到大多数数字引脚上。关于启动配置引脚的限制和模拟引脚,请查阅{" "}
<a
href={`https://docs.espressif.com/projects/esp-idf/en/latest/${String(key).toLowerCase().replace("-", "")}/api-reference/peripherals/gpio.html`}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1 font-medium text-accent underline decoration-accent/30 underline-offset-2 hover:decoration-accent"
>
官方 GPIO 指南
<ExternalLink className="h-3.5 w-3.5" aria-hidden="true" />
</a>
。
</>
) : isDe ? (
<>
Die IO-Matrix des {key} ermöglicht das Zuweisen von SPI, I2C, UART, PWM und Kamera-/Displaybussen
zu den meisten digitalen Pins. Für Strapping-Einschränkungen und analoge Pins konsultieren Sie den{" "}
<a
href={`https://docs.espressif.com/projects/esp-idf/en/latest/${String(key).toLowerCase().replace("-", "")}/api-reference/peripherals/gpio.html`}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1 font-medium text-accent underline decoration-accent/30 underline-offset-2 hover:decoration-accent"
>
offiziellen GPIO-Leitfaden
<ExternalLink className="h-3.5 w-3.5" aria-hidden="true" />
</a>
.
</>
) : isFr ? (
<>
La matrice d'E/S du {key} permet d'assigner SPI, I2C, UART, PWM et bus caméra/écran
à la majorité des broches numériques. Pour les restrictions de strapping et broches analogiques,
consultez le{" "}
<a
href={`https://docs.espressif.com/projects/esp-idf/en/latest/${String(key).toLowerCase().replace("-", "")}/api-reference/peripherals/gpio.html`}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1 font-medium text-accent underline decoration-accent/30 underline-offset-2 hover:decoration-accent"
>
guide officiel GPIO
<ExternalLink className="h-3.5 w-3.5" aria-hidden="true" />
</a>
.
</>
) : isEs ? (
<>
La matriz de E/S del {key} permite mover buses SPI, I2C, UART, PWM y cámara/pantalla
a la mayoría de los pines digitales. Para las restricciones de strapping y pines analógicos,
consulte la{" "}
<a
href={`https://docs.espressif.com/projects/esp-idf/en/latest/${String(key).toLowerCase().replace("-", "")}/api-reference/peripherals/gpio.html`}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1 font-medium text-accent underline decoration-accent/30 underline-offset-2 hover:decoration-accent"
>
guía oficial de GPIO
<ExternalLink className="h-3.5 w-3.5" aria-hidden="true" />
</a>
.
</>
) : isEn ? (
<>
The {key} IO matrix allows moving SPI, I2C, UART, PWM, and camera/display buses
to most digital pins. For strapping restrictions and analog pins, consult the{" "}
<a
href={`https://docs.espressif.com/projects/esp-idf/en/latest/${String(key).toLowerCase().replace("-", "")}/api-reference/peripherals/gpio.html`}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1 font-medium text-accent underline decoration-accent/30 underline-offset-2 hover:decoration-accent"
>
official GPIO guide
<ExternalLink className="h-3.5 w-3.5" aria-hidden="true" />
</a>
.
</>
) : (
<>
A matriz de IO do {key} permite mover SPI, I2C, UART, PWM e barramentos de câmera ou display
para a maioria dos pinos digitais. Para as restrições de strapping e dos pinos analógicos,
consulte o{" "}
<a
href={`https://docs.espressif.com/projects/esp-idf/en/latest/${String(key).toLowerCase().replace("-", "")}/api-reference/peripherals/gpio.html`}
target="_blank"
rel="noopener noreferrer"
className="inline-flex items-center gap-1 font-medium text-accent underline decoration-accent/30 underline-offset-2 hover:decoration-accent"
>
guia oficial de GPIO
<ExternalLink className="h-3.5 w-3.5" aria-hidden="true" />
</a>
.
</>
)}
</p>
</div>
</div>
),
},
];
const secoes = [
{ id: "processador", titulo: isZh ? "处理器" : isDe ? "Prozessor" : isFr ? "Processeur" : isEs ? "Procesador" : isEn ? "Processor" : "Processador", icon: Cpu, specs: processadorSpecs },
{ id: "conectividade", titulo: isZh ? "无线连接" : isDe ? "Konnektivität" : isFr ? "Connectivité" : isEs ? "Conectividad" : isEn ? "Connectivity" : "Conectividade", icon: Wifi, specs: conectividadeSpecs },
{ id: "ferramentas", titulo: isZh ? "工具与可用性" : isDe ? "Werkzeuge und Verfügbarkeit" : isFr ? "Outils et disponibilité" : isEs ? "Herramientas y disponibilidad" : isEn ? "Tools and availability" : "Ferramentas e disponibilidade", icon: Package, specs: ferramentasSpecs },
{ id: "seguranca", titulo: isZh ? "安全" : isDe ? "Sicherheit" : isFr ? "Sécurité" : isEs ? "Seguridad" : isEn ? "Security" : "Segurança", icon: ShieldCheck, specs: segurancaSpecs },
{ id: "memoria", titulo: isZh ? "内存" : isDe ? "Speicher" : isFr ? "Mémoire" : isEs ? "Memoria" : isEn ? "Memory" : "Memória", icon: Database, specs: memoriaSpecs },
...(consumoEnergia.length > 0
? [{
id: "energia",
titulo: isZh ? "功耗" : isDe ? "Stromverbrauch" : isFr ? "Consommation d'énergie" : isEs ? "Consumo de energía" : isEn ? "Power consumption" : "Consumo de energia",
icon: Battery,
specs: consumoEnergia,
nota: isZh ? "典型值,条件为 3.3 V、25 °C。实际功耗取决于射频占空比和所配置的时钟频率。" : isDe
? "Typische Werte bei 3,3 V und 25 °C. Der tatsächliche Stromverbrauch hängt vom Funk-Tastgrad und der konfigurierten Taktfrequenz ab."
: isFr
? "Valeurs typiques à 3,3 V et 25 °C. La consommation réelle dépend du cycle de travail de la radio et de la fréquence d'horloge configurée."
: isEs
? "Valores típicos a 3,3 V y 25 °C. El consumo real depende del ciclo de trabajo de la radio y de la frecuencia de reloj configurada."
: isEn
? "Typical values at 3.3 V and 25 °C. Actual power consumption depends on radio duty cycle and configured clock frequency."
: "Valores típicos a 3,3 V e 25 °C. O consumo real depende do ciclo de trabalho do rádio e da frequência de clock configurada.",
}]
: []),
{ id: "perifericos", titulo: isZh ? "外设" : isDe ? "Peripherie" : isFr ? "Périphériques" : isEs ? "Periféricos" : isEn ? "Peripherals" : "Periféricos", icon: Sliders, specs: perifericos },
...(interfacesEspeciais.length > 0
? [{ id: "interfaces", titulo: isZh ? "特殊接口" : isDe ? "Spezielle Schnittstellen" : isFr ? "Interfaces spéciales" : isEs ? "Interfaces especiales" : isEn ? "Special interfaces" : "Interfaces especiais", icon: Sliders, specs: interfacesEspeciais }]
: []),
{
id: "temperatura",
titulo: isZh ? "温度范围" : isDe ? "Temperaturgrenzwerte" : isFr ? "Limites de température" : isEs ? "Límites de temperatura" : isEn ? "Temperature limits" : "Limites de temperatura",
icon: Thermometer,
specs: [
{ label: isZh ? "工作" : isDe ? "Betrieb" : isFr ? "Fonctionnement" : isEs ? "Operación" : isEn ? "Operating" : "Operação", value: serie.temperatura_operacao },
{ label: isZh ? "存储" : isDe ? "Lagerung" : isFr ? "Stockage" : isEs ? "Almacenamiento" : isEn ? "Storage" : "Armazenamento", value: serie.temperatura_armazenamento },
],
},
];
const fatos = [
{ label: isZh ? "处理器" : isDe ? "Prozessor" : isFr ? "Processeur" : isEs ? "Procesador" : isEn ? "Processor" : "Processador", value: String(serie.nucleos).includes("2") ? "Dual-core" : "Single-core", detail: serie.frequencia },
{ label: "SRAM", value: serie.memoria_sram, detail: isZh ? `+ ${serie.memoria_sram_rtc} RTC SRAM` : isDe ? `+ ${serie.memoria_sram_rtc} RTC-SRAM` : isFr ? `+ ${serie.memoria_sram_rtc} de SRAM RTC` : isEs ? `+ ${serie.memoria_sram_rtc} de SRAM RTC` : isEn ? `+ ${serie.memoria_sram_rtc} RTC SRAM` : `+ ${serie.memoria_sram_rtc} de SRAM RTC` },
{ label: "GPIO", value: serie.gpio, detail: isZh ? "个可编程引脚" : isDe ? "programmierbare Pins" : isFr ? "broches programmables" : isEs ? "pines programables" : isEn ? "programmable pins" : "pinos programáveis" },
{ label: isZh ? "架构" : isDe ? "Architektur" : isFr ? "Architecture" : isEs ? "Arquitectura" : isEn ? "Architecture" : "Arquitetura", value: String(serie.arquitetura).includes("RISC-V") ? "RISC-V" : "Xtensa", detail: serie.arquitetura },
];
return (
<div className="site-canvas min-h-screen">
<script
type="application/ld+json"
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd.serie(key, serie, currentLocale)) }}
/>
<script
type="application/ld+json"
dangerouslySetInnerHTML={{
__html: JSON.stringify(jsonLd.trilha([
{ nome: isZh ? "首页" : isDe ? "Startseite" : isFr ? "Accueil" : isEs ? "Inicio" : isEn ? "Home" : "Início", caminho: isZh ? "/zh-CN" : isDe ? "/de" : isFr ? "/fr" : isEn ? "/en" : isEs ? "/es" : "/" },
{ nome: isZh ? "ESP32 系列" : isDe ? "ESP32-Serien" : isFr ? "Séries ESP32" : isEs ? "Series ESP32" : isEn ? "ESP32 Series" : "Séries ESP32", caminho: getLocalizedHref("/series", currentLocale) },
{ nome: serie.nome_completo, caminho: getLocalizedHref(`/series/${key}`, currentLocale) },
])),
}}
/>
<Header />
<main id="conteudo">
<PageHero
isEn={isEn}
isEs={isEs}
isFr={isFr}
isDe={isDe} isZh={isZh}
trail={[{ label: isZh ? "系列" : isDe ? "Serien" : isFr ? "Séries" : isEs ? "Series" : isEn ? "Series" : "Séries", href: getLocalizedHref("/series", currentLocale) }, { label: key }]}
icon={Cpu}
label={serie.arquitetura}
title={key}
lede={serie.descricao}
>
{serie.datasheet ? (
<a href={serie.datasheet} target="_blank" rel="noopener noreferrer" className="btn btn-primary">
<FileText className="h-4 w-4" aria-hidden="true" />
{isZh ? "官方数据手册" : isDe ? "Offizielles Datenblatt" : isFr ? "Datasheet officiel" : isEs ? "Datasheet oficial" : isEn ? "Official datasheet" : "Datasheet oficial"}
<ArrowUpRight className="h-4 w-4" aria-hidden="true" />
</a>
) : (
<span className="btn btn-ghost cursor-not-allowed opacity-70" aria-disabled="true">
<FileText className="h-4 w-4" aria-hidden="true" />
{isZh ? "数据手册尚未发布" : isDe ? "Datenblatt noch nicht veröffentlicht" : isFr ? "Datasheet pas encore publié" : isEs ? "Datasheet aún no publicado" : isEn ? "Datasheet not yet published" : "Datasheet ainda não publicado"}
</span>
)}
{serie.guia_de_programacao && (
<a href={serie.guia_de_programacao} target="_blank" rel="noopener noreferrer" className="btn btn-ghost">
<Code className="h-4 w-4" aria-hidden="true" />
{isZh ? "编程指南" : isDe ? "Programmierleitfaden" : isFr ? "Guide de programmation" : isEs ? "Guía de programación" : isEn ? "Programming guide" : "Guia de programação"}
<ArrowUpRight className="h-4 w-4" aria-hidden="true" />
</a>
)}
{serie.manual_tecnico && (
<a href={serie.manual_tecnico} target="_blank" rel="noopener noreferrer" className="btn btn-ghost">
<BookOpen className="h-4 w-4" aria-hidden="true" />
{isZh ? "技术参考手册" : isDe ? "Technisches Referenzhandbuch" : isFr ? "Manuel technique de référence" : isEs ? "Manual de referencia técnica" : isEn ? "Technical reference manual" : "Manual técnico"}
<ArrowUpRight className="h-4 w-4" aria-hidden="true" />
</a>
)}
</PageHero>
<section className="shell mt-10" aria-label={isZh ? "概要" : isDe ? "Zusammenfassung" : isFr ? "Résumé" : isEs ? "Resumen" : isEn ? "Summary" : "Resumo"}>
<dl className="grid grid-cols-2 gap-3 lg:grid-cols-4">
{fatos.map((fato) => (
<div key={fato.label} className="tile">
<dt className="text-xs font-medium text-muted">{fato.label}</dt>
<dd className="mt-1 font-display text-2xl font-semibold tracking-[-0.03em] text-ink">{fato.value}</dd>
<dd className="mt-0.5 text-xs text-muted">{fato.detail}</dd>
</div>
))}
</dl>
{serie.status_documentacao && (
<div className="callout callout-warn mt-4 flex items-start gap-3">
<AlertTriangle className="mt-0.5 h-5 w-5 shrink-0 text-gold" aria-hidden="true" />
<div>
<p className="font-semibold text-ink">
{isZh ? "初步文档" : isDe ? "Vorläufige Dokumentation" : isFr ? "Documentation préliminaire" : isEs ? "Documentación preliminar" : isEn ? "Preliminary documentation" : "Documentação preliminar"}
</p>
<p className="mt-1">{serie.status_documentacao}</p>
</div>
</div>
)}
</section>
<div className="shell mt-10">
<SeriesTabMenu tabs={tabs} isEn={isEn} isEs={isEs} isFr={isFr} isDe={isDe} isZh={isZh} />
<PlacasSugeridas chips={[key]} className="mt-5" />
<PinRestrictions conexoes={conexoes} serieKey={key} isEn={isEn} isEs={isEs} isFr={isFr} isDe={isDe} isZh={isZh} />
</div>
<div className="shell mt-12">
<nav
aria-label={isZh ? "数据手册章节" : isDe ? "Abschnitte des Datenblatts" : isFr ? "Sections de la fiche" : isEs ? "Secciones de la ficha" : isEn ? "Datasheet sections" : "Seções da ficha"}
className="nav-pill no-scrollbar sticky top-20 z-30 flex gap-1 overflow-x-auto rounded-full p-1.5"
>
{secoes.map((secao) => (
<a key={secao.id} href={`#${secao.id}`} className="nav-link shrink-0">
{secao.titulo}
</a>
))}
</nav>
<div className="mt-8 space-y-5">
{secoes.map((secao) => (
<SpecSection key={secao.id} {...secao} />
))}
</div>
</div>
<section className="shell section">
<div className="panel flex flex-col items-start justify-between gap-6 p-7 sm:p-10 md:flex-row md:items-center">
<div className="max-w-2xl">
<h2 className="section-title">
{isZh ? ( <>准备好用 {key} 做原型了吗?</> ) : isDe ? (
<>Bereit zum Prototyping mit {key}?</>
) : isFr ? (
<>Prêt à prototyper avec {key} ?</>
) : isEs ? (
<>¿Listo para prototipar con {key}?</>
) : isEn ? (
<>Ready to prototype with {key}?</>
) : (
<>Pronto para prototipar o {key}?</>
)}
</h2>
<p className="mt-3 text-base text-muted">
{isZh ? "查看这个系列可用的开发板,含 USB、板载传感器和官方商店链接。" : isDe
? "Entdecken Sie die für diese Serie verfügbaren Entwicklungsboards mit USB, integrierten Sensoren und Links zum offiziellen Shop."
: isFr
? "Explorez les cartes de développement disponibles pour cette série, avec USB, capteurs intégrés et liens vers la boutique officielle."
: isEs
? "Explore las placas de desarrollo disponibles para esta serie, con USB, sensores integrados y enlaces a la tienda oficial."
: isEn
? "Explore development boards available for this series, with USB, onboard sensors, and official store links."
: "Veja as placas de desenvolvimento disponíveis para a série, com USB, sensores integrados e link para a loja oficial."}
</p>
</div>
<Link href={getLocalizedHref("/catalogo", currentLocale)} className="btn btn-primary shrink-0">
{isZh ? "查看开发板" : isDe ? "Boards ansehen" : isFr ? "Voir les cartes" : isEs ? "Ver placas" : isEn ? "View boards" : "Ver placas"}
<ArrowRight className="h-4 w-4" aria-hidden="true" />
</Link>
</div>
<nav aria-label={isZh ? "其他系列" : isDe ? "Andere Serien" : isFr ? "Autres séries" : isEs ? "Otras series" : isEn ? "Other series" : "Outras séries"} className="mt-6 grid gap-3 sm:grid-cols-[1fr_auto_1fr] sm:items-center">
{previousKey ? (
<Link href={getLocalizedHref(`/series/${previousKey}`, currentLocale)} className="card card-interactive group flex items-center gap-3 px-5 py-4">
<ArrowLeft className="h-4 w-4 text-muted transition-transform group-hover:-translate-x-1" aria-hidden="true" />
<span>
<span className="block text-xs text-muted">{isZh ? "上一个系列" : isDe ? "Vorherige Serie" : isFr ? "Série précédente" : isEs ? "Serie anterior" : isEn ? "Previous series" : "Série anterior"}</span>
<span className="block font-display text-lg font-semibold text-ink">{previousKey}</span>
</span>
</Link>
) : (
<span className="hidden sm:block" />
)}
<Link href={getLocalizedHref("/comparacao", currentLocale)} className="btn btn-ghost justify-self-center">
<Scale className="h-4 w-4" aria-hidden="true" />
{isZh ? "对比系列" : isDe ? "Serien vergleichen" : isFr ? "Comparer les séries" : isEs ? "Comparar series" : isEn ? "Compare series" : "Comparar séries"}
</Link>
{nextKey ? (
<Link href={getLocalizedHref(`/series/${nextKey}`, currentLocale)} className="card card-interactive group flex items-center justify-end gap-3 px-5 py-4 text-right">
<span>
<span className="block text-xs text-muted">{isZh ? "下一个系列" : isDe ? "Nächste Serie" : isFr ? "Série suivante" : isEs ? "Siguiente serie" : isEn ? "Next series" : "Próxima série"}</span>
<span className="block font-display text-lg font-semibold text-ink">{nextKey}</span>
</span>
<ArrowRight className="h-4 w-4 text-muted transition-transform group-hover:translate-x-1" aria-hidden="true" />
</Link>
) : (
<span className="hidden sm:block" />
)}
</nav>
</section>
</main>
<Footer />
</div>
);
}
function SpecSection({ id, titulo, icon: Icon, specs, nota }) {
return (
<section id={id} aria-labelledby={`${id}-titulo`} className="card scroll-mt-36 p-5 sm:p-7">
<h2 id={`${id}-titulo`} className="flex items-center gap-3 font-display text-xl font-semibold tracking-[-0.03em] text-ink">
<span className="grid h-9 w-9 place-items-center rounded-full bg-accent-soft text-accent">
<Icon className="h-4 w-4" aria-hidden="true" />
</span>
{titulo}
</h2>
{nota && <p className="mt-3 text-sm text-muted">{nota}</p>}
<dl className="mt-5 grid grid-cols-2 gap-3 lg:grid-cols-3">
{specs.map((spec) => {
const negativo = /^n[ãa]o\b|^no\b/i.test(String(spec.value));
return (
<div key={spec.label} className="tile">
<dt className="text-xs font-medium text-muted">{spec.label}</dt>
<dd className={`mt-1 text-sm font-semibold leading-snug ${negativo ? "text-muted" : "text-ink"}`}>{spec.value}</dd>
</div>
);
})}
</dl>
</section>
);
}
export async function generateMetadata({ params }) {
const { locale, key } = await params;
const isEn = locale === "en";
const isEs = locale === "es";
const isFr = locale === "fr";
const isDe = locale === "de";
const isZh = locale === "zh-CN";
const currentLocale = isZh ? "zh-CN" : isDe ? "de" : isFr ? "fr" : isEs ? "es" : isEn ? "en" : "pt";
const seriesData = isZh ? seriesDataZh : isDe ? seriesDataDe : isFr ? seriesDataFr : isEs ? seriesDataEs : isEn ? seriesDataEn : seriesDataPt;
const serie = seriesData[key];
if (!serie) {
return {
title: isZh ? "未找到该系列" : isDe
? "Serie nicht gefunden"
: isFr
? "Série non trouvée"
: isEs
? "Serie no encontrada"
: isEn
? "Series not found"
: "Série não encontrada",
robots: { index: false, follow: false },
};
}
const radio = [
String(serie.wifi).startsWith("Não") || String(serie.wifi).startsWith("No") ? null : serie.wifi.split(" (")[0],
String(serie.bluetooth).startsWith("Não") || String(serie.bluetooth).startsWith("No") ? null : serie.bluetooth.split(" (")[0],
serie.zigbee_thread && !String(serie.zigbee_thread).startsWith("Não") && !String(serie.zigbee_thread).startsWith("No") ? "802.15.4" : null,
].filter(Boolean).join(", ");
const descricao = isZh ? `${serie.nome_completo}:${serie.arquitetura},${serie.frequencia},` +
`${serie.memoria_sram} SRAM,${serie.gpio} 个 GPIO` +
(radio ? `。无线:${radio}` : "") +
`。含完整引脚图、外设、硬件安全与受限引脚的简体中文说明。` : isDe
? `${serie.nome_completo}: ${serie.arquitetura}, ${serie.frequencia}, ` +
`${serie.memoria_sram} SRAM und ${serie.gpio} GPIOs` +
(radio ? `. Funk: ${radio}` : "") +
`. Vollständige Pinbelegung, Peripherie, Hardwaresicherheit und eingeschränkte Pins auf Deutsch.`
: isFr
? `${serie.nome_completo} : ${serie.arquitetura}, ${serie.frequencia}, ` +
`${serie.memoria_sram} de SRAM et ${serie.gpio} GPIO` +
(radio ? `. Radio : ${radio}` : "") +
`. Brochage complet, périphériques, sécurité matérielle et broches avec restrictions, en français.`
: isEs
? `${serie.nome_completo}: ${serie.arquitetura}, ${serie.frequencia}, ` +
`${serie.memoria_sram} de SRAM y ${serie.gpio} GPIO` +
(radio ? `. Radio: ${radio}` : "") +
`. Patillaje completo, periféricos, seguridad por hardware y pines restringidos, en español.`
: isEn
? `${serie.nome_completo}: ${serie.arquitetura}, ${serie.frequencia}, ` +
`${serie.memoria_sram} SRAM, and ${serie.gpio} GPIOs` +
(radio ? `. Radio: ${radio}` : "") +
`. Complete pinout, peripherals, hardware security, and restricted pins in English.`
: `${serie.nome_completo}: ${serie.arquitetura}, ${serie.frequencia.replace("Até ", "até ")}, ` +
`${serie.memoria_sram} de SRAM e ${serie.gpio} GPIOs` +
(radio ? `. Rádio: ${radio}` : "") +
`. Pinagem completa, periféricos, segurança em hardware e pinos com restrição, em português.`;
const imagem = serie.placa
? [{ url: serie.placa, width: 1600, height: 1091, alt: isZh ? `${serie.nome_completo} 的引脚图` : isDe ? `Pinbelegung von ${serie.nome_completo}` : isFr ? `Brochage de ${serie.nome_completo}` : isEs ? `Patillaje de ${serie.nome_completo}` : isEn ? `Pinout of ${serie.nome_completo}` : `Pinagem do ${serie.nome_completo}` }]
: [{ url: "/opengraph-image.png", width: 1200, height: 630, alt: "ESPDocs" }];
const keywords = isZh ? [ serie.nome_completo, `${serie.nome_completo} 引脚图`, `${serie.nome_completo} 数据手册`, `${serie.nome_completo} 规格`, "ESP32", "乐鑫", "微控制器", ] : isDe
? [
serie.nome_completo, `${serie.nome_completo} pinout`, `${serie.nome_completo} Pinbelegung`,
`${serie.nome_completo} datasheet`, `${serie.nome_completo} Spezifikationen`,
`${serie.nome_completo} deutsch`, "ESP32", "Espressif", "Mikrocontroller",
]
: isFr
? [
serie.nome_completo, `${serie.nome_completo} pinout`, `${serie.nome_completo} brochage`,
`${serie.nome_completo} datasheet`, `${serie.nome_completo} spécifications`,
`${serie.nome_completo} français`, "ESP32", "Espressif", "microcontrôleur",
]
: isEs
? [
serie.nome_completo, `${serie.nome_completo} pinout`, `${serie.nome_completo} patillaje`,
`${serie.nome_completo} datasheet`, `${serie.nome_completo} especificaciones`,
`${serie.nome_completo} español`, "ESP32", "Espressif", "microcontrolador",
]
: isEn
? [
serie.nome_completo, `${serie.nome_completo} pinout`,
`${serie.nome_completo} datasheet`, `${serie.nome_completo} specifications`,
"ESP32", "Espressif", "microcontroller",
]
: [
serie.nome_completo, `${serie.nome_completo} pinout`,
`${serie.nome_completo} datasheet`, `${serie.nome_completo} especificações`,
`${serie.nome_completo} português`, "ESP32", "Espressif", "microcontrolador",
];
const meta = {
...paginaMeta({
titulo: isZh ? `${serie.nome_completo}:规格与引脚图` : isDe
? `${serie.nome_completo}: Spezifikationen und Pinbelegung`
: isFr
? `${serie.nome_completo} : spécifications et brochage`
: isEs
? `${serie.nome_completo}: especificaciones y patillaje`
: isEn
? `${serie.nome_completo}: specifications and pinout`
: `${serie.nome_completo}: especificações e pinagem`,
descricao,
caminho: `/series/${key}`,
tipo: "article",
locale: currentLocale,
keywords,
}),
other: {
"article:section": isZh ? "ESP32 系列" : isDe
? "ESP32-Serien"
: isFr
? "Séries ESP32"
: isEs
? "Series ESP32"
: isEn
? "ESP32 Series"
: "Séries ESP32",
},
};
meta.openGraph = { ...meta.openGraph, images: imagem };
meta.twitter = { ...meta.twitter, images: imagem };
return meta;
}
export async function generateStaticParams() {
return Object.keys(seriesDataPt).map((key) => ({
key: key,
}));
}