misskey/packages/i18n/scripts/verify.ts

71 lines
2.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

/*
* SPDX-FileCopyrightText: syuilo and misskey-project
* SPDX-License-Identifier: AGPL-3.0-only
*/
let valid = true;
interface LocaleRecord {
[key: string]: string | LocaleRecord;
}
interface ErrorData {
expected?: string;
actual?: string;
parameter?: string;
}
function writeError(type: string, lang: string, tree: string, data: ErrorData): void {
process.stderr.write(JSON.stringify({ type, lang, tree, data }));
process.stderr.write('\n');
valid = false;
}
function verify(expected: LocaleRecord, actual: LocaleRecord, lang: string, trace?: string): void {
for (const key in expected) {
if (!Object.prototype.hasOwnProperty.call(actual, key)) {
continue;
}
if (typeof expected[key] === 'object') {
if (typeof actual[key] !== 'object') {
writeError('mismatched_type', lang, trace ? `${trace}.${key}` : key, { expected: 'object', actual: typeof actual[key] });
continue;
}
verify(expected[key] as LocaleRecord, actual[key] as LocaleRecord, lang, trace ? `${trace}.${key}` : key);
} else if (typeof expected[key] === 'string') {
switch (typeof actual[key]) {
case 'object':
writeError('mismatched_type', lang, trace ? `${trace}.${key}` : key, { expected: 'string', actual: 'object' });
break;
case 'undefined':
continue;
case 'string': {
const expectedParameters = new Set((expected[key] as string).match(/\{[^}]+\}/g)?.map((s) => s.slice(1, -1)));
const actualParameters = new Set((actual[key] as string).match(/\{[^}]+\}/g)?.map((s) => s.slice(1, -1)));
for (const parameter of expectedParameters) {
if (!actualParameters.has(parameter)) {
writeError('missing_parameter', lang, trace ? `${trace}.${key}` : key, { parameter });
}
}
}
}
}
}
}
// index.tsはtsのまま動かすことを想定していないビルド成果物を外部に公開する.
// よってビルド後のものを検証する
const locales = await import('../built/index.js');
const { 'ja-JP': original, ...verifiees } = locales as unknown as Record<string, LocaleRecord>;
for (const lang in verifiees) {
if (!Object.prototype.hasOwnProperty.call(locales, lang)) {
continue;
}
verify(original, verifiees[lang], lang);
}
if (!valid) {
process.exit(1);
}