48 lines
1.8 KiB
JavaScript
48 lines
1.8 KiB
JavaScript
import { readFile } from 'node:fs/promises';
|
|
import path from 'node:path';
|
|
import { fail, flatten, pass, repositoryRoot } from './lib.mjs';
|
|
|
|
const localeRoot = path.join(repositoryRoot, 'src', 'content', 'locales');
|
|
const locales = ['en', 'fr', 'ar'];
|
|
const files = ['homepage.json', 'shell.json'];
|
|
const errors = [];
|
|
|
|
for (const file of files) {
|
|
const catalogs = new Map();
|
|
for (const locale of locales) {
|
|
const parsed = JSON.parse(await readFile(path.join(localeRoot, locale, file), 'utf8'));
|
|
catalogs.set(locale, flatten(parsed));
|
|
}
|
|
const sourceKeys = [...catalogs.get('en').keys()];
|
|
for (const locale of locales) {
|
|
const catalog = catalogs.get(locale);
|
|
const keys = [...catalog.keys()];
|
|
const missing = sourceKeys.filter((key) => !catalog.has(key));
|
|
const extra = keys.filter((key) => !catalogs.get('en').has(key));
|
|
if (missing.length) errors.push(`${locale}/${file} missing: ${missing.join(', ')}`);
|
|
if (extra.length) errors.push(`${locale}/${file} extra: ${extra.join(', ')}`);
|
|
for (const [key, value] of catalog) {
|
|
if (typeof value === 'string' && value.trim().length === 0) {
|
|
errors.push(`${locale}/${file}:${key} is empty.`);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const expectedDirections = { en: 'ltr', fr: 'ltr', ar: 'rtl' };
|
|
for (const locale of locales) {
|
|
const homepage = JSON.parse(
|
|
await readFile(path.join(localeRoot, locale, 'homepage.json'), 'utf8'),
|
|
);
|
|
if (homepage.meta.dir !== expectedDirections[locale]) {
|
|
errors.push(`${locale} metadata direction must be ${expectedDirections[locale]}.`);
|
|
}
|
|
if (JSON.stringify(homepage).includes('homePageCar')) {
|
|
errors.push(`${locale} implementation catalog still contains the retired project name.`);
|
|
}
|
|
}
|
|
|
|
if (errors.length > 0) fail(errors);
|
|
else
|
|
pass('English, French, and Arabic catalogs have exact key parity and valid direction metadata.');
|