import fs from 'node:fs'; import path from 'node:path'; import vm from 'node:vm'; import assert from 'node:assert/strict'; import ts from '../../../../job-tracker-ui/node_modules/typescript/lib/typescript.js'; import { fileURLToPath } from 'node:url'; const here = path.dirname(fileURLToPath(import.meta.url)); const root = path.resolve(here, '../../../..'); const source = fs.readFileSync(path.join(root, 'job-tracker-ui/src/i18n/translations.ts'), 'utf8'); const compiled = ts.transpileModule(source, { compilerOptions: { module: ts.ModuleKind.CommonJS } }).outputText; const sandbox = { exports: {} }; vm.runInNewContext(compiled, sandbox); const { en, nb } = sandbox.exports.translations; const placeholders = value => [...new Set(value.match(/\{\w+\}/g) ?? [])].sort(); assert.deepEqual(placeholders('A {count} and {name} {count}'), ['{count}', '{name}']); const missingNb = Object.keys(en).filter(key => !(key in nb)); const extraNb = Object.keys(nb).filter(key => !(key in en)); const placeholderDifferences = Object.keys(en).filter(key => key in nb && JSON.stringify(placeholders(en[key])) !== JSON.stringify(placeholders(nb[key]))); const unchangedStrings = Object.keys(en).filter(key => en[key] === nb[key]).map(key => ({ key, value: en[key] })); const report = { englishKeys: Object.keys(en).length, bokmalKeys: Object.keys(nb).length, missingNb, extraNb, placeholderDifferences, unchangedStrings, limitation: 'Dictionary/placeholder parity is static evidence. Equal strings can be proper names or technical words. Human Bokmal review and provider-generated/server messages remain separate.' }; fs.writeFileSync(path.join(here, 'localisation.json'), JSON.stringify(report, null, 2) + '\n'); assert.deepEqual(missingNb, []); assert.deepEqual(extraNb, []); assert.deepEqual(placeholderDifferences, []); console.log(JSON.stringify({ ...report, unchangedStrings: unchangedStrings.length }));