Files
SnapOtter/tests/unit/scripts/i18n/batch.test.ts
T
SnapOtterandGitHub 00b651c9f8 feat(i18n): 21-language pipeline, landing/docs/API wiring, landing+API translations
Shared Claude Code translation pipeline (scripts/i18n, no API key) plus Astro/VitePress/Scalar i18n wiring. Landing and API reference translated into all 20 languages; docs i18n wiring + English source anchors. The translated docs markdown (apps/docs/<locale>/**, 3,620 files) follows in a companion PR because it exceeds GitHub's per-PR CI file limit.
2026-07-11 13:01:55 +08:00

54 lines
2.1 KiB
TypeScript

// tests/unit/scripts/i18n/batch.test.ts
import { mkdtempSync, readFileSync, writeFileSync } from "node:fs";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { describe, expect, it } from "vitest";
import {
batchResultTranslator,
readDone,
writePending,
} from "../../../../scripts/i18n/lib/batch.mjs";
describe("batch handoff", () => {
it("writes pending units as masked {id, masked} pairs", () => {
const dir = mkdtempSync(join(tmpdir(), "i18n-batch-"));
const path = writePending(dir, "docs", "de", [
{ unit: { id: "a", sourceText: "Run `x` for {n}" }, srcHash: "h" },
]);
const parsed = JSON.parse(readFileSync(path, "utf8"));
expect(parsed[0].id).toBe("a");
expect(parsed[0].masked).not.toContain("`x`"); // masked
expect(parsed[0].masked).not.toContain("{n}");
});
it("batchResultTranslator restores tokens from the done map", async () => {
const dir = mkdtempSync(join(tmpdir(), "i18n-batch-"));
// Simulate a subagent producing a done file that keeps the mask tokens.
// Build the expected masked form by masking the same source the translator will mask.
const units = [{ id: "a", sourceText: "Run `x` for {n}" }];
// The subagent returns the translated masked text; here we fake "DE " prefix.
writePending(
dir,
"docs",
"de",
units.map((u) => ({ unit: u, srcHash: "h" })),
);
const pending = JSON.parse(readFileSync(join(dir, "docs.de.pending.json"), "utf8"));
const done = { a: `DE ${pending[0].masked}` };
writeFileSync(join(dir, "docs.de.done.json"), JSON.stringify(done));
const doneMap = readDone(dir, "docs", "de");
const translate = batchResultTranslator(doneMap);
const out = await translate(units, "de");
expect(out.get("a")).toContain("`x`"); // restored
expect(out.get("a")).toContain("{n}");
expect(out.get("a")).toContain("DE ");
});
it("batchResultTranslator returns null for a missing id", async () => {
const translate = batchResultTranslator(new Map());
const out = await translate([{ id: "z", sourceText: "hi" }], "de");
expect(out.get("z")).toBeNull();
});
});