mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-14 16:07:52 +00:00
test(i18n): fail on keys a locale catalog defines twice (#2804)
JSON.parse keeps only the last of two equal keys, so a catalog could carry duplicate entries (one of them silently unused) without any test noticing. The text catalog test now parses every message and source-text catalog with the TypeScript JSON parser and lists keys defined more than once.
This commit is contained in:
@@ -620,6 +620,26 @@ const catalogs = Object.fromEntries(
|
||||
.map((f) => [f.slice(0, -5), JSON.parse(readFileSync(new URL(f, TEXT_DIR), "utf8")) as Record<string, string>]),
|
||||
);
|
||||
|
||||
/** Keys a JSON file defines more than once (at any depth); `JSON.parse` keeps only the last. */
|
||||
function duplicateKeys(url: URL): string[] {
|
||||
const file = ts.parseJsonText(url.pathname, readFileSync(url, "utf8"));
|
||||
const duplicates: string[] = [];
|
||||
const visit = (node: ts.Node, path: string) => {
|
||||
if (ts.isObjectLiteralExpression(node)) {
|
||||
const seen = new Set<string>();
|
||||
for (const property of node.properties) {
|
||||
if (!ts.isPropertyAssignment(property) || !ts.isStringLiteral(property.name)) continue;
|
||||
const key = path + property.name.text;
|
||||
if (seen.has(key)) duplicates.push(key);
|
||||
seen.add(key);
|
||||
visit(property.initializer, `${key}.`);
|
||||
}
|
||||
}
|
||||
};
|
||||
file.statements.forEach((statement) => visit(statement.expression, ""));
|
||||
return duplicates;
|
||||
}
|
||||
|
||||
/** `{name}` templates of a catalog, as `txTemplate` matches them. */
|
||||
function templatePatterns(catalog: Record<string, string>): RegExp[] {
|
||||
return Object.keys(catalog)
|
||||
@@ -658,6 +678,21 @@ it("uses only message keys of the English catalog", () => {
|
||||
expect(report(scan.keys.filter(({ text }) => !Object.hasOwn(en, text)))).toEqual([]);
|
||||
});
|
||||
|
||||
const CATALOG_DIRS: [prefix: string, dir: URL][] = [
|
||||
["", new URL("./", import.meta.url)],
|
||||
["text/", TEXT_DIR],
|
||||
];
|
||||
|
||||
it.each(
|
||||
CATALOG_DIRS.flatMap(([prefix, dir]) =>
|
||||
readdirSync(dir)
|
||||
.filter((f) => f.endsWith(".json"))
|
||||
.map((f) => ({ name: `${prefix}${f}`, url: new URL(f, dir) })),
|
||||
),
|
||||
)("defines each key once in $name", ({ url }) => {
|
||||
expect(duplicateKeys(url)).toEqual([]);
|
||||
});
|
||||
|
||||
describe.each(Object.keys(catalogs))("source-text catalog %s", (locale) => {
|
||||
const catalog = catalogs[locale]!;
|
||||
const patterns = templatePatterns(catalog);
|
||||
|
||||
Reference in New Issue
Block a user