Files
tolaria/scripts/validate-locales.mjs
2026-04-27 13:06:59 +02:00

62 lines
1.8 KiB
JavaScript

import fs from 'node:fs'
import path from 'node:path'
import { fileURLToPath } from 'node:url'
const root = path.resolve(path.dirname(fileURLToPath(import.meta.url)), '..')
const localesDir = path.join(root, 'src/lib/locales')
const sourcePath = path.join(localesDir, 'en.json')
function readCatalog(filePath) {
return JSON.parse(fs.readFileSync(filePath, 'utf8'))
}
function assertFlatStringCatalog(locale, catalog) {
if (!catalog || typeof catalog !== 'object' || Array.isArray(catalog)) {
throw new Error(`${locale}: expected a flat object of translation keys`)
}
for (const [key, value] of Object.entries(catalog)) {
if (typeof value !== 'string') {
throw new Error(`${locale}: key "${key}" must map to a string`)
}
}
}
const sourceCatalog = readCatalog(sourcePath)
assertFlatStringCatalog('en', sourceCatalog)
const sourceKeys = Object.keys(sourceCatalog).sort()
const localeFiles = fs.readdirSync(localesDir).filter((file) => file.endsWith('.json'))
const issues = []
for (const file of localeFiles) {
const locale = file.replace(/\.json$/, '')
const filePath = path.join(localesDir, file)
const catalog = readCatalog(filePath)
assertFlatStringCatalog(locale, catalog)
if (locale === 'en') continue
const keys = Object.keys(catalog).sort()
const missing = sourceKeys.filter((key) => !keys.includes(key))
const extra = keys.filter((key) => !sourceKeys.includes(key))
if (missing.length > 0) {
issues.push(`${locale}: missing ${missing.length} key(s)`)
}
if (extra.length > 0) {
issues.push(`${locale}: extra ${extra.length} key(s)`)
}
}
if (issues.length > 0) {
console.error('Locale validation failed:')
for (const issue of issues) {
console.error(`- ${issue}`)
}
process.exit(1)
}
console.log(`Validated ${localeFiles.length} locale catalog(s) against ${sourceKeys.length} English keys.`)