diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7d608ac..2730aea 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,9 @@
## v1.62.0 — unreleased
+- 同一个东西只用一个名字:界面上的“配方”统一叫 **工作流**(工作流页的卡片、保存和导出、操作记录、备份说明),“配方包”保留,它是发给别人的 .zip;AI 工作台里统一用“素材”“留言”“节点结构”“连接”“副本”“撤销”。
+- One name for each thing: what the screen called a recipe is a **workflow** everywhere (the Workflows page, saving and exporting, the activity log, backups); a recipe package stays the .zip you give to others. The AI workbench says materials, message, node map and copy throughout.
+
- 标注窗口的“同时做成重绘遮罩”勾选框换成 **怎么改** 三选一:交给 AI 判断、只改标出的地方(其余保持原样,AMB 做好遮罩,AI 只重绘这些地方)、整张重新出图。你选的会作为你的要求写在 AI 收到的第一句,时间线里那条标注也写着“改法:…”;用“涂重绘区”笔刷时自动选中“只改标出的地方”。
- The marker's "make a repaint mask" checkbox is now **How to change it**, one of three: leave it to the AI, only the marked areas (the rest stays; Anomalous makes the mask and the AI repaints just those), or the whole picture anew. The choice is the first thing the AI reads, as yours, and the timeline row says it; painting with the repaint brush picks "only the marked areas".
diff --git a/README.md b/README.md
index 70caad7..8abbcbd 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
# 🚀 Anomalous Model Browser
**A model browser and creative workspace for ComfyUI**
-*模型库 · 出图图库 · 工作流配方 · 搭配 · 提示词 · 角色配音 · 模型检查 · 操作记录*
+*模型库 · 出图图库 · 工作流 · 搭配 · 提示词 · 角色配音 · 模型检查 · 操作记录*
@@ -86,10 +86,10 @@ Every page has an icon on the rail at the left of the window.
| Page | What you do there |
| :--- | :--- |
| **🏠 Home** | Pick what you want to do: a card per task, first steps (scan your model folders, a guided tour of the interface) and your latest activity. |
-| **🕘 Activity** | Everything the plugin changed, by day: on the canvas (which node settings changed from what to what, nodes added or removed, workflows opened) and in files (models, covers, recipes, materials, notes, images, audio). **Find on canvas** jumps to the node; a canvas change can be undone with **Undo** until something changes it again, the rest is recorded only. Your own edits are not listed. |
+| **🕘 Activity** | Everything the plugin changed, by day: on the canvas (which node settings changed from what to what, nodes added or removed, workflows opened) and in files (models, covers, workflows, materials, notes, images, audio). **Find on canvas** jumps to the node; a canvas change can be undone with **Undo** until something changes it again, the rest is recorded only. Your own edits are not listed. |
| **📦 Models** | Your models with covers, trigger words and base model. Chips at the top switch between types (Checkpoint, LoRA, VAE…) and list a whole type, subfolders included; the folder list narrows it to one folder. **+** adds a loader node to the canvas; edit a model's name, notes and cover, or scan just that model. |
| **🖼️ Gallery** | Your ComfyUI `output` folder. Search by prompt, model, LoRA, seed, file name or model hash; open an image to see the parameters it was made with, or drag it onto the canvas to get its workflow back. **☆** keeps a good one as a whole workflow, a combo (model, LoRAs, prompt) or just its prompts. |
-| **🪡 Workflows** | Workflow recipes: save a whole workflow or a part of one together with its models, cover, notes and parameters. Each card shows whether the models are on this computer; drag it onto the canvas to load it. Versions can be compared and restored. A card's export button makes a **recipe package** (.zip) to give to someone; dropped into their ⇅, it becomes a recipe card. |
+| **🪡 Workflows** | Saved workflows: save a whole workflow or a part of one together with its models, cover, notes and parameters. Each card shows whether the models are on this computer; drag it onto the canvas to load it. Versions can be compared and restored. A card's export button makes a **recipe package** (.zip) to give to someone; dropped into their ⇅, it becomes a workflow card. |
| **🧩 Combos** | A main model, a few LoRAs and a prompt you like, kept together. **Put on canvas** (or dragging the card onto the canvas) lays them out as a wired group of nodes; nothing already on the canvas changes. |
| **✍️ Prompts** | Prompt Studio, a page of the browser; **Beside the canvas** moves it next to the canvas to see both. Select a prompt node and its prompt boxes appear as tags, edited in place: click a tag to make it stronger or weaker, double-click to edit, drag to reorder, type to add (Chinese, Japanese and other languages are translated to English), and show each tag's meaning in Chinese, Japanese, Korean and other languages. Click a card (a few common ones, plus your saved prompts) to add it, or drag it straight onto a prompt box on the canvas (outlined green for positive, red for negative) or onto empty canvas for a new prompt node. With no prompt node selected you write a draft. |
| **🎙️ Voices / 🎧 Audio** | With [Anomalous_TTS](https://github.com/DemonGatanjieu/Anomalous_TTS) installed: import GPT-SoVITS characters, pick a reference clip per emotion, fix pronunciations, write a script under Voice-over on the same page and generate it right there; generated audio is listed in the audio gallery. Without it, the page explains how to install it and nothing else depends on it. |
@@ -122,7 +122,7 @@ Open the browser with **Shift + B** (again to close), the floating button on the
**Network:** Scan looks models up on Civitai and prompt translation uses Google Translate, so both need to reach those sites (from mainland China usually through a proxy; when civitai.com cannot be reached the plugin tries Civitai's other address, civitai.red, which some networks reach, a cloud server in mainland China among them: names and trigger words come, covers usually not). Without them, pick **Offline** on the scan page (an online scan does the same by itself when it cannot connect): base models are read from the files, without covers or trigger words, and a later online scan fills in the rest. Downloading missing models needs the network too; for Hugging Face, **Settings → Model downloads** can use the hf-mirror.com mirror (Civitai has none). Browsing models, outputs, workflows and combos needs no network.
-**Keep a copy of your own data:** **Settings → Backup → Export** packs Workflow Recipes, combos, saved prompts and node values, parameter presets, and the names, notes and covers you gave your models into one .zip; keep it on a cloud drive or a USB stick, and **Import** puts it back, also on another computer. (They live in `workflows/anomalous_recipes`, `workflows/anomalous_notebooks`, `workflows/anomalous_materials` and `workflows/anomalous_parameters` in your ComfyUI user folder.)
+**Keep a copy of your own data:** **Settings → Backup → Export** packs workflows, combos, saved prompts and node values, parameter presets, and the names, notes and covers you gave your models into one .zip; keep it on a cloud drive or a USB stick, and **Import** puts it back, also on another computer. (They live in `workflows/anomalous_recipes`, `workflows/anomalous_notebooks`, `workflows/anomalous_materials` and `workflows/anomalous_parameters` in your ComfyUI user folder.)
@@ -198,10 +198,10 @@ Open the browser with **Shift + B** (again to close), the floating button on the
| 页面 | 在这里做什么 |
| :--- | :--- |
| **🏠 主页** | 想做什么就点哪张卡片。还有上手第一步(扫描模型文件夹、界面导览)和最近的操作记录。 |
-| **🕘 记录** | 按天列出插件做过的每一处改动。 画布上:哪个节点的设置从什么改成了什么、加了或删了哪些节点、打开了哪个工作流。 文件上:模型、封面、配方、素材、笔记、图片、音频。 **在画布上找到** 可以直接跳到那个节点;画布上的改动在没被再改过之前可以点 **撤销**,其余只记录。你自己在画布上的修改不会记进来。 |
+| **🕘 记录** | 按天列出插件做过的每一处改动。 画布上:哪个节点的设置从什么改成了什么、加了或删了哪些节点、打开了哪个工作流。 文件上:模型、封面、工作流、素材、笔记、图片、音频。 **在画布上找到** 可以直接跳到那个节点;画布上的改动在没被再改过之前可以点 **撤销**,其余只记录。你自己在画布上的修改不会记进来。 |
| **📦 模型** | 模型带封面、触发词和底模信息。 顶部标签切换类型(Checkpoint、LoRA、VAE…),连同子文件夹一起列出;左侧文件夹列表可以只看某个文件夹。 **+** 一键在画布上创建加载节点;也可以改名、写备注、换封面,或只扫描这一个模型。 |
| **🖼️ 图库** | 读取 ComfyUI 的 `output` 文件夹。 可以按提示词、模型、LoRA、seed、文件名或模型哈希搜索。 点开图片能看到生成参数;拖到画布上可以还原当时的工作流。 觉得好就点 **☆**:存成整个工作流、搭配(模型 + LoRA + 提示词),或者只存提示词。 |
-| **🪡 工作流** | 工作流配方:把完整工作流或其中一段,连同模型、封面、备注和参数一起存下来。 卡片会显示这台电脑上模型是否齐全;拖到画布上即可载入。 可以比较、恢复历史版本。 卡片上的导出按钮能打成**配方包**(压缩包)发给别人,对方拖进 ⇅ 就多一张配方卡片。 |
+| **🪡 工作流** | 存下的工作流:把完整工作流或其中一段,连同模型、封面、备注和参数一起存下来。 卡片会显示这台电脑上模型是否齐全;拖到画布上即可载入。 可以比较、恢复历史版本。 卡片上的导出按钮能打成**配方包**(压缩包)发给别人,对方拖进 ⇅ 就多一张工作流卡片。 |
| **🧩 搭配** | 把常用的主模型、几个 LoRA 和一段提示词存成一个搭配。 按 **放到画布**(或把卡片拖到画布上),就放出一组连好线的节点;画布上原有的东西不动。 |
| **✍️ 提示词** | 提示词工坊,浏览器里的一个页面;点“停到画布旁”可以移到画布旁边,边看画布边改。选中一个提示词节点,它的提示词框就以词块的样子出现在工坊里,直接改:点一下调权重,双击改字,拖动换位置,输入就加(中文、日文等会自动译成英文),还能在每个词下面显示它的中文、日文、韩文等语言的意思。 点词卡(几张常用的,加上你存的)加进去,或者直接拖到画布的提示词框里(正面绿框、负面红框),拖到空白处就新建一个提示词节点。没选中提示词节点时写的是草稿。 |
| **🎙️ 角色语音 / 🎧 音频库** | 装了 [Anomalous_TTS](https://github.com/DemonGatanjieu/Anomalous_TTS) 后可用: 导入 GPT-SoVITS 角色,给每种情绪选参考音频,修正读音;切到“配音”写台词并直接生成。 生成的音频都在音频库里。没装时,页面会说明怎么安装,其他功能不受影响。 |
@@ -237,7 +237,7 @@ Open the browser with **Shift + B** (again to close), the floating button on the
**关于网络:** 扫描模型要连 Civitai(C 站)查封面和触发词,提示词翻译默认用谷歌翻译,这两样在国内一般要开网络代理才能用。不开代理也行:扫描页选 **离线**(联网扫描连不上时也会自动改成这样),只从模型文件推断底模,没有封面和触发词,以后能连上时再扫一次会自动补上。下载缺失的模型也要联网:Hugging Face 的模型可以在 **设置 → 模型下载** 里打开“Hugging Face 用国内镜像”,不用代理;C 站的没有镜像。(civitai.com 连不上时插件会自动试 Civitai 的另一个地址 civitai.red,有的网络能连上,比如国内的云服务器,这时能认出模型名字和触发词,封面多半还是下不来。)浏览模型、图库、工作流和搭配都不用联网。
-**备份自己的数据:** **设置 → 备份 → 导出**,把工作流配方、搭配、存下的提示词和节点参数、参数预设,以及你给模型改的名字、备注和封面打成一个压缩包,放到云端硬盘或 U 盘里;换电脑或重装后用 **导入** 恢复。(它们存在 ComfyUI 用户目录下的 `workflows/anomalous_recipes`、`workflows/anomalous_notebooks`、`workflows/anomalous_materials` 与 `workflows/anomalous_parameters`。)
+**备份自己的数据:** **设置 → 备份 → 导出**,把工作流、搭配、存下的提示词和节点参数、参数预设,以及你给模型改的名字、备注和封面打成一个压缩包,放到云端硬盘或 U 盘里;换电脑或重装后用 **导入** 恢复。(它们存在 ComfyUI 用户目录下的 `workflows/anomalous_recipes`、`workflows/anomalous_notebooks`、`workflows/anomalous_materials` 与 `workflows/anomalous_parameters`。)
diff --git a/docs/architecture/ui-flows.md b/docs/architecture/ui-flows.md
index 51d6dc5..77879d0 100644
--- a/docs/architecture/ui-flows.md
+++ b/docs/architecture/ui-flows.md
@@ -103,8 +103,12 @@ node tools/ui_map.mjs build 写出 docs/ui-map.md:按页面列
| 展台 | stage | 画板、舞台 | — |
| 成果 | results | 产出 | — |
| 关卡 | gates | 闸门 | — |
+| 工作流(存下的整套工作流,“工作流”页的卡片) | workflow | 配方(配方包、搭配方案除外) | recipe(recipe package 除外)、recipes |
+| 配方包(把一个工作流打包发给别人的 .zip) | recipe package | — | — |
+| 搭配(主模型 + LoRA + 提示词) | combo | — | — |
+
+“不再用”里可以写例外,比如“配方(配方包、搭配方案除外)”:这两个词里的“配方”不算。`{recipe}` 这样的占位符也不算。
## 还没统一的
-- **工作流 / 配方**:左边栏和页面标题叫“工作流”,但还有大约 60 条文字叫“配方”(比如“更新当前配方”)。“配方包 .zip”是单独的分享格式,要分开。等决定以后再加进上面的表。
- `node tools/ui_map.mjs build` 的最后一节列出没有文件用到的文字(目前 33 条),清理前先确认不是拼出来的 key。
diff --git a/docs/guides/mcp.md b/docs/guides/mcp.md
index 9b6efac..32249d8 100644
--- a/docs/guides/mcp.md
+++ b/docs/guides/mcp.md
@@ -90,7 +90,7 @@ claude mcp add --transport http anomalous http://127.0.0.1:8188/anomalous/mcp
| scan_report | 哪些模型匹配上了 C 站,哪些没有、原因是什么,哪些还没扫,上次扫描做了什么 |
| search_images / get_image_info | 按提示词、模型、参数找出图;看某张图的全部生成参数,可以附上缩略图。`folder=input` 时看 ComfyUI 输入文件夹里的图(比如你标注时 AMB 存的重绘遮罩图):尺寸、要重画的区域在哪、占多大,也能附上图,不用 AI 自己跑命令去看 |
| list_combos | 你的搭配(主模型 + LoRA + 提示词) |
-| list_workflows | 你的工作流配方,带标签、备注和主要设置 |
+| list_workflows | 你存下的工作流,带标签、备注和主要设置 |
| list_saved_prompts | 提示词工坊里存的提示词 |
| search_audio | 用 Anomalous TTS 生成过的语音,带台词和角色 |
| recent_activity | 插件最近改过什么(操作记录) |
diff --git a/tests/ui_map.mjs b/tests/ui_map.mjs
index c3ca389..19a6ef8 100644
--- a/tests/ui_map.mjs
+++ b/tests/ui_map.mjs
@@ -29,4 +29,10 @@ assert.match(wrong[1], /ui_ai_nothing_here\.js/);
assert.match(wrong[2], /no_such_route/);
assert.match(wrong[3], /"新任务" is retired/);
+// A retired name with where it is not that name: 配方包 and 搭配方案 are not 配方, {recipe} is no word on screen.
+const glossary = (zh, en) => check(['## 统一叫法', '| 说法 | English | 不再用 | 不再用(English) |', '| --- | --- | --- | --- |', `| 工作流 | workflow | ${zh} | ${en} |`].join('\n'));
+assert.deepEqual(await glossary('配方(配方包、搭配方案除外)', 'recipe(recipe package 除外)、recipes'), []);
+assert.match((await glossary('配方', '—')).join('\n'), /"配方" is retired/, 'without the exceptions 配方包 counts');
+assert.match((await glossary('—', 'recipe')).join('\n'), /"recipe" is retired/);
+
console.log('ui map ok');
diff --git a/tools/ui_map.mjs b/tools/ui_map.mjs
index 34f66a8..8e33b28 100644
--- a/tools/ui_map.mjs
+++ b/tools/ui_map.mjs
@@ -170,15 +170,19 @@ export async function check(doc = null) {
if (token.startsWith('/anomalous/') && !index.routes.some(route => route.shape.startsWith(routeShape(token.replace(/^(GET|POST) /, ''))))) failures.push(`${where}: no backend route \`${token}\``);
}
});
- // The glossary: one name for each thing; the names it retired are not on screen.
+ // The glossary: one name for each thing; the names it retired are not on screen. A retired name
+ // may list where it is not that name ("配方(配方包、搭配方案除外)"); {placeholders} do not count.
const glossary = doc.split(/^## /m).find(part => part.startsWith('统一叫法')) || '';
for (const row of glossary.split('\n').filter(item => /^\|/.test(item) && !/^\|\s*[-:]/.test(item)).slice(1)) {
const cells = row.split('|').slice(1, -1).map(cell => cell.trim());
const retired = [[cells[2], 'zh'], [cells[3], 'en']];
for (const [list, lang] of retired) {
- for (const word of String(list || '').split(/[、,,]/).map(item => item.replace(/[「」`]/g, '').trim()).filter(item => item && !/^[-—–无]+$/.test(item))) {
- const test = lang === 'en' ? new RegExp(`\\b${word}\\b`, 'i') : null;
- const hits = Object.entries(index.text[lang]).filter(([, value]) => (test ? test.test(value) : String(value).includes(word))).map(([key]) => key);
+ for (const entry of retiredNames(list)) {
+ const [, word, except = ''] = entry.match(/^([^(]+)(?:((.*)))?$/);
+ const others = except.replace(/除外|除了/g, '').split(/[、,,/]/).map(item => item.trim()).filter(Boolean);
+ const bare = value => others.reduce((text, other) => text.split(other).join(' '), String(value).replace(/\{[^}]*\}/g, ' '));
+ const test = lang === 'en' ? new RegExp(`\\b${word.trim()}\\b`, 'i') : null;
+ const hits = Object.entries(index.text[lang]).filter(([, value]) => (test ? test.test(bare(value)) : bare(value).includes(word.trim()))).map(([key]) => key);
if (hits.length) failures.push(`${FLOWS} glossary: "${word}" is retired for 「${cells[0]}」 but still on screen: ${hits.slice(0, 6).join(', ')}`);
}
}
@@ -186,6 +190,19 @@ export async function check(doc = null) {
return failures;
}
+/** A glossary cell's retired names, split at 、 , , outside (…); "—" and 无 are none. */
+function retiredNames(cell) {
+ const out = [''];
+ let depth = 0;
+ for (const char of String(cell || '').replace(/[「」`]/g, '')) {
+ if (char === '(') depth += 1;
+ if (char === ')') depth -= 1;
+ if (!depth && '、,,'.includes(char)) out.push('');
+ else out[out.length - 1] += char;
+ }
+ return out.map(item => item.trim()).filter(item => item && !/^[-—–无]+$/.test(item));
+}
+
function fileExists(token) {
if (fs.existsSync(path.join(ROOT, token))) return true;
const name = path.posix.basename(token);
diff --git a/web/modules/locales.js b/web/modules/locales.js
index b662684..1868935 100644
--- a/web/modules/locales.js
+++ b/web/modules/locales.js
@@ -63,7 +63,7 @@ export const i18n = {
versionConfirmRollback: "从 {from} 回退到 {tag}?",
versionConfirmLatest: "切回默认分支并更新到最新代码?",
versionConfirmUndo: "回到切换前的版本 {label}?",
- versionRollbackDataWarning: "旧版本可能读不懂新版本保存的设置或配方。你的数据不会被删除,回到新版后即可恢复正常。",
+ versionRollbackDataWarning: "旧版本可能读不懂新版本保存的设置或工作流。你的数据不会被删除,回到新版后即可恢复正常。",
versionNoPanelWarning: "{tag} 还没有版本面板。想回到新版时,请在 ComfyUI Manager 里点“更新”这个插件。",
versionRestartNote: "切换后需要重启 ComfyUI 才会生效。",
versionSwitched: "已切换到 {tag}。",
@@ -112,7 +112,7 @@ export const i18n = {
promptCompositionHint: "填写提示词,选择放在前面或后面,再拖到提示词节点。保留节点原有文字,不自动运行。",
nodeValuesSaved: "已存下这些节点的参数。以后选中同类节点,在“当前节点”里就能套用。",
promptDragNoteHint: "按住卡头或便签,直接拖拽至画布节点",
- recipeMoveKept: "以前从出图收下的完整工作流还有 {count} 个没移过来。它们现在都放在这里,以后在图库点 ☆ 也能直接存成配方。",
+ recipeMoveKept: "以前从出图收下的完整工作流还有 {count} 个没移过来。它们现在都放在这里,以后在图库点 ☆ 也能直接存成工作流。",
recipeMoveKeptButton: "移到这里",
recipeMovedKept: "移过来了 {count} 个。原来的文件还在,只是不再单独列出。",
recipeScopePill_all: "全部",
@@ -728,13 +728,13 @@ export const i18n = {
workbenchKeepHint: "把这张图存成工作流、搭配或提示词",
keepMenuTitle: "收藏这张图",
keepAs_recipe: "整个工作流",
- keepAs_recipeHint: "存成工作流配方,在“工作流”页,可以整个打开",
+ keepAs_recipeHint: "存成工作流,在“工作流”页,可以整个打开",
keepAs_combo: "模型搭配",
keepAs_comboHint: "出这张图的模型、LoRA 和正负提示词节点,数值原样记下,在“搭配”页一键放到画布",
keepAs_prompt: "只要提示词",
keepAs_promptHint: "正向和负向提示词,存进提示词库",
keepKeptAs: "已存:{name},点这里打开",
- keptAs_recipe: "已存成工作流配方:{name}",
+ keptAs_recipe: "已存成工作流:{name}",
keptAs_combo: "已存成搭配:{name}",
keptAs_comboShort: "已存成搭配,名字可以直接改:",
comboFromImage: "从这张图存下的搭配",
@@ -769,7 +769,7 @@ export const i18n = {
keepRemoveConfirm: "取消收藏后,存下的{what}“{name}”会移到系统回收站。确定吗?",
keepRemoved: "已取消收藏:{what}“{name}”在回收站里",
keepRemoveFailed: "没能取消收藏,请再试一次。",
- keepNoun_recipe: "工作流配方",
+ keepNoun_recipe: "工作流",
keepNoun_combo: "搭配",
keepNoun_prompt: "提示词",
keepNoPrompt: "这张图的工作流里没找到提示词。",
@@ -916,7 +916,7 @@ export const i18n = {
currentNodeDeleteFailed: "没删掉,请再试一次。",
currentNodeSaveFailed: '没能保存这组参数',
currentNodeSearch: '搜索参数…',
- currentNodeNoSets: "这种节点还没有存过参数。在这里“存下当前参数”、在图库的参数页里存下节点,或配方里的参数方案,都会列在这里。",
+ currentNodeNoSets: "这种节点还没有存过参数。在这里“存下当前参数”、在图库的参数页里存下节点,或工作流里的参数方案,都会列在这里。",
currentNodeNoMatch: '没有匹配的参数',
currentNodeLoadFailed: '没能读出存过的参数',
currentNodeFromSet: '工作流「{recipe}」的参数方案',
@@ -1455,8 +1455,8 @@ export const i18n = {
aiOutRunWorkflow: "出最新那张图的工作流",
aiOutChanges: "AI 改过 {count} 次",
aiOutOpenCanvas: "在画布打开",
- aiOutNeedPicture: "出过图以后,可以在这里按最新那张图存成配方、搭配和提示词。",
- aiOutKeep_recipe: "存成配方",
+ aiOutNeedPicture: "出过图以后,可以在这里按最新那张图存成工作流、搭配和提示词。",
+ aiOutKeep_recipe: "存成工作流",
aiOutKeepTip_recipe: "把出最新那张图的整个工作流存进“工作流”页",
aiOutKeep_combo: "把最新那张图存成搭配",
aiOutKeepTip_combo: "出最新那张图的模型、LoRA 和提示词节点,数值原样记下,存进“搭配”页",
@@ -1922,7 +1922,7 @@ export const i18n = {
aiOutsideFiles: "动到的文件",
aiTool_begin_task: "开始任务",
activityTitle: "操作记录",
- activityLead: "Anomalous 改过的东西都记在这里:画布上改了哪个节点的什么参数,增删了哪些节点,以及模型、配方、搭配、提示词、图片、音频等文件的改动。画布上的改动,在没被再改过之前可以点“撤销”;其余只记录。",
+ activityLead: "Anomalous 改过的东西都记在这里:画布上改了哪个节点的什么参数,增删了哪些节点,以及模型、工作流、搭配、提示词、图片、音频等文件的改动。画布上的改动,在没被再改过之前可以点“撤销”;其余只记录。",
activityAll: "全部",
activityCanvas: "画布",
activityFiles: "文件",
@@ -1972,11 +1972,11 @@ export const i18n = {
activityFieldFilename: "文件名",
activityFileMoved: "移到回收站:{name}",
activityFieldChange: "{field}:{before} → {after}",
- activityRecipeSave: "保存工作流配方",
- activityRecipeEdit: "修改配方",
- activityRecipeDelete: "删除配方",
- activityRecipeRestore: "恢复配方旧版本",
- activityRecipeCover: "设置配方封面",
+ activityRecipeSave: "保存工作流",
+ activityRecipeEdit: "修改工作流",
+ activityRecipeDelete: "删除工作流",
+ activityRecipeRestore: "恢复工作流旧版本",
+ activityRecipeCover: "设置工作流封面",
activityRecipeImport: "导入配方包",
activityMaterialSave: "存下提示词或参数",
activityMaterialEdit: "修改存下的提示词或参数",
@@ -2082,13 +2082,13 @@ export const i18n = {
settingsSidecarsFailed: '没能完成,详情在浏览器控制台里。',
settingsBackup: '备份',
settingsBackupExport: '导出备份',
- settingsBackupExportHelp: '把工作流配方、搭配、素材和存下的提示词、参数方案,以及你给模型改的名字、备注和封面,打成一个压缩包。放到云端硬盘或 U 盘里,换电脑、重装时导回来。',
+ settingsBackupExportHelp: "把工作流、搭配、素材和存下的提示词、参数方案,以及你给模型改的名字、备注和封面,打成一个压缩包。放到云端硬盘或 U 盘里,换电脑、重装时导回来。",
settingsBackupExportButton: '导出',
settingsBackupImport: '导入备份',
settingsBackupImportHelp: '从导出的压缩包恢复。先列出包里有什么;默认只添加这台电脑上没有的,不会删掉任何东西。',
settingsBackupImportButton: '选择文件',
backupExportTitle: '导出备份',
- backupExportIntro: '工作流配方、搭配、素材和存下的提示词、参数方案都会带上,还有插件设置。',
+ backupExportIntro: "工作流、搭配、素材和存下的提示词、参数方案都会带上,还有插件设置。",
backupExportModels: '模型的名字、备注和自选封面',
backupExportModelsHint: '换了电脑也能按文件哈希对回模型。扫描得来的 C 站信息不用带,重新扫描就有。',
backupExportComfyHint: 'ComfyUI 工作流菜单里保存的那些(user/default/workflows)。',
@@ -2120,7 +2120,7 @@ export const i18n = {
backupImportTitle: '导入备份',
backupReading: '正在读取 {name}…',
backupFrom: '{name}:做于 {date},插件版本 {version}。选要导入的部分:',
- backupPart_recipes: '工作流配方',
+ backupPart_recipes: "工作流",
backupPart_combos: '搭配',
backupPart_materials: '素材和存下的提示词',
backupPart_parameters: '参数方案',
@@ -2300,7 +2300,7 @@ export const i18n = {
tidyUsageTitle: '很久没用的模型',
tidyUsagePacksTitle: '很久没用的节点包',
tidyUsagePacksElsewhere: '节点包的整理在 设置 → 节点包 →',
- tidyUsageLead: '按 AMB 记下的每次运行和打开过的工作流、出图和音频里存的记录、保存过的工作流(配方、搭配也算),以及现在开着的标签页来判断。放进来不到 30 天的不算。这里只是建议,删之前看一眼。',
+ tidyUsageLead: "按 AMB 记下的每次运行和打开过的工作流、出图和音频里存的记录、保存过的工作流和搭配,以及现在开着的标签页来判断。放进来不到 30 天的不算。这里只是建议,删之前看一眼。",
tidyUsageRun: '开始查找',
tidyUsageLedger: '运行和打开工作流的记录从 {date} 开始({days} 天)。',
tidyUsageLedgerShort: 'AMB 从 {date} 才开始记录每次运行和打开的工作流({days} 天),比这一档短;更早的只看得到出图和保存的工作流,结果可能不全。',
@@ -2315,7 +2315,7 @@ export const i18n = {
tidyUsageSeenCapped: '看了 {outputs} 个出图(图片和音频)、{saved} 个保存的文件(太多了没看完,结果可能不全)。',
tidyUsageNoOutput: '没找到用过的记录:没运行过,打开过的工作流、出图和保存的工作流里也没有它',
tidyUsageLast: '上次用到:{date}({days} 天前)',
- tidyUsageSaved: '有 {count} 个保存的工作流 / 配方 / 搭配用到它',
+ tidyUsageSaved: "有 {count} 个保存的工作流或搭配用到它",
tidyUsagePicked: '已选 {count} 个,共 {size}',
tidyUsagePickHint: '勾选要清理的模型',
tidyUsageRecycle: '移到回收站',
@@ -2584,10 +2584,10 @@ export const i18n = {
importBtn: '导入工作流 (分享码)',
recipeTitle: '工作流',
recipeSaveCurrent: '保存当前工作流',
- recipeSaveTitle: '保存为工作流配方',
+ recipeSaveTitle: "保存为工作流",
recipeName: '名称',
- recipeDefaultName: '新工作流配方',
- recipeNameRequired: '请填写配方名称。',
+ recipeDefaultName: "新工作流",
+ recipeNameRequired: "请填写工作流名称。",
recipeTags: '标签',
recipeTagsHint: '例如:人像, SDXL, 放大',
recipeNotes: '备注',
@@ -2600,52 +2600,52 @@ export const i18n = {
recipeVerifyOnSave: '保存时核验并写入完整 SHA-256',
recipeVerifyOnSaveHint: '默认不核验;选中后保存可能需要更长时间。',
recipeSaveReceipt: '已保存:{nodes} 个节点,{links} 条连线,{groups} 个分组。',
- recipeSaveReceiptMismatch: '已保存,但完整性回执与当前画布不一致;请重新打开配方核对。',
- recipeLoadError: '无法加载工作流配方。',
- recipeUntitled: '未命名配方',
+ recipeSaveReceiptMismatch: "已保存,但完整性回执与当前画布不一致;请重新打开工作流核对。",
+ recipeLoadError: "无法加载保存的工作流。",
+ recipeUntitled: "未命名工作流",
recipeSearchPlaceholder: '搜索名称、笔记或标签…',
- recipeNoMatches: '没有匹配的配方。请清除搜索或标签筛选。',
+ recipeNoMatches: "没有匹配的工作流。请清除搜索或标签筛选。",
recipeExport: '导出配方包',
recipePackageExportTitle: '导出配方包:{name}',
- recipePackageExportIntro: '把这个配方的工作流、名字、备注、标签、参数、封面和模型缩略图打成一个压缩包发给别人。对方在“工作流”页的 ⇅ 里拖进去,就多一张配方卡片。',
+ recipePackageExportIntro: "把这个工作流连同名字、备注、标签、参数、封面和模型缩略图打成一个压缩包发给别人。对方在“工作流”页的 ⇅ 里拖进去,就多一张工作流卡片。",
recipePackageHistory: '带上版本历史',
recipePackageHistoryHint: '你改过的旧版本。给别人一般不用带。',
recipePackageExportStart: '导出',
recipePackageExported: '已经下载:{name}({size})。用 QQ、微信发的时候按“文件”发。',
recipePackageImportTitle: '导入配方包',
- recipePackageImportWhat: '配方“{name}”:{cover},{pictures} 张模型缩略图。',
+ recipePackageImportWhat: "工作流“{name}”:{cover},{pictures} 张模型缩略图。",
recipePackageImportCover: '有封面',
recipePackageImportNoCover: '没有封面',
recipePackageImportHistory: '还带了 {count} 个旧版本。',
- recipePackageImportRenamed: '你已经有同名的配方,这个会存为“{name}”,原来的不动。',
+ recipePackageImportRenamed: "你已经有同名的工作流,这个会存为“{name}”,原来的不动。",
recipePackageImportModels: '缺的模型,打开工作流时“模型检查”会提示,能一键下载。',
- recipePackageKeep: '存为配方',
- recipePackageKeepAndOpen: '存为配方并打开',
- recipePackageImported: '已存为配方:{name}',
+ recipePackageKeep: "存为工作流",
+ recipePackageKeepAndOpen: "存为工作流并打开",
+ recipePackageImported: "已存为工作流:{name}",
recipeAppendCanvas: '追加到画布',
- recipeAppendError: '无法追加此配方到当前画布。',
+ recipeAppendError: "无法追加此工作流到当前画布。",
recipeOpenCanvas: '新画布打开',
- recipeOpenError: '无法在新画布中打开此配方。',
+ recipeOpenError: "无法在新画布中打开此工作流。",
recipeDragHint: '按住拖拽至画布打开工作流',
recipeDragTargetCanvas: '释放以在画布打开工作流',
recipeCardDragHint: '按住卡片可拖拽至画布打开工作流',
recipeCardPrimaryActionTooltipComplete: '在新画布中打开工作流(也可直接按住卡片拖至画布)',
recipeCardPrimaryActionTooltipPartial: '追加模块至当前画布(也可直接按住卡片拖至画布)',
- recipeEmptyGuideTitle: '工作流配方工坊暂无配方',
+ recipeEmptyGuideTitle: "还没有存下的工作流",
recipeEmptyGuideSubtitle: "把调好的工作流连同模型和参数存下来,下次直接用。",
recipeEmptyStep1Title: '1. 保存当前工作流',
- recipeEmptyStep1Desc: "点右上角“保存当前工作流”,把画布上的工作流和参数存成配方。",
+ recipeEmptyStep1Desc: "点右上角“保存当前工作流”,把画布上的工作流和参数存下来。",
recipeEmptyStep2Title: '2. 画布直接拖拽',
- recipeEmptyStep2Desc: "按住配方卡片拖到画布空白处松开,整套工作流就载入了,不用重新连线。",
+ recipeEmptyStep2Desc: "按住工作流卡片拖到画布空白处松开,整套工作流就载入了,不用重新连线。",
recipeEmptyStep3Title: "3. 缺模型也不怕",
- recipeEmptyStep3Desc: "打开配方时,模型检查会在本机找出改过名、换过文件夹的模型,帮你换上。",
+ recipeEmptyStep3Desc: "打开工作流时,模型检查会在本机找出改过名、换过文件夹的模型,帮你换上。",
recipeEmptySaveCurrentBtn: '保存当前工作流',
recipeScopePartialSaveHint: "这不是能单独运行的完整工作流(比如没有输出节点),会存成“功能模块”:用的时候加到现有画布上。",
recipeScopeCompleteSaveHint: "这是能单独运行的完整工作流,以后可以直接在新画布里打开。",
recipeDelete: '删除',
- recipeDeleteConfirm: '确定删除这个工作流配方吗?配方、历史版本和图片会移到系统回收站。',
- recipeDeleteError: '删除工作流配方失败。',
- recipeSaveError: '保存工作流配方失败。',
+ recipeDeleteConfirm: "确定删除这个工作流吗?它的历史版本和图片会一起移到系统回收站。",
+ recipeDeleteError: "删除工作流失败。",
+ recipeSaveError: "保存工作流失败。",
recipeCopyParameter: '复制参数值',
recipeCopied: '已复制',
recipeCopyFailed: '复制失败',
@@ -2661,23 +2661,23 @@ export const i18n = {
recipeRecentImagesUnavailable: '暂时无法读取最近生成结果。',
recipeKeepImage: '保留当前封面',
recipeEdit: '编辑',
- recipeEditTitle: '编辑工作流配方',
+ recipeEditTitle: "编辑工作流",
recipeHistory: '版本历史',
- recipeHistoryEmpty: '还没有历史版本。更新配方后会自动保留旧版本。',
+ recipeHistoryEmpty: "还没有历史版本。更新工作流后会自动保留旧版本。",
recipeUnknownVersion: '未知时间',
recipeRestoreVersion: '恢复此版本',
- recipeRestoreVersionConfirm: '恢复此版本会覆盖当前配方,但当前内容会先自动存入历史。继续吗?',
+ recipeRestoreVersionConfirm: "恢复此版本会覆盖当前工作流,但当前内容会先自动存入历史。继续吗?",
recipeEditCanvas: '载入画布编辑',
- recipeEditCanvasConfirm: '载入会替换当前画布。完成结构编辑后,点击“更新当前配方”即可保存为新版本。继续吗?',
+ recipeEditCanvasConfirm: "载入会替换当前画布。完成结构编辑后,点击“更新当前工作流”即可保存为新版本。继续吗?",
recipeUpdate: '保存更新',
- recipeUpdateCurrent: '更新当前配方',
- recipeUpdateError: '更新工作流配方失败。',
- recipeDetailBack: '返回配方列表',
+ recipeUpdateCurrent: "更新当前工作流",
+ recipeUpdateError: "更新工作流失败。",
+ recipeDetailBack: "返回工作流列表",
recipeGallery: '图库',
recipeGalleryLoading: '正在查找匹配的历史出图…',
- recipeGalleryEmpty: '未在最近 200 张含工作流数据的 PNG 中找到与此配方结构匹配的出图。',
+ recipeGalleryEmpty: "未在最近 200 张含工作流数据的 PNG 中找到与此工作流结构匹配的出图。",
recipeGalleryRefresh: '刷新匹配结果',
- recipeGalleryLoadError: '无法读取配方图库。',
+ recipeGalleryLoadError: "无法读取这个工作流的图库。",
recipeGalleryScanHint: '已检查最近 {count} 张含工作流数据的 PNG。',
recipeGalleryOpenImage: '查看原图',
recipeGalleryDifferenceHint: '以下是节点参数的差异;图库匹配本身只关注节点类型。',
@@ -2691,13 +2691,13 @@ export const i18n = {
recipeParameterNew: '新建参数方案',
recipeParameterReadCurrent: '从当前画布保存新方案',
recipeParameterReadCurrentError: '无法读取当前画布参数。',
- recipeParameterSkeletonMismatch: '当前画布缺少配方必需的核心节点,无法直接应用参数。',
+ recipeParameterSkeletonMismatch: "当前画布缺少这个工作流必需的核心节点,无法直接应用参数。",
recipeParameterWidgetMismatch: '当前画布的节点输入项与预设不一致:',
recipeParameterNodeUnavailable: '无法在当前画布中定位匹配节点:',
recipeParameterApply: '应用到当前画布',
recipeParameterApplied: '已应用 {count} 项参数',
recipeParameterApplyError: '应用参数失败,当前画布未完成修改。',
- recipeParameterNewHint: '基于当前配方骨架编辑节点参数;种子等运行时变化值会被忽略。保存后会生成新的只读快照,不会覆盖历史记录。',
+ recipeParameterNewHint: "基于当前工作流的骨架编辑节点参数;种子等运行时变化值会被忽略。保存后会生成新的只读快照,不会覆盖历史记录。",
recipeParameterName: '笔记名称',
recipeParameterSave: '保存参数方案',
recipeParameterCancel: '取消编辑',
@@ -2709,7 +2709,7 @@ export const i18n = {
recipeDetailSteps: '步数',
recipeDetailCFG: 'CFG',
recipeDetailDenoise: '降噪',
- recipeDetailNoSavedParameters: '此配方没有可展示的参数。',
+ recipeDetailNoSavedParameters: "此工作流没有可展示的参数。",
recipeDetailVersions: '版本',
recipeDetailModelComposition: "用到的模型",
recipeDetailBaseModel: '主模型',
@@ -2721,7 +2721,7 @@ export const i18n = {
recipeDetailUpdated: '更新时间',
recipeDetailCopyFingerprint: '复制工作流指纹',
recipeDetailPrompts: '提示词',
- recipeDetailNoPrompts: '此配方没有可安全展示的提示词摘要。',
+ recipeDetailNoPrompts: "此工作流没有可安全展示的提示词摘要。",
recipePromptSupportNotice: '当前仅自动识别 ComfyUI 原生 CLIPTextEncode 与已知官方连接;第三方文本节点请手动标注。',
recipePromptRoleChoose: '选择提示词角色',
recipePromptRoleAutomatic: '自动识别',
@@ -2745,7 +2745,7 @@ export const i18n = {
recipeModelNoteEdit: '编辑模型备注',
recipeModelNoteEmpty: '暂无个人模型备注',
recipeModelNoteTitle: '模型个人备注',
- recipeModelNotePrompt: '记录这个模型在当前配方中的用法、建议权重或注意事项。留空保存即可删除备注。',
+ recipeModelNotePrompt: "记录这个模型在当前工作流中的用法、建议权重或注意事项。留空保存即可删除备注。",
recipeModelNoteError: '无法保存模型备注。',
recipeDetailCurrentVersion: '当前版本',
recipeCompareVersion: '对比此版本',
@@ -3483,7 +3483,7 @@ export const i18n = {
versionConfirmRollback: "Roll back from {from} to {tag}?",
versionConfirmLatest: "Switch to the default branch and update to the newest code?",
versionConfirmUndo: "Go back to {label}, the version before the last switch?",
- versionRollbackDataWarning: "Older versions may not understand settings or recipes saved by newer ones. Nothing is deleted; it all works again once you return to the newer version.",
+ versionRollbackDataWarning: "Older versions may not understand settings or workflows saved by newer ones. Nothing is deleted; it all works again once you return to the newer version.",
versionNoPanelWarning: "{tag} does not have this version panel yet. To come back, use \"Update\" for this plugin in ComfyUI Manager.",
versionRestartNote: "Restart ComfyUI afterwards for the change to take effect.",
versionSwitched: "Switched to {tag}.",
@@ -3532,7 +3532,7 @@ export const i18n = {
promptCompositionHint: "Enter prompt text, choose beginning or end, then drag onto a prompt node. Existing text is preserved. This does not start generation.",
nodeValuesSaved: "Saved these nodes' values. Select a node of the same kind and they are in Current node.",
promptDragNoteHint: "Hold card or header to drag onto canvas node",
- recipeMoveKept: "{count} whole workflows kept from your images earlier are not here yet. They belong here now; the gallery's star keeps new ones as recipes.",
+ recipeMoveKept: "{count} whole workflows kept from your images earlier are not here yet. They belong here now; the gallery's star keeps new ones as workflows.",
recipeMoveKeptButton: "Move them here",
recipeMovedKept: "Moved {count}. The original files stay; they are just not listed on their own.",
recipeScopePill_all: "All",
@@ -4148,13 +4148,13 @@ export const i18n = {
workbenchKeepHint: "Keep this image as a workflow, a combo or its prompts",
keepMenuTitle: "Keep this image",
keepAs_recipe: "The whole workflow",
- keepAs_recipeHint: "As a Workflow Recipe on the Workflows page, to open whole",
+ keepAs_recipeHint: "As a workflow on the Workflows page, to open whole",
keepAs_combo: "Its combo",
keepAs_comboHint: "The nodes that made its model and prompts, every value as it was, on the Combos page",
keepAs_prompt: "Just the prompts",
keepAs_promptHint: "The positive and negative prompts, in your saved prompts",
keepKeptAs: "Kept as {name}; open it",
- keptAs_recipe: "Kept as a Workflow Recipe: {name}",
+ keptAs_recipe: "Kept as a workflow: {name}",
keptAs_combo: "Kept as a combo: {name}",
keptAs_comboShort: "Kept as a combo. Rename it here if you like:",
comboFromImage: "Kept from this image",
@@ -4189,7 +4189,7 @@ export const i18n = {
keepRemoveConfirm: "Remove the kept {what} \"{name}\"? It goes to the Recycle Bin.",
keepRemoved: "Removed the {what} \"{name}\"; it is in the Recycle Bin",
keepRemoveFailed: "Could not remove it; please try again.",
- keepNoun_recipe: "workflow recipe",
+ keepNoun_recipe: "workflow",
keepNoun_combo: "combo",
keepNoun_prompt: "prompt",
keepNoPrompt: "This image's workflow has no prompt.",
@@ -4336,7 +4336,7 @@ export const i18n = {
currentNodeDeleteFailed: "Could not delete it; try again.",
currentNodeSaveFailed: 'Could not save these values',
currentNodeSearch: 'Search…',
- currentNodeNoSets: "No values saved for this kind of node yet. Values saved here, nodes saved from an image's parameters and recipe parameter sets show up here.",
+ currentNodeNoSets: "No values saved for this kind of node yet. Values saved here, nodes saved from an image's parameters and the parameter sets of saved workflows show up here.",
currentNodeNoMatch: 'Nothing matches',
currentNodeLoadFailed: 'Could not read the saved values',
currentNodeFromSet: 'Parameter set of the workflow “{recipe}”',
@@ -4876,7 +4876,7 @@ export const i18n = {
aiOutChanges: "The AI changed it {count} {count|time|times}",
aiOutOpenCanvas: "Show on the canvas",
aiOutNeedPicture: "Once there is a picture, its workflow, combo and prompts can be kept from here.",
- aiOutKeep_recipe: "Keep as a recipe",
+ aiOutKeep_recipe: "Keep as a workflow",
aiOutKeepTip_recipe: "Keeps the whole workflow of the newest picture on the Workflows page",
aiOutKeep_combo: "Keep the newest picture's combo",
aiOutKeepTip_combo: "The nodes that made the newest picture's model and prompts, every value as it was, on the Combos page",
@@ -5342,7 +5342,7 @@ export const i18n = {
aiOutsideFiles: "Files",
aiTool_begin_task: "Began the task",
activityTitle: "Activity",
- activityLead: "What Anomalous changed: which node settings it changed on the canvas, which nodes it added or removed, and changes to models, recipes, combos, prompts, images, audio and other files. Canvas changes can be undone here until something changes them again; the rest is only recorded.",
+ activityLead: "What Anomalous changed: which node settings it changed on the canvas, which nodes it added or removed, and changes to models, workflows, combos, prompts, images, audio and other files. Canvas changes can be undone here until something changes them again; the rest is only recorded.",
activityAll: "All",
activityCanvas: "Canvas",
activityFiles: "Files",
@@ -5392,11 +5392,11 @@ export const i18n = {
activityFieldFilename: "file name",
activityFileMoved: "Moved to the Recycle Bin: {name}",
activityFieldChange: "{field}: {before} → {after}",
- activityRecipeSave: "Saved workflow recipe",
- activityRecipeEdit: "Edited recipe",
- activityRecipeDelete: "Deleted recipe",
- activityRecipeRestore: "Restored an older recipe version",
- activityRecipeCover: "Set recipe cover",
+ activityRecipeSave: "Saved workflow",
+ activityRecipeEdit: "Edited workflow",
+ activityRecipeDelete: "Deleted workflow",
+ activityRecipeRestore: "Restored an older workflow version",
+ activityRecipeCover: "Set workflow cover",
activityRecipeImport: "Imported recipe package",
activityMaterialSave: "Saved prompts or values",
activityMaterialEdit: "Edited saved prompts or values",
@@ -5502,13 +5502,13 @@ export const i18n = {
settingsSidecarsFailed: 'This did not finish; the browser console says why.',
settingsBackup: 'Backup',
settingsBackupExport: 'Export a backup',
- settingsBackupExportHelp: 'Workflow Recipes, combos, materials and saved prompts, parameter sets, and the names, notes and covers you gave your models, in one .zip. Keep it on a cloud drive or a USB stick and bring it back on a new computer.',
+ settingsBackupExportHelp: "Workflows, combos, materials and saved prompts, parameter sets, and the names, notes and covers you gave your models, in one .zip. Keep it on a cloud drive or a USB stick and bring it back on a new computer.",
settingsBackupExportButton: 'Export',
settingsBackupImport: 'Import a backup',
settingsBackupImportHelp: 'Puts an exported .zip back. It first lists what is inside; by default only what this computer lacks is added, and nothing is deleted.',
settingsBackupImportButton: 'Choose file',
backupExportTitle: 'Export a backup',
- backupExportIntro: 'Workflow Recipes, combos, materials and saved prompts, parameter sets and the plugin settings are included.',
+ backupExportIntro: "Workflows, combos, materials and saved prompts, parameter sets and the plugin settings are included.",
backupExportModels: "Your models' names, notes and own covers",
backupExportModelsHint: 'Found again by file hash on another computer. What a scan fetched from Civitai is not needed: scan again.',
backupExportComfyHint: "The workflows saved in ComfyUI's workflow menu (user/default/workflows).",
@@ -5540,7 +5540,7 @@ export const i18n = {
backupImportTitle: 'Import a backup',
backupReading: 'Reading {name}…',
backupFrom: '{name}: made {date}, plugin version {version}. Choose what to import:',
- backupPart_recipes: 'Workflow Recipes',
+ backupPart_recipes: "Workflows",
backupPart_combos: 'Combos',
backupPart_materials: 'Materials and saved prompts',
backupPart_parameters: 'Parameter sets',
@@ -5720,7 +5720,7 @@ export const i18n = {
tidyUsageTitle: 'Models not used lately',
tidyUsagePacksTitle: 'Node packs not used lately',
tidyUsagePacksElsewhere: 'Node packs are tidied in Settings → Node packs →',
- tidyUsageLead: 'Judged by the runs and opened workflows AMB notes, what your images and sounds record, your saved workflows (recipes and combos too) and the tabs open now. Anything here for less than 30 days is left out. These are suggestions: have a look before removing anything.',
+ tidyUsageLead: "Judged by the runs and opened workflows AMB notes, what your images and sounds record, your saved workflows and combos, and the tabs open now. Anything here for less than 30 days is left out. These are suggestions: have a look before removing anything.",
tidyUsageRun: 'Look for them',
tidyUsageLedger: 'Runs and opened workflows noted since {date} ({days} days).',
tidyUsageLedgerShort: 'AMB has noted runs and opened workflows only since {date} ({days} days), less than this group asks; before that only the outputs and saved workflows tell, so the result may be incomplete.',
@@ -5735,7 +5735,7 @@ export const i18n = {
tidyUsageSeenCapped: 'Read {outputs} outputs (images and sounds) and {saved} saved files (too many to read them all; the result may be incomplete).',
tidyUsageNoOutput: 'No sign of use: never run, and in no opened workflow, output or saved workflow',
tidyUsageLast: 'Last used: {date} ({days} days ago)',
- tidyUsageSaved: 'Used by {count} saved workflow(s) / recipe(s) / combo(s)',
+ tidyUsageSaved: "Used by {count} saved {count|workflow or combo|workflows or combos}",
tidyUsagePicked: '{count} picked, {size}',
tidyUsagePickHint: 'Tick the models to clear out',
tidyUsageRecycle: 'Move to the Recycle Bin',
@@ -6004,10 +6004,10 @@ export const i18n = {
importBtn: 'Import Workflow (Share Code)',
recipeTitle: 'Workflows',
recipeSaveCurrent: 'Save Current Workflow',
- recipeSaveTitle: 'Save Workflow Recipe',
+ recipeSaveTitle: "Save workflow",
recipeName: 'Name',
- recipeDefaultName: 'New Workflow Recipe',
- recipeNameRequired: 'Enter a recipe name.',
+ recipeDefaultName: "New workflow",
+ recipeNameRequired: "Enter a workflow name.",
recipeTags: 'Tags',
recipeTagsHint: 'For example: portrait, SDXL, upscale',
recipeNotes: 'Notes',
@@ -6020,52 +6020,52 @@ export const i18n = {
recipeVerifyOnSave: 'Verify and save full SHA-256 hashes',
recipeVerifyOnSaveHint: 'Off by default. Saving may take longer when enabled.',
recipeSaveReceipt: 'Saved: {nodes} {nodes|node|nodes}, {links} {links|link|links}, {groups} {groups|group|groups}.',
- recipeSaveReceiptMismatch: 'Saved, but the integrity receipt differs from the current canvas. Reopen the recipe to verify it.',
- recipeLoadError: 'Could not load Workflow Recipes.',
- recipeUntitled: 'Untitled Recipe',
+ recipeSaveReceiptMismatch: "Saved, but the integrity receipt differs from the current canvas. Reopen the workflow to verify it.",
+ recipeLoadError: "Could not load the saved workflows.",
+ recipeUntitled: "Untitled workflow",
recipeSearchPlaceholder: 'Search names, notes, or tags…',
- recipeNoMatches: 'No recipes match. Clear the search or tag filters.',
+ recipeNoMatches: "No workflows match. Clear the search or tag filters.",
recipeExport: 'Export recipe package',
recipePackageExportTitle: 'Export recipe package: {name}',
- recipePackageExportIntro: "This recipe's workflow, name, notes, tags, parameters, cover and model thumbnails in one .zip to give to someone. Dropped into the ⇅ of their Workflows page, it becomes a recipe card.",
+ recipePackageExportIntro: "This workflow with its name, notes, tags, parameters, cover and model thumbnails in one .zip to give to someone. Dropped into the ⇅ of their Workflows page, it becomes a workflow card.",
recipePackageHistory: 'Include its versions',
recipePackageHistoryHint: 'The older versions you saved. Usually not needed by others.',
recipePackageExportStart: 'Export',
recipePackageExported: 'Downloaded: {name} ({size}). In chat apps, send it as a file.',
recipePackageImportTitle: 'Import recipe package',
- recipePackageImportWhat: 'Recipe "{name}": {cover}, {pictures} model thumbnails.',
+ recipePackageImportWhat: "Workflow \"{name}\": {cover}, {pictures} model thumbnails.",
recipePackageImportCover: 'a cover',
recipePackageImportNoCover: 'no cover',
recipePackageImportHistory: 'It also carries {count} older versions.',
- recipePackageImportRenamed: 'You already have a recipe of that name; this one is kept as "{name}" and yours stays.',
+ recipePackageImportRenamed: "You already have a workflow of that name; this one is kept as \"{name}\" and yours stays.",
recipePackageImportModels: 'Model Check tells which models are missing when the workflow opens, and can download them.',
- recipePackageKeep: 'Keep as recipe',
+ recipePackageKeep: "Keep as workflow",
recipePackageKeepAndOpen: 'Keep and open',
- recipePackageImported: 'Kept as recipe: {name}',
+ recipePackageImported: "Kept as workflow: {name}",
recipeAppendCanvas: 'Append to Canvas',
- recipeAppendError: 'Could not append this recipe to the current canvas.',
+ recipeAppendError: "Could not append this workflow to the current canvas.",
recipeOpenCanvas: 'Open in New Canvas',
- recipeOpenError: 'Could not open this recipe in a new canvas.',
+ recipeOpenError: "Could not open this workflow in a new canvas.",
recipeDragHint: 'Drag onto canvas to load workflow',
recipeDragTargetCanvas: 'Drop to load workflow onto canvas',
recipeCardDragHint: 'Hold & drag card onto canvas to load workflow',
recipeCardPrimaryActionTooltipComplete: 'Open workflow in new canvas (or drag & drop card directly)',
recipeCardPrimaryActionTooltipPartial: 'Append module to current canvas (or drag & drop card directly)',
- recipeEmptyGuideTitle: 'Workflow Recipe Studio is Empty',
+ recipeEmptyGuideTitle: "No saved workflows yet",
recipeEmptyGuideSubtitle: "Keep a tuned workflow with its models and settings, and use it again next time.",
recipeEmptyStep1Title: '1. Save Current Workflow',
- recipeEmptyStep1Desc: "Press Save current workflow at the top right to keep the canvas and its settings as a recipe.",
+ recipeEmptyStep1Desc: "Press Save current workflow at the top right to keep the canvas and its settings.",
recipeEmptyStep2Title: '2. Drag onto Canvas',
- recipeEmptyStep2Desc: "Drag a recipe card onto empty canvas and let go: the whole workflow loads, no rewiring.",
+ recipeEmptyStep2Desc: "Drag a workflow card onto empty canvas and let go: the whole workflow loads, no rewiring.",
recipeEmptyStep3Title: "3. Missing models",
- recipeEmptyStep3Desc: "When a recipe opens, Model Check finds models you renamed or moved on this computer and puts them in.",
+ recipeEmptyStep3Desc: "When a workflow opens, Model Check finds models you renamed or moved on this computer and puts them in.",
recipeEmptySaveCurrentBtn: 'Save Current Workflow',
recipeScopePartialSaveHint: "This is not a workflow that runs on its own (no output node, say), so it is saved as a module you add to an open canvas.",
recipeScopeCompleteSaveHint: "This workflow runs on its own; you can open it on a new canvas later.",
recipeDelete: 'Delete',
- recipeDeleteConfirm: 'Delete this Workflow Recipe? The recipe, its versions and images go to the Recycle Bin.',
- recipeDeleteError: 'Could not delete this Workflow Recipe.',
- recipeSaveError: 'Could not save this Workflow Recipe.',
+ recipeDeleteConfirm: "Delete this workflow? It goes to the Recycle Bin with its versions and images.",
+ recipeDeleteError: "Could not delete this workflow.",
+ recipeSaveError: "Could not save this workflow.",
recipeCopyParameter: 'Copy parameter value',
recipeCopied: 'Copied',
recipeCopyFailed: 'Copy failed',
@@ -6081,23 +6081,23 @@ export const i18n = {
recipeRecentImagesUnavailable: 'Recent outputs are currently unavailable.',
recipeKeepImage: 'Keep current cover',
recipeEdit: 'Edit',
- recipeEditTitle: 'Edit Workflow Recipe',
+ recipeEditTitle: "Edit workflow",
recipeHistory: 'Version history',
recipeHistoryEmpty: 'No prior version yet. The previous version is retained automatically on update.',
recipeUnknownVersion: 'Unknown time',
recipeRestoreVersion: 'Restore this version',
- recipeRestoreVersionConfirm: 'Restore this version? The current recipe will first be retained in history.',
+ recipeRestoreVersionConfirm: "Restore this version? The current workflow will first be retained in history.",
recipeEditCanvas: 'Edit on canvas',
- recipeEditCanvasConfirm: 'Loading replaces the current canvas. After structural edits, use Update Current Recipe to save a new version. Continue?',
+ recipeEditCanvasConfirm: "Loading replaces the current canvas. After structural edits, use Update current workflow to save a new version. Continue?",
recipeUpdate: 'Save updates',
- recipeUpdateCurrent: 'Update Current Recipe',
- recipeUpdateError: 'Could not update this Workflow Recipe.',
- recipeDetailBack: 'Back to recipes',
+ recipeUpdateCurrent: "Update current workflow",
+ recipeUpdateError: "Could not update this workflow.",
+ recipeDetailBack: "Back to workflows",
recipeGallery: 'Gallery',
recipeGalleryLoading: 'Finding matching history images…',
recipeGalleryEmpty: 'No matching result was found in the latest 200 PNGs with workflow metadata.',
recipeGalleryRefresh: 'Refresh matches',
- recipeGalleryLoadError: 'Could not load the recipe gallery.',
+ recipeGalleryLoadError: "Could not load this workflow's gallery.",
recipeGalleryScanHint: 'Checked the latest {count} {count|PNG|PNGs} with workflow metadata.',
recipeGalleryOpenImage: 'View full image',
recipeGalleryDifferenceHint: 'These are node-parameter differences; gallery matching only uses node types.',
@@ -6111,13 +6111,13 @@ export const i18n = {
recipeParameterNew: 'New parameter note',
recipeParameterReadCurrent: 'Read current and create',
recipeParameterReadCurrentError: 'Could not read parameters from the current canvas.',
- recipeParameterSkeletonMismatch: 'The current canvas is missing recipe skeleton nodes; nothing was changed.',
+ recipeParameterSkeletonMismatch: "The current canvas is missing this workflow's core nodes; nothing was changed.",
recipeParameterWidgetMismatch: 'The current node widgets do not match this parameter note:',
recipeParameterNodeUnavailable: 'Could not resolve a matching node on the current canvas:',
recipeParameterApply: 'Apply to current workflow',
recipeParameterApplied: 'Applied {count} {count|parameter|parameters}',
recipeParameterApplyError: 'Could not apply parameters; the current canvas was not fully changed.',
- recipeParameterNewHint: 'Edit node parameters from the current recipe skeleton. Runtime-changing values such as seeds are ignored. Saving creates a new read-only snapshot and never overwrites history.',
+ recipeParameterNewHint: "Edit node parameters from the current workflow's skeleton. Runtime-changing values such as seeds are ignored. Saving creates a new read-only snapshot and never overwrites history.",
recipeParameterName: 'Note name',
recipeParameterSave: 'Save parameter note',
recipeParameterCancel: 'Cancel editing',
@@ -6129,7 +6129,7 @@ export const i18n = {
recipeDetailSteps: 'Steps',
recipeDetailCFG: 'CFG',
recipeDetailDenoise: 'Denoise',
- recipeDetailNoSavedParameters: 'This recipe has no displayable parameters.',
+ recipeDetailNoSavedParameters: "This workflow has no displayable parameters.",
recipeDetailVersions: 'Versions',
recipeDetailModelComposition: "Models it uses",
recipeDetailBaseModel: 'Base model',
@@ -6141,7 +6141,7 @@ export const i18n = {
recipeDetailUpdated: 'Updated',
recipeDetailCopyFingerprint: 'Copy workflow fingerprint',
recipeDetailPrompts: 'Prompts',
- recipeDetailNoPrompts: 'This recipe has no safe prompt summary to show.',
+ recipeDetailNoPrompts: "This workflow has no safe prompt summary to show.",
recipePromptSupportNotice: 'Automatic detection currently supports ComfyUI CLIPTextEncode and known official connections only. Label third-party text nodes manually.',
recipePromptRoleChoose: 'Choose prompt role',
recipePromptRoleAutomatic: 'Automatic',
@@ -6165,7 +6165,7 @@ export const i18n = {
recipeModelNoteEdit: 'Edit Model Note',
recipeModelNoteEmpty: 'No personal model note',
recipeModelNoteTitle: 'Personal Model Note',
- recipeModelNotePrompt: 'Record usage, suggested weight, or cautions for this model in the current recipe. Save an empty value to remove the note.',
+ recipeModelNotePrompt: "Record usage, suggested weight, or cautions for this model in the current workflow. Save an empty value to remove the note.",
recipeModelNoteError: 'Could not save the model note.',
recipeDetailCurrentVersion: 'Current version',
recipeCompareVersion: 'Compare version',
diff --git a/web/modules/ui_recipe_catalog.js b/web/modules/ui_recipe_catalog.js
index 4375d24..1cedab6 100644
--- a/web/modules/ui_recipe_catalog.js
+++ b/web/modules/ui_recipe_catalog.js
@@ -150,29 +150,29 @@ export function recipeMatchesFilter(data, query, selectedTags, scope = 'all') {
function renderRecipeEmptyGuide(owner) {
const guide = appendText(owner.recipeListContainer, 'div', '', 'anomalous-recipe-empty-guide');
appendText(guide, 'div', '⚡', 'anomalous-recipe-empty-icon');
- appendText(guide, 'h3', t('recipeEmptyGuideTitle') || '工作流配方工坊暂无配方', 'anomalous-recipe-empty-title');
- appendText(guide, 'p', t('recipeEmptyGuideSubtitle') || '保存、管理与复用 ComfyUI 完整或局部工作流,支持画布直接拖拽载入与模型自愈。', 'anomalous-recipe-empty-subtitle');
+ appendText(guide, 'h3', t('recipeEmptyGuideTitle'), 'anomalous-recipe-empty-title');
+ appendText(guide, 'p', t('recipeEmptyGuideSubtitle'), 'anomalous-recipe-empty-subtitle');
const steps = appendText(guide, 'div', '', 'anomalous-recipe-empty-steps');
const step1 = appendText(steps, 'div', '', 'anomalous-recipe-empty-step');
appendText(step1, 'div', '💾', 'anomalous-recipe-step-icon');
- appendText(step1, 'strong', t('recipeEmptyStep1Title') || '1. 保存当前工作流');
- appendText(step1, 'p', t('recipeEmptyStep1Desc') || '点击右上角“保存当前工作流”按钮,即可将当前画布节点网络与参数保存为配方。');
+ appendText(step1, 'strong', t('recipeEmptyStep1Title'));
+ appendText(step1, 'p', t('recipeEmptyStep1Desc'));
const step2 = appendText(steps, 'div', '', 'anomalous-recipe-empty-step');
appendText(step2, 'div', '🎯', 'anomalous-recipe-step-icon');
- appendText(step2, 'strong', t('recipeEmptyStep2Title') || '2. 画布直接拖拽');
- appendText(step2, 'p', t('recipeEmptyStep2Desc') || '按住配方卡片直接拖拽到 ComfyUI 画布空白处释放,瞬间载入整套工作流,无需重新接线。');
+ appendText(step2, 'strong', t('recipeEmptyStep2Title'));
+ appendText(step2, 'p', t('recipeEmptyStep2Desc'));
const step3 = appendText(steps, 'div', '', 'anomalous-recipe-empty-step');
appendText(step3, 'div', '🩺', 'anomalous-recipe-step-icon');
- appendText(step3, 'strong', t('recipeEmptyStep3Title') || '3. 缺失模型自愈');
- appendText(step3, 'p', t('recipeEmptyStep3Desc') || '若配方中的模型在本地缺失,点击卡片进入详情可智能比对并一键替换为同类可用模型。');
+ appendText(step3, 'strong', t('recipeEmptyStep3Title'));
+ appendText(step3, 'p', t('recipeEmptyStep3Desc'));
const actionBtn = appendText(guide, 'button', '', 'anomalous-recipe-empty-action-btn');
actionBtn.type = 'button';
- actionBtn.innerHTML = `${t('recipeEmptySaveCurrentBtn') || '保存当前工作流'}`;
+ actionBtn.innerHTML = `${t('recipeEmptySaveCurrentBtn')}`;
actionBtn.onclick = () => owner.handleSaveRecipe?.();
}