CI / Lint e auditorias (push) Successful in 1m10s
CI / Trivy (dependências e segredos) (push) Successful in 12s
CI / Imagem Docker (linux/arm64) (push) Successful in 2m39s
Release / Plano (reaproveitar a imagem?) (push) Successful in 6s
Release / ci (push) Skipped
Release / Publica a imagem (linux/arm64) (push) Successful in 18s
Release / Cria a release no Gitea (push) Successful in 5s
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
277 lines
15 KiB
React
277 lines
15 KiB
React
import { paginaMeta, jsonLd } from "@/lib/seo";
|
||
import Link from "next/link";
|
||
import Header from "@/components/Header";
|
||
import Footer from "@/components/Footer";
|
||
import PageHero from "@/components/PageHero";
|
||
import { notFound } from "next/navigation";
|
||
import CodeExample from "@/components/CodeExample";
|
||
import frameworksDataPt from "@/public/frameworks.json";
|
||
import frameworksDataEn from "@/data/en/frameworks.json";
|
||
import frameworksDataEs from "@/data/es/frameworks.json";
|
||
import frameworksDataFr from "@/data/fr/frameworks.json";
|
||
import frameworksDataDe from "@/data/de/frameworks.json";
|
||
import frameworksDataZh from "@/data/zh-CN/frameworks.json";
|
||
import { getLocalizedHref } from "@/i18n/links";
|
||
import { ArrowRight, ArrowUpRight, BookOpen, Box, Check, Code, Layers } from "lucide-react";
|
||
|
||
export default async function FrameworkDetail({ 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 = isEs ? "es" : isEn ? "en" : isFr ? "fr" : isZh ? "zh-CN" : isDe ? "de" : "pt";
|
||
const frameworksData = isEs ? frameworksDataEs : isEn ? frameworksDataEn : isFr ? frameworksDataFr : isZh ? frameworksDataZh : isDe ? frameworksDataDe : frameworksDataPt;
|
||
const framework = frameworksData[key];
|
||
|
||
if (!framework) {
|
||
notFound();
|
||
}
|
||
|
||
const features = framework.caracteristicas || [];
|
||
const useCases = framework.casos_uso || [];
|
||
const isEspIdf = key === "ESP-IDF";
|
||
|
||
return (
|
||
<div className="site-canvas min-h-screen">
|
||
{/* Ficha técnica do framework e trilha de navegação para o Google */}
|
||
<script
|
||
type="application/ld+json"
|
||
dangerouslySetInnerHTML={{ __html: JSON.stringify(jsonLd.framework(key, framework, currentLocale)) }}
|
||
/>
|
||
<script
|
||
type="application/ld+json"
|
||
dangerouslySetInnerHTML={{
|
||
__html: JSON.stringify(jsonLd.trilha([
|
||
{ nome: isEs ? "Inicio" : isEn ? "Home" : isFr ? "Accueil" : isZh ? "首页" : isDe ? "Startseite" : "Início", caminho: isEs ? "/es" : isEn ? "/en" : isFr ? "/fr" : isZh ? "/zh-CN" : isDe ? "/de" : "/" },
|
||
{ nome: "Frameworks", caminho: getLocalizedHref("/frameworks", currentLocale) },
|
||
{ nome: framework.nome, caminho: getLocalizedHref(`/frameworks/${encodeURIComponent(key)}`, currentLocale) },
|
||
])),
|
||
}}
|
||
/>
|
||
|
||
<Header />
|
||
|
||
<main id="conteudo">
|
||
<PageHero
|
||
isEn={isEn}
|
||
isEs={isEs}
|
||
isFr={isFr}
|
||
isDe={isDe} isZh={isZh}
|
||
trail={[{ label: isEs ? "Frameworks y SDKs" : isEn ? "Frameworks & SDKs" : isFr ? "Frameworks et SDKs" : isZh ? "框架与 SDK" : isDe ? "Frameworks & SDKs" : "Frameworks e SDKs", href: getLocalizedHref("/frameworks", currentLocale) }, { label: framework.nome }]}
|
||
icon={Layers}
|
||
label={framework.tipo}
|
||
title={framework.nome}
|
||
lede={framework.descricao}
|
||
>
|
||
{framework.documentacao && (
|
||
<a href={framework.documentacao} target="_blank" rel="noopener noreferrer" className="btn btn-primary">
|
||
<BookOpen className="h-4 w-4" aria-hidden="true" />
|
||
{isEs ? "Documentación oficial" : isEn ? "Official documentation" : isFr ? "Documentation officielle" : isZh ? "官方文档" : isDe ? "Offizielle Dokumentation" : "Documentação oficial"}
|
||
<ArrowUpRight className="h-4 w-4" aria-hidden="true" />
|
||
</a>
|
||
)}
|
||
{framework.repositorio && (
|
||
<a href={framework.repositorio} target="_blank" rel="noopener noreferrer" className="btn btn-ghost">
|
||
<Code className="h-4 w-4" aria-hidden="true" />
|
||
{isEs ? "Repositorio en GitHub" : isEn ? "GitHub repository" : isFr ? "Dépôt sur GitHub" : isZh ? "GitHub 仓库" : isDe ? "GitHub-Repository" : "Repositório no GitHub"}
|
||
<ArrowUpRight className="h-4 w-4" aria-hidden="true" />
|
||
</a>
|
||
)}
|
||
</PageHero>
|
||
|
||
<section className="shell mt-10" aria-label={isEs ? "Resumen" : isEn ? "Summary" : isFr ? "Résumé" : isZh ? "概览" : isDe ? "Übersicht" : "Resumo"}>
|
||
<dl className="grid gap-3 md:grid-cols-3">
|
||
<div className="tile">
|
||
<dt className="text-xs font-medium text-muted">{isEs ? "Lenguaje" : isEn ? "Language" : isFr ? "Langage" : isZh ? "语言" : isDe ? "Sprache" : "Linguagem"}</dt>
|
||
<dd className="mt-1 font-display text-2xl font-semibold tracking-[-0.03em] text-ink">{framework.linguagem}</dd>
|
||
<dd className="mt-0.5 text-xs text-muted">{framework.nome_completo}</dd>
|
||
</div>
|
||
<div className="tile">
|
||
<dt className="text-xs font-medium text-muted">{isEs ? "Categoría" : isEn ? "Category" : isFr ? "Catégorie" : isZh ? "类别" : isDe ? "Kategorie" : "Categoria"}</dt>
|
||
<dd className="mt-1 font-display text-2xl font-semibold tracking-[-0.03em] text-ink">{framework.tipo}</dd>
|
||
</div>
|
||
<div className="tile">
|
||
<dt className="text-xs font-medium text-muted">{isEs ? "Objetivo principal" : isEn ? "Main purpose" : isFr ? "Objectif principal" : isZh ? "主要目标" : isDe ? "Hauptzweck" : "Objetivo principal"}</dt>
|
||
<dd className="mt-1 text-sm font-medium leading-relaxed text-ink">{framework.funcao_principal}</dd>
|
||
</div>
|
||
</dl>
|
||
</section>
|
||
|
||
<section className="shell mt-12 grid gap-5 lg:grid-cols-2" aria-label={isEs ? "Funciones y aplicaciones" : isEn ? "Features and applications" : isFr ? "Fonctionnalités et applications" : isZh ? "功能与应用" : isDe ? "Features und Anwendungen" : "Recursos e aplicações"}>
|
||
<div className="card p-5 sm:p-7">
|
||
<h2 className="font-display text-xl font-semibold tracking-[-0.03em] text-ink">
|
||
{isEs ? "Funciones destacadas" : isEn ? "Key features" : isFr ? "Fonctionnalités clés" : isZh ? "亮点功能" : isDe ? "Wichtigste Features" : "Recursos de destaque"}
|
||
</h2>
|
||
<ul className="mt-5 space-y-3">
|
||
{features.map((feature) => (
|
||
<li key={feature} className="flex items-start gap-3 text-sm leading-relaxed text-ink-soft">
|
||
<Check className="mt-0.5 h-4 w-4 shrink-0 text-ok" aria-hidden="true" />
|
||
{feature}
|
||
</li>
|
||
))}
|
||
</ul>
|
||
</div>
|
||
|
||
<div className="card p-5 sm:p-7">
|
||
<h2 className="font-display text-xl font-semibold tracking-[-0.03em] text-ink">
|
||
{isEs ? "Cuándo usar" : isEn ? "When to use" : isFr ? "Quand l'utiliser" : isZh ? "适用场景" : isDe ? "Einsatzbereiche" : "Quando usar"}
|
||
</h2>
|
||
<ul className="mt-5 space-y-2.5">
|
||
{useCases.map((useCase) => (
|
||
<li key={useCase} className="tile text-sm font-medium text-ink-soft">
|
||
{useCase}
|
||
</li>
|
||
))}
|
||
</ul>
|
||
</div>
|
||
</section>
|
||
|
||
{isEspIdf && (
|
||
<section className="shell mt-8">
|
||
<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">
|
||
<span className="chip chip-accent">
|
||
<Box className="h-3.5 w-3.5" aria-hidden="true" />
|
||
{isEs ? "ESP-IDF 4.4 o superior" : isEn ? "ESP-IDF 4.4 or higher" : isFr ? "ESP-IDF 4.4 ou supérieur" : isZh ? "ESP-IDF 4.4 或更高版本" : isDe ? "ESP-IDF 4.4 oder höher" : "ESP-IDF 4.4 ou superior"}
|
||
</span>
|
||
<h2 className="section-title mt-4">
|
||
{isEs ? "Módulos con ESP Component Registry" : isEn ? "Modules with the ESP Component Registry" : isFr ? "Modules avec l'ESP Component Registry" : isZh ? "借助 ESP Component Registry 使用模块" : isDe ? "Module mit der ESP Component Registry" : "Módulos com o ESP Component Registry"}
|
||
</h2>
|
||
<p className="mt-3 text-base leading-relaxed text-muted">
|
||
{isEs ? (
|
||
<>
|
||
En los proyectos ESP-IDF v4.4+ y v5.x, las bibliotecas ya no necesitan agregarse como submódulos Git. Utilice el{" "}
|
||
<code className="rounded bg-surface-2 px-1.5 py-0.5 font-mono text-sm">idf_component.yml</code> y el comando{" "}
|
||
<code className="rounded bg-surface-2 px-1.5 py-0.5 font-mono text-sm">idf.py add-dependency</code> para descargar controladores de pantalla (LVGL), pilas industriales (Modbus), RainMaker y más.
|
||
</>
|
||
) : isEn ? (
|
||
<>
|
||
In ESP-IDF v4.4+ and v5.x projects, libraries no longer need to be added as Git submodules. Use{" "}
|
||
<code className="rounded bg-surface-2 px-1.5 py-0.5 font-mono text-sm">idf_component.yml</code> and the command{" "}
|
||
<code className="rounded bg-surface-2 px-1.5 py-0.5 font-mono text-sm">idf.py add-dependency</code> to download display drivers (LVGL), industrial stacks (Modbus), RainMaker, and more.
|
||
</>
|
||
) : isFr ? (
|
||
<>
|
||
Dans les projets ESP-IDF v4.4+ et v5.x, les bibliothèques n'ont plus besoin d'être ajoutées comme sous-modules Git. Utilisez le fichier{" "}
|
||
<code className="rounded bg-surface-2 px-1.5 py-0.5 font-mono text-sm">idf_component.yml</code> et la commande{" "}
|
||
<code className="rounded bg-surface-2 px-1.5 py-0.5 font-mono text-sm">idf.py add-dependency</code> pour télécharger des pilotes d'écran (LVGL), des piles industrielles (Modbus), RainMaker et bien plus encore.
|
||
</>
|
||
) : isZh ? (
|
||
<>
|
||
在 ESP-IDF v4.4+ 和 v5.x 项目中,库不再需要以 Git 子模块的方式引入。使用{" "}
|
||
<code className="rounded bg-surface-2 px-1.5 py-0.5 font-mono text-sm">idf_component.yml</code> 和命令{" "}
|
||
<code className="rounded bg-surface-2 px-1.5 py-0.5 font-mono text-sm">idf.py add-dependency</code>,即可下载显示驱动(LVGL)、工业协议栈(Modbus)、RainMaker 等。
|
||
</>
|
||
) : isDe ? (
|
||
<>
|
||
In Projekten mit ESP-IDF v4.4+ und v5.x müssen Bibliotheken nicht mehr als Git-Submodule eingebunden werden. Nutzen Sie{" "}
|
||
<code className="rounded bg-surface-2 px-1.5 py-0.5 font-mono text-sm">idf_component.yml</code> und den Befehl{" "}
|
||
<code className="rounded bg-surface-2 px-1.5 py-0.5 font-mono text-sm">idf.py add-dependency</code>, um Display-Treiber (LVGL), Industrieprotokolle (Modbus), RainMaker und mehr herunterzuladen.
|
||
</>
|
||
) : (
|
||
<>
|
||
Nos projetos ESP-IDF v4.4+ e v5.x, as bibliotecas não precisam mais entrar como submódulos Git. Use o{" "}
|
||
<code className="rounded bg-surface-2 px-1.5 py-0.5 font-mono text-sm">idf_component.yml</code> e o comando{" "}
|
||
<code className="rounded bg-surface-2 px-1.5 py-0.5 font-mono text-sm">idf.py add-dependency</code> para baixar drivers de display (LVGL), pilhas industriais (Modbus), RainMaker e mais.
|
||
</>
|
||
)}
|
||
</p>
|
||
</div>
|
||
<Link href={getLocalizedHref("/componentes", currentLocale)} className="btn btn-primary shrink-0">
|
||
{isEs ? "Explorar componentes" : isEn ? "Explore components" : isFr ? "Explorer les composants" : isZh ? "探索组件" : isDe ? "Komponenten erkunden" : "Explorar componentes"}
|
||
<ArrowRight className="h-4 w-4" aria-hidden="true" />
|
||
</Link>
|
||
</div>
|
||
</section>
|
||
)}
|
||
|
||
{framework.exemplo && (
|
||
<section className="shell mt-8">
|
||
<CodeExample framework={framework} />
|
||
</section>
|
||
)}
|
||
|
||
<div className="shell section pt-10">
|
||
<Link href={getLocalizedHref("/frameworks", currentLocale)} className="inline-flex min-h-11 items-center gap-2 text-sm font-medium text-accent hover:text-accent-strong">
|
||
<ArrowRight className="h-4 w-4 rotate-180" aria-hidden="true" />
|
||
{isEs ? "Ver todos los frameworks" : isEn ? "View all frameworks" : isFr ? "Voir tous les frameworks" : isZh ? "查看全部框架" : isDe ? "Alle Frameworks ansehen" : "Ver todos os frameworks"}
|
||
</Link>
|
||
</div>
|
||
</main>
|
||
|
||
<Footer />
|
||
</div>
|
||
);
|
||
}
|
||
|
||
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 = isEs ? "es" : isEn ? "en" : isFr ? "fr" : isZh ? "zh-CN" : isDe ? "de" : "pt";
|
||
const frameworksData = isEs ? frameworksDataEs : isEn ? frameworksDataEn : isFr ? frameworksDataFr : isZh ? frameworksDataZh : isDe ? frameworksDataDe : frameworksDataPt;
|
||
const framework = frameworksData[key];
|
||
|
||
if (!framework) {
|
||
return { title: isEs ? "Framework no encontrado" : isEn ? "Framework not found" : isFr ? "Framework introuvable" : isZh ? "未找到该框架" : isDe ? "Framework nicht gefunden" : "Framework não encontrado", robots: { index: false, follow: false } };
|
||
}
|
||
|
||
return {
|
||
...paginaMeta({
|
||
titulo: isEs ? `${framework.nome} para ESP32 · Guía técnica` : isEn ? `${framework.nome} for ESP32 · Technical Guide` : isFr ? `${framework.nome} pour ESP32 · Guide technique` : isZh ? `用于 ESP32 的 ${framework.nome}:技术指南` : isDe ? `${framework.nome} für ESP32 · Technischer Leitfaden` : `${framework.nome} para ESP32 · Guia Técnico`,
|
||
descricao: isEs
|
||
? `${framework.nome_completo}: ${framework.descricao} Guía con ejemplos prácticos de código y casos de uso.`
|
||
: isEn
|
||
? `${framework.nome_completo}: ${framework.descricao} Guide with practical code examples and use cases.`
|
||
: isFr
|
||
? `${framework.nome_completo} : ${framework.descricao} Guide avec exemples pratiques de code et cas d'usage.`
|
||
: isZh ? `${framework.nome_completo}:${framework.descricao} 附实用代码示例与使用场景的指南。` : isDe
|
||
? `${framework.nome_completo}: ${framework.descricao} Leitfaden mit praktischen Codebeispielen und Anwendungsfällen.`
|
||
: `${framework.nome_completo}: ${framework.descricao} Guia com exemplos práticos de código e casos de uso.`,
|
||
caminho: `/frameworks/${encodeURIComponent(key)}`,
|
||
tipo: "article",
|
||
locale: currentLocale,
|
||
keywords: isEs
|
||
? [
|
||
framework.nome, framework.nome_completo,
|
||
`${framework.nome} ESP32`, `programar ESP32 con ${framework.nome}`,
|
||
"ESP32", "framework ESP32",
|
||
]
|
||
: isEn
|
||
? [
|
||
framework.nome, framework.nome_completo,
|
||
`${framework.nome} ESP32`, `program ESP32 with ${framework.nome}`,
|
||
"ESP32", "ESP32 framework",
|
||
]
|
||
: isFr
|
||
? [
|
||
framework.nome, framework.nome_completo,
|
||
`${framework.nome} ESP32`, `programmer ESP32 avec ${framework.nome}`,
|
||
"ESP32", "framework ESP32",
|
||
]
|
||
: isZh ? [ framework.nome, framework.nome_completo, `${framework.nome} ESP32`, `用 ${framework.nome} 开发 ESP32`, "ESP32", "ESP32 框架", ] : isDe
|
||
? [
|
||
framework.nome, framework.nome_completo,
|
||
`${framework.nome} ESP32`, `ESP32 programmieren mit ${framework.nome}`,
|
||
"ESP32", "ESP32 Framework",
|
||
]
|
||
: [
|
||
framework.nome, framework.nome_completo,
|
||
`${framework.nome} ESP32`, `programar ESP32 com ${framework.nome}`,
|
||
"ESP32", "framework ESP32",
|
||
],
|
||
}),
|
||
other: { "article:section": "Frameworks" },
|
||
};
|
||
}
|
||
|
||
export async function generateStaticParams() {
|
||
return Object.keys(frameworksDataPt).map((key) => ({
|
||
key: key,
|
||
}));
|
||
} |