feat(inspirations): 灵感库 - 将内置英文提示词统一为中文 (#763)

* feat(inspirations): 灵感库 - 统一中文正文入口并校验译文版本

* feat(inspirations): 灵感库 - 发布完整中文提示词并阻止旧译文覆盖

统一 1319 条外部提示词和 329 条画廊引用,保留来源与模板参数;校验全部原文摘要,防止上游更新后误用过期中文。

验证:Bun 1.3.9 全量 2261 项测试通过,前端构建与 lint 通过,目录身份及媒体元数据对比无变化。
This commit is contained in:
Medivh authored and GitHub committed 2026-10-13 19:12:44 +08:00
1 parent 26dfb8d91b
commit 88de4ce422
12 files changed
+6673 -1705

No files matched your search

+48
View File
@@ -0,0 +1,48 @@
import { describe, expect, test } from "bun:test";
import { createHash } from "node:crypto";
import { readFileSync } from "node:fs";
import { localizeInspirationEntries } from "../scripts/inspiration-localization.mjs";
const hash = (text: string) => createHash("sha256").update(text).digest("hex");
const original = { id: "seedance:sample", prompt: "A slow tracking shot, 16:9, 10 seconds.", image: "/cover.webp", videoUrl: "https://example.com/video.mp4", sourceUrl: "https://example.com/source" };
describe("Chinese inspiration catalogs", () => {
test("replaces the complete prompt while preserving media, identity and attribution", () => {
const translated = "缓慢跟拍镜头,16:9,10 秒。";
const [entry] = localizeInspirationEntries([original], { [original.id]: { sourceHash: hash(original.prompt), prompt: translated, title: "缓慢跟拍", description: "横屏十秒镜头" } });
expect(entry).toEqual({ ...original, prompt: translated, title: "缓慢跟拍", description: "横屏十秒镜头" });
expect(original.prompt).toStartWith("A slow");
});
test("uses the verified translation even when upstream supplies another Chinese body", () => {
const [entry] = localizeInspirationEntries([{ ...original, promptZh: "原站提供的旧中文提示词。" }], { [original.id]: { sourceHash: hash(original.prompt), prompt: "已校对的完整中文提示词。" } });
expect(entry.prompt).toBe("已校对的完整中文提示词。");
expect(entry.promptZh).toBeUndefined();
});
test("upstream Chinese cannot bypass missing or stale translation approval", () => {
for (const records of [{}, { [original.id]: { sourceHash: hash("old prompt"), prompt: "旧翻译" } }]) {
expect(() => localizeInspirationEntries([{ ...original, promptZh: "旧中文" }], records)).toThrow();
}
});
test("rejects missing, outdated and non-Chinese translations instead of restoring English", () => {
for (const records of [{}, { [original.id]: { sourceHash: hash("old prompt"), prompt: "旧翻译" } }, { [original.id]: { sourceHash: hash(original.prompt), prompt: "Still English" } }]) {
expect(() => localizeInspirationEntries([original], records)).toThrow();
}
});
test("every shipped catalog prompt is Chinese and the gallery uses the same complete text", () => {
const all = new Map<string, string>();
for (const name of ["seedance", "haohaoxue", "youmind"]) {
const pack = JSON.parse(readFileSync(new URL(`../public/inspirations/${name}.json`, import.meta.url), "utf8"));
for (const item of pack.entries) {
expect(item.prompt).toMatch(/[\u3400-\u9fff]/);
expect(item.promptZh).toBeUndefined();
all.set(item.id, item.prompt);
}
}
const gallery = JSON.parse(readFileSync(new URL("../public/inspirations/gallery-pool.json", import.meta.url), "utf8"));
for (const item of gallery.entries) expect(item.prompt).toBe(all.get(item.id));
});
});