feat(i18n): French and German localization (phase 5)
- Add full message catalogs and content for French (fr) and German (de) - Implement ASCII canonical slugs for French and German routes - Add language-specific search endpoints (/api/busca/fr, /api/busca/de) - Configure strict 404 responses for /fr/livro and /de/livro - Localize SEO, OpenGraph (fr_FR, de_DE), Twitter and JSON-LD schemas - Add localized code example comments across 14 examples for fr and de - Enable 'fr' and 'de' in ENABLED_LOCALES with root negotiation and redirect - Extend test suite in check-i18n, smoke-imagem and verifica-vazamentos Co-Authored-By: Antigravity <noreply@google.com>
This commit is contained in:
1 parent
7b673aeb4b
commit
7fce46b9e1
104 files changed
+33369
-686
No files matched your search
@@ -201,14 +201,144 @@ const GRUPOS_ES = [
|
||||
},
|
||||
];
|
||||
|
||||
const GRUPOS_FR = [
|
||||
{
|
||||
id: "entrada",
|
||||
titulo: "Entrée uniquement",
|
||||
icone: ArrowDownToLine,
|
||||
cor: "text-accent",
|
||||
explicacao:
|
||||
"Broches en entrée seule. Elles ne peuvent pas être configurées en sortie et ne possèdent pas de résistances de pull-up ou de pull-down internes. Si vous en avez besoin, ajoutez-en dans votre circuit externe.",
|
||||
combina: (avisos) => /entrée uniquement|input[- ]only/i.test(avisos),
|
||||
},
|
||||
{
|
||||
id: "flash",
|
||||
titulo: "Liées à la mémoire flash/PSRAM",
|
||||
icone: HardDrive,
|
||||
cor: "text-copper",
|
||||
explicacao:
|
||||
"Déjà connectées à la mémoire depuis laquelle le firmware est exécuté. Les utiliser comme GPIO standard plante généralement la puce ou corrompt l'exécution. Sur les modules avec flash interne, elles ne sont même pas reliées aux broches du boîtier.",
|
||||
combina: (avisos) =>
|
||||
/(flash|psram)/i.test(avisos) &&
|
||||
/(dédi|mémoire|ne doit pas|déconseillé|connected to|dedicated to|should not)/i.test(avisos),
|
||||
},
|
||||
{
|
||||
id: "strapping",
|
||||
titulo: "Strapping (mode de démarrage)",
|
||||
icone: Power,
|
||||
cor: "text-gold",
|
||||
explicacao:
|
||||
"La puce lit l'état logique de ces broches au moment du reset pour déterminer son mode de démarrage. Vous pouvez les utiliser après le boot, mais le circuit externe ne doit pas forcer un niveau incorrect pendant le reset, sinon la carte ne démarrera pas ou entrera en mode flashage de manière inattendue.",
|
||||
combina: (avisos, cats) =>
|
||||
cats.includes("Strapping") ||
|
||||
/strapping|mode de démarrage|démarrage|boot mode/i.test(avisos),
|
||||
},
|
||||
{
|
||||
id: "debug",
|
||||
titulo: "Programmation et débogage",
|
||||
icone: Bug,
|
||||
cor: "text-accent",
|
||||
explicacao:
|
||||
"Ce sont l'UART de programmation et les lignes JTAG. Elles restent utilisables comme GPIO, mais les réutiliser supprime la possibilité de flasher et de déboguer la carte sans déconnecter ce qui y est relié.",
|
||||
combina: (avisos, cats) => /débogage|programmation|debugging/i.test(avisos) || cats.includes("JTAG"),
|
||||
},
|
||||
{
|
||||
id: "usb",
|
||||
titulo: "USB natif",
|
||||
icone: Usb,
|
||||
cor: "text-accent",
|
||||
explicacao:
|
||||
"Reliées par défaut au contrôleur USB Série/JTAG interne. Les utiliser comme GPIO nécessite de désactiver ce périphérique, ce qui désactive également le flashage direct par USB.",
|
||||
combina: (avisos) => /usb (série|serial)\/jtag|usb_d[+-]/i.test(avisos),
|
||||
},
|
||||
{
|
||||
id: "eletrico",
|
||||
titulo: "Ne doivent pas être laissées flottantes",
|
||||
icone: Zap,
|
||||
cor: "text-gold",
|
||||
explicacao:
|
||||
"Nécessitent un niveau logique matériel défini : pull-up externe ou circuit RC de temporisation. Les laisser flottantes entraîne des redémarrages aléatoires ou un démarrage instable.",
|
||||
combina: (avisos) => /flottant|floating/i.test(avisos),
|
||||
},
|
||||
];
|
||||
|
||||
const GRUPOS_DE = [
|
||||
{
|
||||
id: "entrada",
|
||||
titulo: "Nur Eingang",
|
||||
icone: ArrowDownToLine,
|
||||
cor: "text-accent",
|
||||
explicacao:
|
||||
"Pins, die nur als Eingang arbeiten. Sie können nicht als Ausgang konfiguriert werden und besitzen keine internen Pull-up- oder Pull-down-Widerstände. Falls erforderlich, sehen Sie diese in Ihrer externen Schaltung vor.",
|
||||
combina: (avisos) => /nur eingang|input[- ]only/i.test(avisos),
|
||||
},
|
||||
{
|
||||
id: "flash",
|
||||
titulo: "Mit Flash-/PSRAM-Speicher verbunden",
|
||||
icone: HardDrive,
|
||||
cor: "text-copper",
|
||||
explicacao:
|
||||
"Bereits mit dem Speicher verbunden, aus dem die Firmware ausgeführt wird. Die Verwendung als universelle GPIOs führt meist zu Abstürzen oder Speicherbeschädigungen. Bei Modulen mit internem Flash sind sie nicht nach außen geführt.",
|
||||
combina: (avisos) =>
|
||||
/(flash|psram)/i.test(avisos) &&
|
||||
/(dediziert|speicher|sollte nicht|nicht empfohlen|connected to|dedicated to|should not)/i.test(avisos),
|
||||
},
|
||||
{
|
||||
id: "strapping",
|
||||
titulo: "Strapping-Pins (Bootmodus)",
|
||||
icone: Power,
|
||||
cor: "text-gold",
|
||||
explicacao:
|
||||
"Der Chip liest den Logikpegel dieser Pins beim Reset aus, um den Bootmodus festzulegen. Nach dem Booten können sie genutzt werden, die externe Schaltung darf beim Reset jedoch keinen falschen Pegel erzwingen, da das Board sonst nicht startet oder unerwartet in den Download-Modus wechselt.",
|
||||
combina: (avisos, cats) =>
|
||||
cats.includes("Strapping") ||
|
||||
/strapping|bootmodus|boot-modus|boot mode/i.test(avisos),
|
||||
},
|
||||
{
|
||||
id: "debug",
|
||||
titulo: "Programmierung und Debugging",
|
||||
icone: Bug,
|
||||
cor: "text-accent",
|
||||
explicacao:
|
||||
"Dies sind die Flash-UART- und JTAG-Leitungen. Sie können als GPIO genutzt werden, doch dadurch entfällt die Möglichkeit, das Board ohne Trennen der Peripherie zu programmieren oder zu debuggen.",
|
||||
combina: (avisos, cats) => /debugging|programmierung/i.test(avisos) || cats.includes("JTAG"),
|
||||
},
|
||||
{
|
||||
id: "usb",
|
||||
titulo: "Natives USB",
|
||||
icone: Usb,
|
||||
cor: "text-accent",
|
||||
explicacao:
|
||||
"Standardmäßig mit dem internen USB-Serial/JTAG-Controller verbunden. Um sie als GPIO zu nutzen, muss diese Funktion deaktiviert werden, wodurch auch das direkte Flashen über USB entfällt.",
|
||||
combina: (avisos) => /usb[- ](serial|seriell)\/jtag|usb_d[+-]/i.test(avisos),
|
||||
},
|
||||
{
|
||||
id: "eletrico",
|
||||
titulo: "Dürfen nicht unbeschaltet bleiben",
|
||||
icone: Zap,
|
||||
cor: "text-gold",
|
||||
explicacao:
|
||||
"Erfordern einen definierten Hardwarepegel: externen Pull-up oder RC-Verzögerungsschaltung. Bleiben sie unbeschaltet (floating), führt dies zu sporadischen Resets oder instabilem Bootverhalten.",
|
||||
combina: (avisos) => /unbeschaltet|floating/i.test(avisos),
|
||||
},
|
||||
];
|
||||
|
||||
/** Nome do pino + o GPIO correspondente, quando o nome é uma função (ex.: SENSOR_VP). */
|
||||
function rotuloDoPino(pino) {
|
||||
const gpio = (pino.funcoes || []).find((f) => /^GPIO\d+$/.test(f));
|
||||
return gpio && gpio !== pino.nome ? `${pino.nome} · ${gpio}` : pino.nome;
|
||||
}
|
||||
|
||||
function derivarGrupos(conexoes, isEn, isEs) {
|
||||
const listaGrupos = isEn ? GRUPOS_EN : isEs ? GRUPOS_ES : GRUPOS_PT;
|
||||
function derivarGrupos(conexoes, isEn, isEs, isFr, isDe) {
|
||||
const listaGrupos = isEn
|
||||
? GRUPOS_EN
|
||||
: isEs
|
||||
? GRUPOS_ES
|
||||
: isFr
|
||||
? GRUPOS_FR
|
||||
: isDe
|
||||
? GRUPOS_DE
|
||||
: GRUPOS_PT;
|
||||
return listaGrupos.map((grupo) => {
|
||||
const vistos = new Map();
|
||||
for (const pino of conexoes) {
|
||||
@@ -224,13 +354,15 @@ function derivarGrupos(conexoes, isEn, isEs) {
|
||||
}).filter((g) => g.pinos.length > 0);
|
||||
}
|
||||
|
||||
export default function PinRestrictions({ conexoes, serieKey, isEn = false, isEs = false, locale }) {
|
||||
export default function PinRestrictions({ conexoes, serieKey, isEn = false, isEs = false, isFr = false, isDe = false, locale }) {
|
||||
if (!conexoes?.length) return null;
|
||||
|
||||
const effectiveIsEn = isEn || locale === "en";
|
||||
const effectiveIsEs = isEs || locale === "es";
|
||||
const effectiveIsFr = isFr || locale === "fr";
|
||||
const effectiveIsDe = isDe || locale === "de";
|
||||
|
||||
const grupos = derivarGrupos(conexoes, effectiveIsEn, effectiveIsEs);
|
||||
const grupos = derivarGrupos(conexoes, effectiveIsEn, effectiveIsEs, effectiveIsFr, effectiveIsDe);
|
||||
if (!grupos.length) return null;
|
||||
|
||||
const totalPinos = new Set(grupos.flatMap((g) => g.pinos)).size;
|
||||
@@ -241,7 +373,15 @@ export default function PinRestrictions({ conexoes, serieKey, isEn = false, isEs
|
||||
<span className="grid h-9 w-9 place-items-center rounded-full bg-gold-soft text-gold">
|
||||
<AlertTriangle className="h-4 w-4" aria-hidden="true" />
|
||||
</span>
|
||||
{effectiveIsEn ? "Pins with usage restrictions" : effectiveIsEs ? "Pines con restricción de uso" : "Pinos com restrição de uso"}
|
||||
{effectiveIsEn
|
||||
? "Pins with usage restrictions"
|
||||
: effectiveIsEs
|
||||
? "Pines con restricción de uso"
|
||||
: effectiveIsFr
|
||||
? "Broches avec restrictions d'utilisation"
|
||||
: effectiveIsDe
|
||||
? "Pins mit Nutzungseinschränkungen"
|
||||
: "Pinos com restrição de uso"}
|
||||
</h2>
|
||||
|
||||
<p className="mt-3 max-w-3xl text-sm leading-relaxed text-muted">
|
||||
@@ -253,6 +393,14 @@ export default function PinRestrictions({ conexoes, serieKey, isEn = false, isEs
|
||||
<>
|
||||
No todos los pines del {serieKey} están libres para uso general. {totalPinos} de ellos tienen alguna condición: ya están ocupados por memoria, se leen durante el arranque o solo funcionan como entrada. Conviene comprobarlos antes de cerrar el esquemático.
|
||||
</>
|
||||
) : effectiveIsFr ? (
|
||||
<>
|
||||
Toutes les broches de l'{serieKey} ne sont pas libres pour un usage général. {totalPinos} d'entre elles ont des conditions : occupées par la mémoire, lues pendant le démarrage ou fonctionnent uniquement en entrée. Pensez à vérifier avant de finaliser votre schéma.
|
||||
</>
|
||||
) : effectiveIsDe ? (
|
||||
<>
|
||||
Nicht jeder Pin des {serieKey} steht für allgemeine Zwecke frei zur Verfügung. {totalPinos} davon unterliegen Bedingungen: durch Speicher belegt, beim Booten abgefragt oder reine Eingangspins. Prüfen Sie dies vor Abschluss Ihres Schaltplans.
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
Nem todo pino do {serieKey} está livre para uso geral. {totalPinos} deles têm alguma
|
||||
@@ -269,7 +417,26 @@ export default function PinRestrictions({ conexoes, serieKey, isEn = false, isEs
|
||||
<Icone className={`h-4 w-4 shrink-0 ${corIcone}`} aria-hidden="true" />
|
||||
<h3 className="text-sm font-semibold text-ink">{titulo}</h3>
|
||||
<span className="ml-auto text-xs text-muted tabular-nums">
|
||||
{pinos.length} {pinos.length === 1 ? (effectiveIsEn ? "pin" : effectiveIsEs ? "pin" : "pino") : (effectiveIsEn ? "pins" : effectiveIsEs ? "pines" : "pinos")}
|
||||
{pinos.length}{" "}
|
||||
{pinos.length === 1
|
||||
? effectiveIsEn
|
||||
? "pin"
|
||||
: effectiveIsEs
|
||||
? "pin"
|
||||
: effectiveIsFr
|
||||
? "broche"
|
||||
: effectiveIsDe
|
||||
? "Pin"
|
||||
: "pino"
|
||||
: effectiveIsEn
|
||||
? "pins"
|
||||
: effectiveIsEs
|
||||
? "pines"
|
||||
: effectiveIsFr
|
||||
? "broches"
|
||||
: effectiveIsDe
|
||||
? "Pins"
|
||||
: "pinos"}
|
||||
</span>
|
||||
</div>
|
||||
|
||||
@@ -292,12 +459,16 @@ export default function PinRestrictions({ conexoes, serieKey, isEn = false, isEs
|
||||
"These groups are derived from the same data as the pinout diagram. There you can see every pin's full functions, power domain, and complete engineering notes."
|
||||
) : effectiveIsEs ? (
|
||||
"Estos grupos proceden de los mismos datos que el diagrama de conexiones. Allí podrá consultar pino a pino todas las funciones, el dominio de alimentación y los avisos completos."
|
||||
) : effectiveIsFr ? (
|
||||
"Ces groupes sont issus des mêmes données que le schéma de brochage. Vous pouvez y consulter broche par broche l'ensemble des fonctions, le domaine d'alimentation et les remarques complètes."
|
||||
) : effectiveIsDe ? (
|
||||
"Diese Gruppen stammen aus denselben Daten wie das Pinbelegungsdiagramm. Dort finden Sie für jeden Pin alle Funktionen, den Spannungsbereich und die vollständigen Entwicklungshinweise."
|
||||
) : (
|
||||
"Estes grupos vêm dos mesmos dados do diagrama de conexões. Lá você vê pino a pino todas as funções, o domínio de alimentação e os avisos completos."
|
||||
)}
|
||||
</p>
|
||||
<Link href="#connections" className="btn btn-ghost shrink-0">
|
||||
{effectiveIsEn ? "Open pinout diagram" : effectiveIsEs ? "Abrir diagrama de pines" : "Abrir diagrama de pinos"}
|
||||
{effectiveIsEn ? "Open pinout diagram" : effectiveIsEs ? "Abrir diagrama de pines" : effectiveIsFr ? "Ouvrir le brochage" : effectiveIsDe ? "Pinbelegung öffnen" : "Abrir diagrama de pinos"}
|
||||
<ArrowRight className="h-4 w-4" aria-hidden="true" />
|
||||
</Link>
|
||||
</div>
|
||||
|
||||
Reference in new issue
Block a user