feat: lines with style tags inside words are translated without them and marked fuzzy
CI / frontend (push) Failing after 24s
CI / backend (push) Failing after 45s

Decorative Ren'Py tags cannot survive translation mid-word; retry without them when the translator rejects the answer.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
mrleo1nidandClaude Sonnet 5.5 committed 2026-10-25 20:57:46 +03:00
1 parent fb03204726
commit 262db2687e
6 files changed
+123 -26

No files matched your search

+39
View File
@@ -196,3 +196,42 @@ test("a slow page is saved line by line while it is still running", async () =>
assert.ok(seen.includes(1) && seen.includes(2), "progress is reported before the page ends");
assert.equal(seen.at(-1), 3);
});
test("decorative tags inside words are not sent to the model and the line is marked for a look", async () => {
const sent = [];
const translator = fakeTranslator();
const client = { ...translator, async createJob(project, items, size) { sent.push(items.map((i) => i.text)); return translator.createJob(project, items, size); } };
const server = fakeServer(["Y-yo{size=25}o{/size}u're so d{size=38}e{/size}ep...", "{i}Hello{/i} {w}"]);
const saves = [];
const save = server.save;
server.save = async (r) => { saves.push(...r); await save(r); };
await run(client, server, { pageSize: 10 });
assert.deepEqual(sent[0], ["Y-yo" + "o" + "u're so d" + "e" + "ep...", "{i}Hello{/i} {w}"]);
assert.deepEqual(saves.map((s) => [s.key, s.state]), [["k0", "fuzzy"], ["k1", undefined]]);
});
test("a line the model cannot return with its tags is translated again without them", async () => {
const saves = [];
const jobs = new Map();
const client = {
async createJob(_p, items) {
const id = `j${jobs.size}`;
// the first attempt fails for lines that still carry tags
const job = { id, status: "completed", model: "m", error: null, items: items.map((it) => /\{/.test(it.text)
? { id: it.id, source: it.text, translation: null, status: "failed", error: "Protected tokens were changed" }
: { id: it.id, source: it.text, translation: `RU ${it.text}`, status: "completed", error: null }) };
jobs.set(id, job);
return job;
},
async job(id) { return jobs.get(id); },
async cancel(id) { return { ...jobs.get(id), status: "cancelled" }; },
};
const server = fakeServer(["Be {i}very{/i} careful", "Keep {w} this"]);
const save = server.save;
server.save = async (r) => { saves.push(...r); await save(r); };
const seen = [];
await run(client, server, { pageSize: 10, onProgress: (p) => seen.push(p) });
// the style tag is dropped and the line flagged; a line with a gameplay tag stays untranslated
assert.deepEqual(saves, [{ key: "k0", text: "RU Be very careful", state: "fuzzy" }]);
assert.deepEqual([seen.at(-1).done, seen.at(-1).failed], [1, 1]);
});