#!/usr/bin/env node // Mechanically extract every { en, pt } string pair from a file or directory, // sorted and normalised, so a content migration can be proven lossless: // // node .agents/scripts/extract-strings.mjs app.js > /tmp/before.json // node .agents/scripts/extract-strings.mjs src/content/ > /tmp/after.json // diff /tmp/before.json /tmp/after.json // // A non-empty diff means you altered content. These are hand-written // translations with deliberate tone — copy them, never retype them. import { readdirSync, readFileSync, statSync } from 'node:fs'; import { join } from 'node:path'; const target = process.argv[2]; if (!target) { console.error('usage: extract-strings.mjs '); process.exit(2); } const walk = (dir) => readdirSync(dir).flatMap((name) => { const path = join(dir, name); return statSync(path).isDirectory() ? walk(path) : [path]; }); const files = statSync(target).isDirectory() ? walk(target) : [target]; // Matches `en: '…'` / "en": "…" and the pt counterpart, single or double quoted, // tolerating escaped quotes inside. const PAIR = /["']?\b(en|pt)\b["']?\s*:\s*(['"])((?:\\.|(?!\2)[\s\S])*)\2/g; const strings = []; for (const file of files) { const source = readFileSync(file, 'utf8'); for (const match of source.matchAll(PAIR)) { strings.push({ lang: match[1], value: match[3] }); } } // Sort so file ordering and structure changes do not show up as content changes. strings.sort((a, b) => (a.lang + a.value).localeCompare(b.lang + b.value)); console.log(JSON.stringify(strings, null, 2)); console.error(`extracted ${strings.length} strings from ${files.length} file(s)`);