Files
HY2XS_flamy/apps/frontend/test/i18n-runtime.test.ts
T

110 lines
3.3 KiB
Go

import { describe, expect, test } from "bun:test";
import { createI18n } from "vue-i18n";
import {
PEER_NAME_MAX_LENGTH,
PEER_NAME_MIN_LENGTH,
PEER_NAME_PUNCTUATION,
} from "../src/constants/peer";
import en from "../src/lang/package/en";
import ru from "../src/lang/package/ru";
type Dictionary = Record<string, unknown>;
function leafMessages(
value: unknown,
prefix = ""
): Array<[key: string, message: string]> {
if (typeof value === "string") {
return [[prefix, value]];
}
if (!value || typeof value !== "object") {
return [];
}
return Object.entries(value as Dictionary).flatMap(([key, child]) =>
leafMessages(child, prefix ? `${prefix}.${key}` : key)
);
}
function interpolationValues(message: string): Record<string, string | number> {
const values: Record<string, string | number> = {
count: 2,
n: 2,
min: PEER_NAME_MIN_LENGTH,
max: PEER_NAME_MAX_LENGTH,
punctuation: PEER_NAME_PUNCTUATION,
};
for (const match of message.matchAll(/\{([A-Za-z_][A-Za-z0-9_$-]*)\}/g)) {
values[match[1]] ??= match[1];
}
return values;
}
for (const [locale, dictionary] of Object.entries({ ru, en }) as Array<
["ru" | "en", Dictionary]
>) {
describe(`runtime-компиляция локализации ${locale}`, () => {
test("каждое строковое сообщение компилируется без diagnostics", () => {
const compilerDiagnostics: string[] = [];
const thrown: string[] = [];
const originalConsoleError = console.error;
console.error = (...args: unknown[]) => {
compilerDiagnostics.push(args.map(String).join(" "));
};
try {
const i18n = createI18n({
legacy: false,
locale,
fallbackLocale: false,
missingWarn: false,
fallbackWarn: false,
messages: { [locale]: dictionary },
});
for (const [key, message] of leafMessages(dictionary)) {
try {
const translated = i18n.global.t(key, interpolationValues(message));
if (typeof translated !== "string") {
thrown.push(`${key}: результат не является строкой`);
}
} catch (error) {
thrown.push(
`${key}: ${error instanceof Error ? error.message : String(error)}`
);
}
}
} finally {
console.error = originalConsoleError;
}
expect(thrown).toEqual([]);
expect(compilerDiagnostics).toEqual([]);
});
test("набор знаков имени пира проходит интерполяцию как данные", () => {
const i18n = createI18n({
legacy: false,
locale,
fallbackLocale: false,
messages: { [locale]: dictionary },
});
const template = (dictionary as any).peer.form.nameHint as string;
expect(
i18n.global.t("peer.form.nameHint", {
min: PEER_NAME_MIN_LENGTH,
max: PEER_NAME_MAX_LENGTH,
punctuation: PEER_NAME_PUNCTUATION,
})
).toBe(
template
.replace("{min}", String(PEER_NAME_MIN_LENGTH))
.replace("{max}", String(PEER_NAME_MAX_LENGTH))
.replace("{punctuation}", PEER_NAME_PUNCTUATION)
);
});
});
}