- Each ready version gets a "Languages" dropdown next to Play: the original language first, then translations with their completion; picking one starts the version in that language - The game header gets the same dropdown, aggregated over published, ready versions. Each language points at the version that has it best (most complete, the main version on a tie); an original language counts as complete - The old row of language tags linking to the translation editor is replaced - Backend: versions carry source_name (the name of the original language) - pages/languages.ts holds the aggregation logic with tests; LanguageMenu closes on outside click and Escape Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
63 lines
3.4 KiB
JavaScript
63 lines
3.4 KiB
JavaScript
import assert from "node:assert/strict";
|
|
import { fileURLToPath } from "node:url";
|
|
import { test } from "node:test";
|
|
import { build } from "esbuild";
|
|
|
|
const compiled = await build({ entryPoints: [fileURLToPath(new URL("../src/pages/languages.ts", import.meta.url))],
|
|
bundle: true, write: false, format: "esm", platform: "node", logLevel: "silent" });
|
|
const { versionLanguages, aggregateLanguages } =
|
|
await import(`data:text/javascript;base64,${Buffer.from(compiled.outputFiles[0].text).toString("base64")}`);
|
|
|
|
const version = (id, extra = {}) => ({ id, status: "ready", visibility: "published", source_lang: "en", source_name: "English",
|
|
languages: [], ...extra });
|
|
const ru = (progress) => ({ code: "ru", name: "Русский", progress });
|
|
|
|
test("a version lists its original language first, then its translations", () => {
|
|
const entries = versionLanguages(version(1, { languages: [ru(0.5), { code: "de", name: "Deutsch", progress: 1 }] }));
|
|
assert.deepEqual(entries.map((e) => [e.code, e.source, e.progress]), [["en", true, 1], ["ru", false, 0.5], ["de", false, 1]]);
|
|
assert.ok(entries.every((e) => e.versionId === 1));
|
|
});
|
|
|
|
test("an unknown original language is not shown, and a translation never repeats it", () => {
|
|
assert.deepEqual(versionLanguages(version(1, { source_lang: "und", source_name: null })), []);
|
|
assert.deepEqual(versionLanguages(version(1, { source_lang: null })), []);
|
|
const same = versionLanguages(version(1, { languages: [{ code: "en", name: "English", progress: 0.2 }] }));
|
|
assert.equal(same.length, 1);
|
|
assert.equal(same[0].source, true);
|
|
});
|
|
|
|
test("the game lists the languages of every published ready version", () => {
|
|
const entries = aggregateLanguages([
|
|
version(1),
|
|
version(2, { languages: [ru(0.4)] }),
|
|
version(3, { languages: [{ code: "fr", name: "Français", progress: 0.9 }] }),
|
|
], 1);
|
|
assert.deepEqual(entries.map((e) => e.code), ["en", "fr", "ru"], "original first, then by progress");
|
|
assert.equal(entries.find((e) => e.code === "ru").versionId, 2);
|
|
});
|
|
|
|
test("drafts, unfinished and failed versions do not add languages", () => {
|
|
const entries = aggregateLanguages([
|
|
version(1),
|
|
version(2, { visibility: "draft", languages: [ru(1)] }),
|
|
version(3, { status: "converting", languages: [{ code: "de", name: "Deutsch", progress: 1 }] }),
|
|
version(4, { status: "failed", languages: [{ code: "fr", name: "Français", progress: 1 }] }),
|
|
], 1);
|
|
assert.deepEqual(entries.map((e) => e.code), ["en"]);
|
|
});
|
|
|
|
test("when several versions have a language the most complete wins, the main one on a tie", () => {
|
|
const versions = [version(1, { languages: [ru(0.5)] }), version(2, { languages: [ru(0.9)] }), version(3, { languages: [ru(0.9)] })];
|
|
assert.equal(aggregateLanguages(versions, 1).find((e) => e.code === "ru").versionId, 2, "more complete");
|
|
assert.equal(aggregateLanguages(versions, 3).find((e) => e.code === "ru").versionId, 3, "main version on a tie");
|
|
});
|
|
|
|
test("an original language of one version counts as complete even if another has it as a translation", () => {
|
|
const entries = aggregateLanguages([version(1, { source_lang: "ru", source_name: "Русский" }),
|
|
version(2, { languages: [ru(0.3)] })], 1);
|
|
const russian = entries.find((e) => e.code === "ru");
|
|
assert.equal(russian.source, true);
|
|
assert.equal(russian.versionId, 1);
|
|
assert.equal(entries[0].code, "ru", "an original language is listed first");
|
|
});
|