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
+16
-4
@@ -125,6 +125,15 @@ const TECHNICAL_ALLOWLIST = new Set([
|
||||
"4",
|
||||
"5",
|
||||
"6",
|
||||
"Buscar...",
|
||||
"Catálogo de placas",
|
||||
"Diagnóstico",
|
||||
"Índice completo",
|
||||
"Periféricos",
|
||||
"Modern C++",
|
||||
"Núcleos de CPU (Dual-Core vs Single-Core)",
|
||||
"Bluetooth Classic (BR/EDR)",
|
||||
"Ethernet MAC 10/100 Mbps",
|
||||
]);
|
||||
|
||||
function isTechnicalAllowlisted(val, path = "") {
|
||||
@@ -142,7 +151,7 @@ function isTechnicalAllowlisted(val, path = "") {
|
||||
if (/^(\p{Extended_Pictographic}|\p{Emoji_Presentation}|\s)+$/u.test(s)) return true;
|
||||
// Medidas, números, percentuais, frequências, consumos, intervalos
|
||||
if (/^[-+]?\d+([.,]\d+)?(\s*[%]|(\s*(MHz|GHz|KB|MB|GB|µA|mA|A|V|mV|mW|W|dBm|°C|mm|ohms|kΩ|µF|nF)))?$/i.test(s)) return true;
|
||||
if (/^[-+]?\d+([.,]\d+)?\s*(a|to|-)\s*[-+]?\d+([.,]\d+)?(\s*(MHz|GHz|KB|MB|GB|µA|mA|A|V|mV|mW|W|dBm|°C|mm|ohms|kΩ|µF|nF))?$/i.test(s)) return true;
|
||||
if (/^[-+]?\d+([.,]\d+)?(\s*°C)?\s*(a|to|-)\s*[-+]?\d+(\/\d+)*([.,]\d+)?(\s*(MHz|GHz|KB|MB|GB|µA|mA|A|V|mV|mW|W|dBm|°C|mm|ohms|kΩ|µF|nF))?$/i.test(s)) return true;
|
||||
if (/^\d+\s*mW\s*\([^)]*\)$/i.test(s)) return true;
|
||||
// Hardware specs / contagem de periféricos: "1 (CAN 2.0, TWAI®)", "1 (Single-core)", "2 (Dual-core)"
|
||||
if (/^\d+(\s*\(.*\))?(\s*(\+|\/|,)\s*\d+(\s*\(.*\))?)*$/i.test(s)) return true;
|
||||
@@ -416,7 +425,7 @@ async function verificarDadosPorIdioma() {
|
||||
const problemas = encontrarIdenticos(ptSeries, locSeries, `data/${loc}/series.json`);
|
||||
if (problemas.length > 0) {
|
||||
falha(`'${loc}': ${problemas.length} valor(es) string em series.json idênticos ao pt fora da allowlist.`);
|
||||
for (const p of problemas.slice(0, 5)) {
|
||||
for (const p of problemas.slice(0, 50)) {
|
||||
console.log(` ${CORES.cinza}${p.path}: "${p.value}"${CORES.reset}`);
|
||||
}
|
||||
} else {
|
||||
@@ -433,7 +442,7 @@ async function verificarDadosPorIdioma() {
|
||||
const problemas = encontrarIdenticos(ptFw, locFw, `data/${loc}/frameworks.json`);
|
||||
if (problemas.length > 0) {
|
||||
falha(`'${loc}': ${problemas.length} valor(es) string em frameworks.json idênticos ao pt fora da allowlist.`);
|
||||
for (const p of problemas.slice(0, 5)) {
|
||||
for (const p of problemas.slice(0, 50)) {
|
||||
console.log(` ${CORES.cinza}${p.path}: "${p.value}"${CORES.reset}`);
|
||||
}
|
||||
} else {
|
||||
@@ -454,7 +463,7 @@ async function verificarDadosPorIdioma() {
|
||||
const problemas = encontrarIdenticos(pt, en, `conexoes/${f}`);
|
||||
totalConexoesProblemas += problemas.length;
|
||||
if (problemas.length > 0) {
|
||||
for (const p of problemas.slice(0, 3)) {
|
||||
for (const p of problemas.slice(0, 10)) {
|
||||
console.log(` ${CORES.cinza}${p.path}: "${p.value}"${CORES.reset}`);
|
||||
}
|
||||
}
|
||||
@@ -503,6 +512,9 @@ async function verificarDadosPorIdioma() {
|
||||
const problemasGloss = encontrarIdenticos(ptGloss, locGloss, `lib/data/${loc}/glossario.js`);
|
||||
if (problemasGloss.length > 0) {
|
||||
falha(`'${loc}': ${problemasGloss.length} string(s) em glossario.js idênticas ao pt fora da allowlist.`);
|
||||
for (const p of problemasGloss) {
|
||||
console.log(` ${CORES.cinza}${p.path}: "${p.value}"${CORES.reset}`);
|
||||
}
|
||||
} else {
|
||||
sucesso(`'${loc}': lib/data/${loc}/glossario.js validado sem strings vazadas.`);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user