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

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

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

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

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

File diff suppressed because one or more lines are too long

View File

@@ -13,6 +13,7 @@
*/
import { existsSync, mkdirSync, readdirSync, readFileSync, statSync, unlinkSync, writeFileSync } from "node:fs";
import { dirname, join, resolve } from "node:path";
import { localizeInspirationEntries } from "./inspiration-localization.mjs";
const WEB_DIR = resolve(import.meta.dir, "..");
const PUBLIC_DIR = join(WEB_DIR, "public", "inspirations");
@@ -487,6 +488,14 @@ async function main() {
const selected = SOURCE_PIPELINES.filter((pipeline) => !options.only || options.only === pipeline.name);
if (!selected.length) throw new Error(`--only 不认识的来源: ${options.only}`);
const translations = JSON.parse(readFileSync(join(WEB_DIR, "scripts", "data", "inspiration-prompts-zh.json"), "utf8"));
const localizedSources = new Map();
// 先检查所有选中来源的中文覆盖,再下载封面或写目录,避免半批更新后才发现缺译。
for (const pipeline of selected) {
const loaded = await pipeline.load(options);
localizedSources.set(pipeline.name, { ...loaded, entries: localizeInspirationEntries(loaded.entries, translations) });
}
mkdirSync(PUBLIC_DIR, { recursive: true });
const revisions = {};
const counts = {};
@@ -508,7 +517,7 @@ async function main() {
continue;
}
const loaded = await pipeline.load(options);
const loaded = localizedSources.get(pipeline.name);
const { entries } = loaded;
if (!entries.length) throw new Error(`${pipeline.name} 没有解析出任何条目`);
revisions[pipeline.name] = loaded.revision;

View File

@@ -0,0 +1,20 @@
import { createHash } from "node:crypto";
/** 原文变更必须重新确认译文,不能只按 id 套用已过期的中文。 */
export function localizeInspirationEntries(entries, translations) {
return entries.map(({ promptZh, ...entry }) => {
const translation = translations[entry.id];
const sourceHash = createHash("sha256").update(entry.prompt).digest("hex");
if (!translation || translation.sourceHash !== sourceHash) {
throw new Error(`灵感缺少匹配当前原文的中文正文:${entry.id}。请更新 scripts/data/inspiration-prompts-zh.json 后再导入。`);
}
const prompt = translation.prompt?.trim();
if (!prompt || !/[㐀-䶿一-鿿]/.test(prompt)) throw new Error(`灵感中文正文无效:${entry.id}`);
return {
...entry,
...(translation?.title ? { title: translation.title } : {}),
...(translation?.description ? { description: translation.description } : {}),
prompt,
};
});
}