From 6974800d2e70732000ec1649e267cdff79a300bc Mon Sep 17 00:00:00 2001 From: Marcos Paulo Date: Sun, 6 Sep 2026 00:09:28 +0000 Subject: [PATCH] fix(rules): show GATILHO in Portuguese, and diff the PT half too The skill detail panel's label read TRIGGER in both languages. The copy data carries the Portuguese in `skillTriggerLabelPt`, but the island asks for `skillTriggerLabel`, which is "TRIGGER" under both locales -- so the translated value was never reachable. Legacy renders it inline: `language === 'pt' ? 'GATILHO' : 'TRIGGER'`. Fixed by putting the Portuguese where the lookup goes, `pt.skillTriggerLabel`, and dropping the unreachable `skillTriggerLabelPt` from both locales. Nothing else reads that key. rendered-text-diff.mjs grows a `--pt` flag and now reports both directions. English parity was hiding this: a page can paint every English string and still leave a block untranslated, because the Portuguese half is a separate set of nodes, and a string the Astro page renders but the legacy page does not is equally wrong -- it means a translation was invented or an English string was left where the legacy page swaps it. /rules/ is now 119 of 119 in both languages, zero either way. Co-Authored-By: Claude Opus 5 --- .agents/scripts/rendered-text-diff.mjs | 27 +++++++++++++++++++++++--- src/content/rules/copy.json | 4 +--- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/.agents/scripts/rendered-text-diff.mjs b/.agents/scripts/rendered-text-diff.mjs index be48504..870775a 100644 --- a/.agents/scripts/rendered-text-diff.mjs +++ b/.agents/scripts/rendered-text-diff.mjs @@ -2,6 +2,7 @@ // Compare the *rendered* text of a legacy page against its Astro replacement. // // node .agents/scripts/rendered-text-diff.mjs full-guide +// node .agents/scripts/rendered-text-diff.mjs full-guide --pt // // Why this exists: scripts/verify.mjs reads the legacy files, so a migrated // page can drop half its content and still pass the gate. Task 15d shipped @@ -26,9 +27,15 @@ import { chromium } from 'playwright'; // directory of its own, so it needs a different path on the legacy side. const route = process.argv[2]; if (!route) { - console.error('usage: rendered-text-diff.mjs e.g. full-guide, or index'); + console.error('usage: rendered-text-diff.mjs [--pt] e.g. full-guide, or index'); process.exit(2); } + +// `--pt` clicks the language toggle on both pages first. English parity is +// only half the contract: a page can render every English string and still +// leave a restored block untranslated, because the Portuguese half is a +// separate set of nodes. Only /full-guide/ and /rules/ have a toggle. +const portuguese = process.argv.includes('--pt'); const legacyPath = route === 'index' ? 'index.html' : `${route}/index.html`; const astroPath = route === 'index' ? '' : `${route}/`; @@ -74,6 +81,12 @@ try { // The islands hydrate and render their initial panel on load; without this // every panel's copy reads as missing. await page.waitForTimeout(1200); + if (portuguese) { + const toggle = await page.$('[data-lang="pt"]'); + if (!toggle) throw new Error(`no language toggle on ${url}`); + await toggle.click(); + await page.waitForTimeout(1200); + } const spans = await page.evaluate(visibleText); await page.close(); return spans; @@ -86,11 +99,19 @@ try { const rendered = new Set(astro); const missing = legacy.filter((span) => !rendered.has(span)); + // Both directions. A string the Astro page paints and the legacy page does + // not is just as wrong: it means a translation was invented, or an English + // string was left standing where the legacy page swaps it. + const legacySpans = new Set(legacy); + const extra = astro.filter((span) => !legacySpans.has(span)); + + const mode = portuguese ? 'pt' : 'en'; console.log( - `legacy ${legacy.length} spans · astro ${astro.length} spans · missing ${missing.length}`, + `${mode} · legacy ${legacy.length} spans · astro ${astro.length} spans · missing ${missing.length} · extra ${extra.length}`, ); for (const span of missing) console.log(` - ${span}`); - process.exitCode = missing.length === 0 ? 0 : 1; + for (const span of extra) console.log(` + ${span}`); + process.exitCode = missing.length === 0 && extra.length === 0 ? 0 : 1; } finally { stop(); } diff --git a/src/content/rules/copy.json b/src/content/rules/copy.json index 0be3b6d..6c01e92 100644 --- a/src/content/rules/copy.json +++ b/src/content/rules/copy.json @@ -56,7 +56,6 @@ "skillReadSkill": "READ SKILL ↗", "skillReadSkillPt": "LER SKILL ↗", "skillTriggerLabel": "TRIGGER", - "skillTriggerLabelPt": "GATILHO", "copyStatus": "Prompt copied.", "copyStatusPt": "Prompt copiado.", "copyFallback": "Select the text manually.", @@ -118,8 +117,7 @@ "stageOpenSourcePt": "ABRIR FONTE ↗", "skillReadSkill": "LER SKILL ↗", "skillReadSkillPt": "LER SKILL ↗", - "skillTriggerLabel": "TRIGGER", - "skillTriggerLabelPt": "GATILHO", + "skillTriggerLabel": "GATILHO", "copyStatus": "Prompt copied.", "copyStatusPt": "Prompt copiado.", "copyFallback": "Select the text manually.",