110 lines
3.3 KiB
Go
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)
|
|
);
|
|
});
|
|
});
|
|
}
|