1364 lines
89 KiB
JavaScript
1364 lines
89 KiB
JavaScript
export const i18n = {
|
||
zh: {
|
||
title: '📦 Anomalous 模型浏览器',
|
||
scan: '🔄 扫描目录并同步 C 站数据',
|
||
scanTitle: '扫描目录',
|
||
scanConfirm: '注意:\n扫描过程将会自动比对 Civitai 并重命名本地模型,同时清理损坏文件。\n确定要开始扫描吗?',
|
||
scanning: '扫描中...',
|
||
scanBg: '🚀 扫描后台启动!',
|
||
scanDone: '完成',
|
||
scanCompleteMsg: '✅ 扫描完成!\n\n⚠️ 提示:由于部分模型已被重命名或去重,请点击 ComfyUI 的 [Refresh] 按钮以同步最新的模型列表。',
|
||
eco: '🔋 视频悬浮播放 (节能模式)',
|
||
autoPlay: '🎬 自动播放视频封面 (高能耗)',
|
||
togglePlayTitle: '切换播放模式',
|
||
clean: '🧹 清理无效的 .info 残留文件',
|
||
cleanTitle: '清理重复 Info',
|
||
cleanConfirm: '将扫描并删除所有无用的 .civitai.info 残留文件。是否继续?',
|
||
cleaning: '清理中',
|
||
cleanDone: '✅ 清理完毕!删除了',
|
||
files: '个文件。',
|
||
cleanFail: '❌ 清理失败: ',
|
||
cleanErr: '❌ 清理出错: ',
|
||
folders: '📂 文件夹',
|
||
collapseAll: '➖ 收起全部',
|
||
expandAll: '➕ 展开全部',
|
||
noModels: '此文件夹中没有找到模型。',
|
||
noPreview: '暂无预览图',
|
||
clickScan: '点击扫描',
|
||
back: '⬅️ 返回',
|
||
delModel: '🗑️ 删除',
|
||
delConfirm: '确定彻底删除',
|
||
delConfirm2: '及其所有关联配置、预览图和缓存文件吗?此操作不可逆!',
|
||
delSuccess: '✅ 删除成功!\n',
|
||
delNote: '\n\n⚠️ 提示:请重启 ComfyUI,否则由于缓存继续使用会报错',
|
||
delFail: '❌ 删除失败: ',
|
||
copyAll: '📋 复制全部',
|
||
copied: '✅ 已复制!',
|
||
clickToCopy: '点击复制: ',
|
||
compatibleModels: '🔗 兼容模型',
|
||
refresh: '刷新',
|
||
loading: '加载中…',
|
||
loadingCompatible: '加载中...',
|
||
backToPrev: '🔙 返回上一层',
|
||
applyToCanvas: '➕ 插入节点',
|
||
applySuccess: '✅ 已添加至工作流',
|
||
help: '帮助',
|
||
helpTitle: '📖 使用手册',
|
||
helpContent: `
|
||
<div style="line-height: 1.6; font-size: 0.95em; color: #eee; padding: 10px;">
|
||
<h3 style="color:#00ffcc; margin-top:0;">📖 标准操作说明</h3>
|
||
<div style="margin:0 0 14px;padding:12px 14px;border:1px solid rgba(255,193,7,.55);border-radius:9px;background:rgba(255,193,7,.1);color:#ffe4a3;"><strong>🧪 测试功能与数据保护</strong><br>工作流配方及节点助手的“参数笔记本”联动目前属于测试功能;节点助手的“动作”页不属于测试范围。更新插件、导入他人配方、恢复版本、删除配方或应用参数前,请先保存当前画布并备份 ComfyUI 用户目录中 <code>workflows/anomalous_recipes</code> 与 <code>workflows/anomalous_parameters</code> 文件夹。模型预览快照不包含模型文件,不能代替模型备份。</div>
|
||
<p><strong>1. 🔄 前置准备 (扫描向导)</strong><br>具体位置:界面左侧底部的 <strong>扫描向导 (🔄)</strong>。<br>这是最重要的前置操作!请先打开扫描向导执行扫描。切记保持网络畅通。部分 C站限制级模型信息需要在设置中填入 API-KEY。扫描完成后,插件的各项功能基本激活。</p>
|
||
<p><strong>2. 🩺 拯救爆红 (模型医生)</strong><br>具体位置:左侧底部第二个 <strong>听诊器 (🩺)</strong> 按钮。<br>当导入别人使用该插件输出的工作流或者图片时,若模型路径爆红,点击模型医生就能智能识别当前所有节点实现正确路径的替换。</p>
|
||
<p><strong>3. 🤖 选中交互与参数预设 (节点助手)</strong><br>具体位置:左侧第三个 <strong>机器人 (🤖)</strong> 按钮。<br>在画布上选中节点后,“动作”页可以可视化替换模型,或在兼容的 MODEL + CLIP 链前后插入 LoRA。“参数笔记本”页会按配方分组读取工作流配方保存的同类型节点参数;点击一条记录即可把参数应用到当前选中节点。例如选中 KSampler 后,可一键载入配方中的采样器、调度器、步数、CFG 与降噪等值;种子等每次运行变化的参数会被忽略。</p>
|
||
<p><strong>4. 🧰 工作流配方与参数笔记本</strong><br>具体位置:打开 <strong>创作工作台</strong>,切换到 <strong>工作流配方</strong>。<br>配方会保存完整工作流、封面、标签、备注、模型引用及常用参数,可追加到当前画布,并支持导入/导出配方包。详情页包含概览、参数笔记本、图库和版本:可匹配本地模型、查看与复制完整参数、比较历史出图参数、比较或恢复配方版本。参数笔记可从当前画布读取同一骨架的新参数,也可编辑安全控件并保存;“应用到当前工作流”只会在骨架匹配后写入参数。第三方提示词节点无法可靠自动判断正负时,可在配方中手动标注。</p>
|
||
<p><strong>5. ⚙️ 个性化配置 (设置面板)</strong><br>具体位置:左侧底部的 <strong>齿轮 (⚙️)</strong> 按钮。<br>可以调节语言、主页面字体大小;进入“模型设置”可选择视频封面始终播放或悬停播放,以及卡片使用流畅缩略图或原始封面。详情页始终保留原图画质。</p>
|
||
<p><strong>6. 📑 顶部导航与提示词笔记</strong><br>具体位置:右侧顶部的按钮分别为 <strong>模型 (📦)</strong>、<strong>图库 (🖼️)</strong>、<strong>创作工作台 (📑)</strong>、<strong>停靠侧边栏 (◧)</strong>。<br>进入创作工作台的“提示词笔记”,点击新建 <strong>➕</strong>。选择基础模型、主模型和 LoRA 后,可通过 <strong>📝纯文本/粘贴</strong> 填入提示词并进行双语对照、分块、查找替换和标签编辑,最后点击 <strong>🚀 发送到画布</strong> 一键组装节点。</p>
|
||
<p><strong>7. 📁 文件夹管理 (Folder Manager)</strong><br>具体位置:设置 (⚙️) 面板内的 <strong>📁 文件夹管理</strong>。<br>可以用来隐藏不需要的内置文件夹。隐藏后的文件夹不仅从侧边栏消失,后端的静默扫描和本地读取也会完全跳过,实现真正的“零性能损耗”。并且可以在这里拖拽调整文件夹在侧边栏显示的顺序。</p>
|
||
<p><strong>8. 📥 工作流导出与导入 (分享码)</strong><br>具体位置:设置 (⚙️) 按钮左侧的 <strong>导入/导出 (📥)</strong> 按钮。<br>该功能可以将当前的工作流一键编码导出为一段专属分享码,方便发到社交平台。别人只需复制这串分享码,在此界面粘贴即可直接还原导入完整的工作流,并且在导入前系统会自动校验模型是否在本地存在。</p>
|
||
<p><strong>9. 💬 提交反馈 / 报告问题</strong><br>具体位置:设置 (⚙️) 面板内的 <strong>💬 提交反馈 / 报告问题</strong>。<br>当你遇到插件报错或有新功能建议时,点击该按钮可一键直达 GitHub Issues 页面提交反馈。</p>
|
||
</div>`,
|
||
notebooks: '笔记本',
|
||
notebookTitle: '笔记本管理',
|
||
workspace: '创作工作台',
|
||
workspaceTitle: '创作工作台',
|
||
promptNotes: '提示词笔记',
|
||
createNotebook: '新建',
|
||
saveNotebook: '💾 保存',
|
||
deleteNotebook: '🗑️ 删除',
|
||
renameNotebook: '✏️ 重命名',
|
||
baseModel: 'Base Model (基础模型)',
|
||
mainModel: 'Main Model (主模型)',
|
||
sendToCanvas: '🚀 发送到画布',
|
||
translate: '翻译',
|
||
newNotebookName: '新笔记本名称',
|
||
noBaseModel: '请先选择 Base Model',
|
||
dialogOk: '确定',
|
||
dialogCancel: '取消',
|
||
editModel: '编辑模型 (Edit)',
|
||
scanModelPrecisely: '精准扫描此模型',
|
||
unsupportedAutoApply: '不支持该类型模型的自动应用。',
|
||
createNodeFailed: '创建节点失败: ',
|
||
galleryLoading: '加载中...',
|
||
galleryErrorPrefix: '错误: ',
|
||
galleryDelete: '删除',
|
||
galleryDeleteConfirm: '彻底删除这张图片?',
|
||
galleryDeleteConfirmHint: '删除后无法恢复。',
|
||
galleryDeleting: '删除中...',
|
||
galleryDeleteFailed: '删除失败: ',
|
||
galleryNoMore: '没有更多图片了',
|
||
galleryScrollMore: '向下滚动加载更多',
|
||
galleryLoadFailed: '加载失败',
|
||
galleryEmpty: '图库为空',
|
||
galleryClose: '关闭图库',
|
||
galleryHistoryTitle: '历史生成图库: {name}',
|
||
galleryScanning: '加载中,正在扫描图片元数据...',
|
||
galleryNoModelImages: '没有找到使用此模型生成的历史图片。',
|
||
gallerySetCover: '设为封面',
|
||
gallerySetCoverConfirm: '确定将此图片设为封面吗?',
|
||
galleryCoverSuccess: '设置成功!',
|
||
gallerySelectingCoverPrefix: '正在为模型 ',
|
||
gallerySelectingCoverSuffix: ' 选择封面。请点击下方的图片。',
|
||
galleryLoadImagesError: '加载历史图片失败',
|
||
galleryCancel: '取消',
|
||
detailBackDoctor: '⬅ 返回医生面板',
|
||
detailBackAssistant: '⬅ 返回助手面板',
|
||
detailJumpToBottom: '跳到底部',
|
||
detailEdit: '⚙️ 编辑',
|
||
detailNotesTitle: '📓 专属备注 (Notes)',
|
||
detailEditNotes: '编辑备注',
|
||
detailGeneratedGallery: '🖼️ 查看历史生成作品',
|
||
detailTrainedWords: '训练词:',
|
||
detailDescription: '描述:',
|
||
detailNotes: '备注:',
|
||
detailNoCompatibleModels: '没有找到兼容模型。',
|
||
detailCompatibleLoadFailed: '加载失败。',
|
||
detailToggleSound: '开启/关闭声音',
|
||
detailNoCover: '暂无封面',
|
||
detailPickGallery: '从历史图库挑选',
|
||
detailUploadLocal: '从本地上传',
|
||
detailUploadError: '错误: ',
|
||
detailUploadFailed: '上传失败: ',
|
||
detailModelInfo: '编辑模型信息',
|
||
detailFile: '文件:',
|
||
detailCustomNamePlaceholder: '自定义名称 (留空则使用原名)',
|
||
detailNotesPlaceholder: '📓 专属备注... (支持多行)',
|
||
detailPhysicalRename: '同步物理重命名',
|
||
detailPhysicalRenameDesc: '若不勾选则仅虚拟重命名,安全不破坏原文件。',
|
||
detailResetAll: '重置设置',
|
||
detailResetConfirm: '确定要重置该模型的所有自定义信息(名称、封面、备注)吗?',
|
||
detailResetCoverPreserved: '未找到可恢复的 C 站备份或原始封面。为避免丢失唯一图片,当前封面已保留;自定义名称和备注仍已重置。',
|
||
detailResetCoverFailed: '封面恢复未能完整完成,请检查文件权限或占用情况;自定义名称和备注仍已重置。',
|
||
detailResetFailed: '重置失败。',
|
||
detailCancel: '取消',
|
||
detailSaveChanges: '保存更改',
|
||
detailSaving: '保存中...',
|
||
detailSelectModels: '选择模型',
|
||
detailFolders: '目录列表',
|
||
detailSelectedItems: '已选 {count} 项',
|
||
detailSelectedItemsPrefix: '已选 ',
|
||
detailSelectedItemsSuffix: ' 项',
|
||
detailNothingSelected: '暂未选择',
|
||
detailLoadedModels: '已加载 {loaded} / {total} 个模型',
|
||
detailComputing: '计算中...',
|
||
detailSelectNoPreview: '选无预览图',
|
||
detailSelectNoDesc: '选无介绍',
|
||
detailSelectAll: '全选',
|
||
detailClear: '清空',
|
||
detailConfirm: '确定',
|
||
detailLoading: '加载中 (Loading)...',
|
||
detailAllLoaded: '✅ 已加载全部',
|
||
detailScrollMore: '滑动加载更多...',
|
||
detailNoModels: '没有找到模型。',
|
||
detailApiRestart: '❌ 请求后端 API 失败!\n\n你必须重启 ComfyUI 进程,刚写入后端的代码才能生效。',
|
||
doctorTitle: '全局体检中心',
|
||
doctorAutoScanOn: 'ComfyUI 启动时自动检测并替换缺失模型 [已开启]',
|
||
doctorAutoScanOff: 'ComfyUI 启动时自动检测并替换缺失模型 [默认关闭]',
|
||
doctorRefresh: '🔄 刷新缓存',
|
||
doctorRefreshTitle: '重新读取最新模型列表并清除报错',
|
||
doctorGraphUnavailable: '当前画布或节点不可用。',
|
||
doctorMissingChainInputs: '节点没有完整的 MODEL/CLIP 输入。',
|
||
doctorUnconnectedChainInputs: 'MODEL/CLIP 输入尚未全部连接。',
|
||
doctorMissingChainOutputs: '节点没有完整的 MODEL/CLIP 输出。',
|
||
doctorAmbiguousBranches: '检测到多个下游分支,请先整理或选择明确链路。',
|
||
doctorInvalidDownstream: '现有下游连线无效,无法安全改写。',
|
||
doctorUnsupportedInsertion: '当前节点不支持此插入方式。',
|
||
doctorCreateLoraFailed: '无法创建标准 LoRA Loader 节点。',
|
||
doctorLoraNotReady: 'LoRA 列表尚未就绪,请刷新 ComfyUI 模型列表后重试。',
|
||
assistantSelectNode: '请在画布中点击选中任意节点',
|
||
assistantNoModelParameter: '该节点没有受支持的模型参数',
|
||
assistantSelectedNode: '当前选中节点',
|
||
assistantQuickActions: '快捷操作',
|
||
assistantChangeWidget: '更换 {name}',
|
||
assistantChangeCurrent: '更换当前模型',
|
||
assistantVisualPicker: '{type} · 可视化选择',
|
||
assistantInsertBefore: '前方插入 LoRA',
|
||
assistantInsertAfter: '后方插入 LoRA',
|
||
assistantConnectInputs: '接入节点输入端',
|
||
assistantConnectOutputs: '接入节点输出端',
|
||
doctorTotal: '总模型',
|
||
doctorHealthy: '🟢 健康',
|
||
doctorMissing: '🔴 缺失',
|
||
doctorNoWorkflowModels: '当前工作流没有任何模型节点',
|
||
doctorAutoRedirected: '自动重定向',
|
||
doctorReady: '正常',
|
||
doctorMissingStatus: '丢失',
|
||
doctorCivitai: '🌐 C站',
|
||
doctorViewHash: '🔑 查看哈希',
|
||
doctorHashModalTitle: '模型哈希与溯源详情',
|
||
doctorWorkflowHash: '工作流注入哈希 (Provenance)',
|
||
doctorLocalHash: '本地当前哈希 (Local Model)',
|
||
doctorNoHashInWorkflow: '未包含(工作流导出时未注入哈希或处于未扫描状态)',
|
||
doctorNoLocalHash: '本地未扫描或文件丢失',
|
||
doctorCopied: '已复制哈希到剪贴板!',
|
||
doctorFileSize: '文件大小',
|
||
doctorDeepHashScan: '🔍 深度哈希扫描',
|
||
doctorScanStarting: '⏳ 正在启动扫描引擎...',
|
||
doctorScanning: '⏳ 扫描中 ({current}/{total}) {filename}',
|
||
doctorScanError: '❌ 扫描过程中发生错误: ',
|
||
doctorMatching: '⏳ 正在匹配并替换飘红节点...',
|
||
doctorDeepScanSummary: '共深度扫描了 {total} 个缺失信息的模型。',
|
||
doctorNoLocalMatch: '❌ 扫描结束,本地未匹配到模型。\n\n{summary}\n\n这说明模型可能真的不在您的硬盘里,或者您删除了原本记录着哈希的源文件。\n请点击卡片上的【🌐 C站】去云端下载。',
|
||
doctorScanSuccess: '✅ 深度扫描成功!已自动修复该节点!\n\n{summary}',
|
||
doctorPollError: '❌ 状态轮询出错: ',
|
||
doctorScanFailed: '❌ 扫描出错: ',
|
||
doctorManualReplace: '🔀 手动替换',
|
||
doctorOriginalPath: '原路径: {path}',
|
||
assistantPreviewFailed: '无法加载预览',
|
||
betaFeature: '测试功能',
|
||
assistantBetaNotice: '“参数笔记本”联动仍在测试。应用前请保存当前工作流;它会修改选中节点的参数,但会忽略种子等运行时变化值。“动作”页不属于测试范围。',
|
||
assistantHistoryTitle: '🖼️ 历史生成图 ({count})',
|
||
assistantViewAll: '查看全部 →',
|
||
assistantRestoreWorkflow: '点击恢复此工作流',
|
||
assistantViewGallery: '点击查看完整图库',
|
||
pickerNoCompatible: '没有可供选择的兼容模型。',
|
||
pickerEyebrow: '节点助手 · 模型选择器',
|
||
pickerInsertBeforeTitle: '⬅ 在节点前方插入 LoRA',
|
||
pickerInsertAfterTitle: '在节点后方插入 LoRA ➡',
|
||
pickerChangeTitle: '🔀 更换当前模型',
|
||
pickerFolders: '📁 文件夹',
|
||
pickerSearch: '🔍 搜索名称或完整路径…',
|
||
pickerMainAll: '主模型:全部类型',
|
||
pickerNameAsc: '名称 A–Z',
|
||
pickerNameDesc: '名称 Z–A',
|
||
pickerByFolder: '按文件夹',
|
||
pickerLoadingCovers: '⏳ 正在加载模型封面…',
|
||
pickerCancel: '取消',
|
||
pickerInsertConfirm: '插入并自动连线',
|
||
pickerReplaceConfirm: '确认替换',
|
||
pickerCoversFailed: '⚠️ 封面加载失败,仍可按名称选择模型。',
|
||
doctorNodeLabel: '节点',
|
||
doctorAllHealthy: '🎉 太棒了!当前工作流中所有模型均在本地就绪。',
|
||
doctorLoadingPreview: '加载预览...',
|
||
doctorNoPreview: '暂无预览图',
|
||
doctorProfile: '📖 查看档案',
|
||
doctorBase: '基础模型',
|
||
doctorTriggerWords: '触发词',
|
||
doctorClickCopy: '点击复制',
|
||
doctorCopyAll: '📋 全部复制',
|
||
doctorNotes: '📝 我的备注',
|
||
pickerSelected: '已选择: {path}',
|
||
pickerChooseModel: '请选择一个模型。节点连接和强度不会被改动。',
|
||
pickerCompatibleMain: '✨ 已根据主模型 {name} 自动筛选兼容 LoRA;可在上方切换为全部类型。',
|
||
pickerCompatibleTag: '✨ 未找到已连接主模型,已根据当前 LoRA 的 {name} 标注筛选。',
|
||
pickerCompatibleNoTags: 'ℹ 已识别主模型 {name},但没有同类 LoRA 标注,因此暂时显示全部。',
|
||
pickerCompatibleUnknown: 'ℹ 未识别到主模型类型,暂时显示全部 LoRA;你仍可手动按基础模型筛选。',
|
||
pickerAllModels: '全部模型',
|
||
pickerResults: '{count} 个结果',
|
||
pickerCurrent: '当前',
|
||
pickerBaseModel: '基础模型',
|
||
pickerRoot: '根目录',
|
||
pickerNoMatches: '没有符合条件的模型。',
|
||
pickerOperationFailed: '操作失败:',
|
||
notebookSelectMain: '请先选择一个主模型。',
|
||
mainPreflightTitle: '📥 导入工作流 (预检海关)',
|
||
mainPreflightDesc: '请在此处粘贴工作流的 JSON 代码(未来将支持分享码)。我们将为您提取并校验所有模型依赖。',
|
||
mainCancel: '取消',
|
||
mainAnalyzePreflight: '🔍 解析并预检',
|
||
mainForceLoad: '🚀 强制载入画布',
|
||
mainNoDependencies: '✅ 未检测到任何模型依赖。',
|
||
mainDetectedModels: '扫描到 {count} 个模型资源:',
|
||
mainDownloadCivitai: '去 C站下载',
|
||
mainReady: '已就绪',
|
||
mainInvalidJson: '无效的 JSON!',
|
||
mainOpenTitle: '打开 Anomalous 模型浏览器',
|
||
mainRetryInit: '插件界面初始化失败,点击可重试',
|
||
mainRetryInitEn: 'The plugin UI failed to initialize. Click to retry.',
|
||
mainExportTitle: '📦 导出工作流分享码',
|
||
mainSkeletonOption: '精简版 (推荐 B站评论区, 体积小, 丢失坐标)',
|
||
mainFullOption: '完整版 (保留所有坐标与颜色, 较长)',
|
||
mainGenerate: '生成分享码',
|
||
mainCopyClipboard: '复制到剪贴板',
|
||
mainClose: '关闭',
|
||
mainCopied: '✅ 复制成功!',
|
||
mainImportTitle: '📥 导入工作流分享码',
|
||
mainSharePlaceholder: '粘贴 AMB0- 或 AMB1- 开头的分享码...',
|
||
mainImportLoad: '导入并加载',
|
||
mainShareEmpty: '❌ 分享码为空',
|
||
mainImportedNodes: '✅ 成功导入 {count} 个节点配置',
|
||
mainDecodeFailed: '❌ 解析失败: ',
|
||
mainUnifiedTitle: '🔄 工作流分享与导入',
|
||
mainExportWorkflow: '📤 导出当前工作流为分享码',
|
||
mainImportWorkflow: '📥 从分享码导入工作流',
|
||
sidebarToggle: '收起/展开侧边栏',
|
||
sidebarDoctor: '模型医生',
|
||
sidebarAssistant: '节点助手',
|
||
sidebarPreflight: '📥 预检导入工作流',
|
||
sidebarSettings: '设置中心',
|
||
sidebarScanWizard: '🔄 扫描向导 (Scan Wizard)',
|
||
sidebarScanComplete: '✅ 扫描/重命名已完成!数据已为您更新。',
|
||
sidebarScanWizardTitle: '扫描向导',
|
||
sidebarGlobalScanWizard: '全局扫描向导',
|
||
sidebarSingleModelScan: '🎯 单模型扫描向导: {files}',
|
||
sidebarGlobalWizardTitle: '全局扫描向导',
|
||
sidebarApiKey: 'API 密钥',
|
||
sidebarApiKeyPrompt: '请输入 Civitai API Key(留空将清除):',
|
||
sidebarKeySaved: '✅ 密钥保存成功',
|
||
sidebarSaveFailed: '❌ 保存失败: ',
|
||
sidebarStep0: 'Step 0. 扫描目标',
|
||
sidebarOpenSelector: '📂 打开高级模型选择面板',
|
||
sidebarSelectedZero: '已选择 0 个模型',
|
||
sidebarSelectedCount: '已选择 {count} 个模型',
|
||
sidebarTargetGlobal: '默认全局扫描',
|
||
sidebarTargetGlobalDesc: '扫描系统中所有的模型文件,自动匹配封面和信息',
|
||
sidebarTargetCustom: '高级自定义多选',
|
||
sidebarTargetCustomDesc: '跨目录选择特定模型,启动按序队列扫描',
|
||
sidebarStep1: 'Step 1. 获取数据',
|
||
sidebarOnline: '在线完整匹配',
|
||
sidebarOnlineDesc: '自动连接 Civitai 平台,深度获取模型封面图、触发词 (Trigger Words)、作者备注及详细标签。推荐日常使用。',
|
||
sidebarOffline: '离线极速读取',
|
||
sidebarOfflineDesc: '不消耗任何网络。仅通过本地张量计算极速提取模型内的基础元数据,速度极快但信息较基础。',
|
||
sidebarStep2: 'Step 2. 规范命名',
|
||
sidebarNormalize: '自动规范命名',
|
||
sidebarNormalizeDesc: '强迫症福音。自动将杂乱无章的模型文件名重命名为 <b>模型名_版本名.safetensors</b> 的标准格式。<br><span style="color:#8AB4F8; display:inline-block; margin-top:4px;">例如:</span> <span style="color:#ff6b6b; text-decoration:line-through;">model_final(1).safetensors</span> ➔ <span style="color:#28a745;">Beautiful_Mix_V1.0.safetensors</span>',
|
||
sidebarVirtualRename: '虚拟重命名 (安全推荐)',
|
||
sidebarVirtualRenameDesc: '仅将标准名称注入浏览器插件中,不修改硬盘上的真实文件名,随时可无损还原。',
|
||
sidebarPhysicalRename: '物理重命名',
|
||
sidebarPhysicalRenameDesc: '真实修改底层的 <code>.safetensors</code> 及其所有附属文件名,彻底告别乱码文件名。',
|
||
sidebarStep3: 'Step 3. 工作流保障与修复',
|
||
sidebarProvenance: '模型溯源绑定',
|
||
sidebarProvenanceDesc: '全局生效。每次生成图片或保存工作流时,将模型的精确哈希值隐式写入到图像元数据与工作流 JSON 中,防止未来模型改名或换环境后报错找不到。',
|
||
sidebarOverwrite: '强制覆盖已有配置',
|
||
sidebarOverwriteDesc: '扫描时忽略本地已存在的 .info 文件,强制重新计算哈希并覆盖下载。用于修复匹配错乱的模型。',
|
||
sidebarSmartFix: '智能修复当前工作流',
|
||
sidebarSmartFixDesc: '扫描完成后,自动尝试用最新数据修复当前画布中提示缺失的报错模型节点。',
|
||
sidebarNoModelsSelected: '未选择任何模型',
|
||
sidebarScanFailed: '扫描失败: ',
|
||
sidebarCancel: '取消',
|
||
sidebarExecute: '执行扫描',
|
||
sidebarSwitchToEnglish: '🌐 Language: EN',
|
||
sidebarSwitchToChinese: '🌐 语言: 中文',
|
||
sidebarImportExport: '📥 导入 / 导出工作流 (分享码)',
|
||
sidebarGlobalQuickScan: '🌍 一键全盘极速扫描 (不下载封面/不改名)',
|
||
sidebarGlobalQuickScanShort: '🌍 一键全盘扫描 (不下载封面/不改名)',
|
||
sidebarGlobalQuickConfirm: '即将执行极速全盘扫描并同步Hash,此操作不改名也不下载封面,是否继续?',
|
||
sidebarScanning: '⏳ 扫描中...',
|
||
sidebarGlobalStarted: '🚀 全局扫描已后台启动!',
|
||
sidebarScanDone: '✅ 扫描完成',
|
||
sidebarError: '错误: ',
|
||
sidebarLocalScanOn: '☑ 开启非C站模型本地扫描 (读取内置参数) [已开启]',
|
||
sidebarLocalScanOff: '☐ 开启非C站模型本地扫描 (读取内置参数) [已关闭]',
|
||
sidebarLocalScanOnEn: '☑ Local metadata scan for non-Civitai [ON]',
|
||
sidebarLocalScanOffEn: '☐ Local metadata scan for non-Civitai [OFF]',
|
||
sidebarCheckMissing: '🔍 检查并极速录入缺失模型信息',
|
||
sidebarChecking: '⏳ 检查中...',
|
||
sidebarMissingScanning: '⚠️ 发现缺失,正在自动极速扫描...',
|
||
sidebarInfoComplete: '✅ 补全完成',
|
||
sidebarAllInfoComplete: '✨ 所有模型信息已完整',
|
||
sidebarUiScale: 'UI 缩放',
|
||
sidebarResetLayout: '🔄 重置界面布局',
|
||
sidebarResetConfirm: '确认重置窗口位置、缩放和停靠状态吗?',
|
||
sidebarInjectHash: '🟢 注入工作流哈希',
|
||
sidebarSkipHash: '⚪ 不注入工作流哈希',
|
||
sidebarManageFolders: '📁 文件夹管理',
|
||
sidebarFeedback: '💬 提交反馈 / 报告问题',
|
||
sidebarModelSettings: '🖼️ 模型设置',
|
||
sidebarModelCardSettings: '模型卡片设置',
|
||
sidebarModelCardDescription: '只调整模型浏览器里的卡片显示,不会修改模型文件或原始封面。',
|
||
sidebarVideoPlayback: '视频封面播放',
|
||
sidebarVideoHelp: '始终播放更有动感;悬停播放更省显存与电量。',
|
||
sidebarAlwaysPlay: '始终播放',
|
||
sidebarHoverPlay: '悬停播放(推荐)',
|
||
sidebarCardQuality: '卡片图片清晰度',
|
||
sidebarCardQualityHelp: '流畅缩略图只用于卡片;打开详情仍显示原始封面。',
|
||
sidebarOptimizedThumbnail: '流畅缩略图(推荐)',
|
||
sidebarOriginalCover: '原始封面(更占资源)',
|
||
sidebarModelSettingsNote: '缩略图由插件自动缓存和回收;视频离开视野或关闭浏览器后会自动释放。',
|
||
sidebarDone: '完成',
|
||
sidebarModuleNotLoaded: '模块尚未加载,请稍等或刷新页面!',
|
||
sidebarExpandAll: '➕ 展开全部',
|
||
sidebarCollapseAll: '➖ 收起全部',
|
||
sidebarSearchModels: '🔍 搜索模型...',
|
||
sidebarFolderManagerTitle: '📁 侧边栏文件夹管理',
|
||
sidebarFolderManagerDesc: '上下拖拽调整侧边栏的显示顺序。点击眼睛图标可隐藏不需要显示的底层文件夹。隐藏的文件夹不会被扫描,完全不占用性能。',
|
||
sidebarCategoryMode: '分类模式 (ComfyUI)',
|
||
sidebarPhysicalMode: '物理模式 (本地文件夹)',
|
||
sidebarFolderLoadFailed: '加载文件夹类型失败。',
|
||
sidebarFolderModeError: '切换模式失败',
|
||
sidebarVisible: '可见',
|
||
sidebarHidden: '隐藏',
|
||
sidebarSaveReload: '保存并刷新',
|
||
sidebarSaveConfigError: '保存配置失败: ',
|
||
hashResolverFixed: '🪄 Anomalous 成功修复了 {count} 个缺失的模型!\n\n💡 提示:ComfyUI V1 对报错的缓存极深。请务必手动点击侧边栏【工作流总览】中的【刷新】按钮,或者直接按 F5 刷新浏览器,否则切换工作流时节点可能会再次变红。',
|
||
closeHelp: '关闭说明',
|
||
delSure: '⚠️ 确定吗?',
|
||
dockTitle: '侧边停靠',
|
||
replaceAll: '全部替换',
|
||
editRaw: '📝 纯文本/粘贴',
|
||
findPlaceholder: '查找...',
|
||
replacePlaceholder: '替换为...',
|
||
models: '模型',
|
||
gallery: '图库',
|
||
apiKeyConfig: '🔑 Civitai API 密钥配置 (用于下载封面)',
|
||
apiKeyPrompt: '请输入你的 Civitai API Key:',
|
||
settingsBtn: '设置',
|
||
closeSettings: '✖ 关闭设置面板',
|
||
doctorBtn: '节点助手',
|
||
importBtn: '📥 导入 / 导出工作流 (分享码)',
|
||
recipeTitle: '工作流配方',
|
||
recipeBetaNotice: '工作流配方仍在测试。更新插件以及导入、恢复、删除或应用参数前,请保存当前画布并备份用户 workflows 目录中的 anomalous_recipes 与 anomalous_parameters。',
|
||
recipeClose: '关闭工作流配方',
|
||
recipeSaveCurrent: '保存当前工作流',
|
||
recipeSaveTitle: '保存为工作流配方',
|
||
recipeName: '名称',
|
||
recipeDefaultName: '新工作流配方',
|
||
recipeNameRequired: '请填写配方名称。',
|
||
recipeTags: '标签',
|
||
recipeTagsHint: '例如:人像, SDXL, 放大',
|
||
recipeNotes: '备注',
|
||
recipeNotesHint: '记录这个版本为什么好用……',
|
||
recipeThumbnail: '工作流缩略图',
|
||
recipeCancel: '取消',
|
||
recipeSave: '保存',
|
||
recipeSaving: '正在保存…',
|
||
recipeSaveReceipt: '已保存:{nodes} 个节点,{links} 条连线,{groups} 个分组。',
|
||
recipeSaveReceiptMismatch: '已保存,但完整性回执与当前画布不一致;请重新打开配方核对。',
|
||
recipeEmpty: '还没有工作流配方。保存一个已经跑通的工作流吧。',
|
||
recipeLoadError: '无法加载工作流配方。',
|
||
recipeUntitled: '未命名配方',
|
||
recipeSearchPlaceholder: '搜索名称、笔记或标签…',
|
||
recipeClearFilters: '清除筛选',
|
||
recipeDialogNo: '否',
|
||
recipeNoTags: '暂无标签',
|
||
recipeNoMatches: '没有匹配的配方。请清除搜索或标签筛选。',
|
||
recipeFilterByTag: '按此标签筛选',
|
||
recipeImport: '导入配方包',
|
||
recipeExport: '导出配方包',
|
||
recipeExportError: '导出工作流配方包失败。',
|
||
recipeImportError: '导入工作流配方包失败。',
|
||
recipeExportSnapshotsConfirm: '导出时包含模型预览快照吗?\n\n快照是展示数据,不包含模型文件;视频封面只保留轻量静态快照,不会打包原视频。',
|
||
recipeExportHistoryConfirm: '导出时包含历史版本吗?\n\n历史可能包含旧提示词和备注。',
|
||
recipeExportRedactIdentityConfirm: '是否移除模型 SHA-256、大小和来源信息?\n\n点击“确定”将移除这些身份信息。',
|
||
recipeImportSummary: '配方包检查完成。确认导入以下内容吗?',
|
||
recipeImportAssets: '预览资产',
|
||
recipeImportHistory: '历史版本',
|
||
recipeImportRenamePrompt: '配方名称已存在,请输入导入后的名称:',
|
||
recipeModel: '模型',
|
||
recipeLoras: 'LoRA',
|
||
recipePrompt: '正向提示词',
|
||
recipeSteps: '步数',
|
||
recipeRestore: '恢复版本',
|
||
recipeAppendCanvas: '追加到画布',
|
||
recipeAppendError: '无法追加此配方到当前画布。',
|
||
recipeDelete: '删除',
|
||
recipeDeleteConfirm: '确定删除这个工作流配方吗?',
|
||
recipeDeleteError: '删除工作流配方失败。',
|
||
recipeSaveError: '保存工作流配方失败。',
|
||
recipeNodeParams: '节点参数',
|
||
recipeUnknownNode: '未知节点',
|
||
recipeCopyParameter: '复制参数值',
|
||
recipeCopied: '已复制',
|
||
recipeCopyFailed: '复制失败',
|
||
recipeAdvancedInfo: '高级信息',
|
||
recipeInlineEditName: '点击修改名称',
|
||
recipeInlineEditNotes: '点击修改备注',
|
||
recipeInlineEditTags: '编辑标签',
|
||
recipeInlineSave: '保存',
|
||
recipeInlineCancel: '取消',
|
||
recipeInlineSaving: '保存中…',
|
||
recipeInlineError: '保存失败,请重试。',
|
||
recipeInlineNameRequired: '名称不能为空。',
|
||
recipeSomeParamsInWorkflow: '其余复杂或敏感参数仍保存在完整工作流中。',
|
||
recipeMoreNodesInWorkflow: '其余节点仍保存在完整工作流中。',
|
||
recipeMissingNodes: '当前缺少以下节点类型,恢复后可能无法运行',
|
||
recipeBindImage: '绑定封面图片',
|
||
recipeNoImage: '不绑定图片',
|
||
recipeCanvasPreview: '当前画布',
|
||
recipeLoadingRecentImages: '正在读取最近生成结果…',
|
||
recipeRecentImages: '最近生成结果',
|
||
recipeRecentImagesUnavailable: '暂时无法读取最近生成结果。',
|
||
recipeChoosePinnedParams: '选择关键参数',
|
||
recipePinnedParams: '关键参数',
|
||
recipeKeepImage: '保留当前封面',
|
||
recipeEdit: '编辑',
|
||
recipeEditTitle: '编辑工作流配方',
|
||
recipeEditNodeParams: '编辑节点参数',
|
||
recipeComplexParam: '复杂值仅展示;完整值仍安全保存在工作流中。',
|
||
recipeHistory: '版本历史',
|
||
recipeHistoryEmpty: '还没有历史版本。更新配方后会自动保留旧版本。',
|
||
recipeUnknownVersion: '未知时间',
|
||
recipeRestoreVersion: '恢复此版本',
|
||
recipeRestoreVersionConfirm: '恢复此版本会覆盖当前配方,但当前内容会先自动存入历史。继续吗?',
|
||
recipeEditCanvas: '载入画布编辑',
|
||
recipeEditCanvasConfirm: '载入会替换当前画布。完成结构编辑后,点击“更新当前配方”即可保存为新版本。继续吗?',
|
||
recipeUpdate: '保存更新',
|
||
recipeUpdateCurrent: '更新当前配方',
|
||
recipeUpdateError: '更新工作流配方失败。',
|
||
recipeViewDetails: '查看详情',
|
||
recipeDetailBack: '返回配方列表',
|
||
recipeDetailOverview: '概览',
|
||
recipeGallery: '图库',
|
||
recipeGalleryLoading: '正在查找匹配的历史出图…',
|
||
recipeGalleryEmpty: '未在最近 200 张含工作流数据的 PNG 中找到与此配方结构匹配的出图。',
|
||
recipeGalleryRefresh: '刷新匹配结果',
|
||
recipeGallerySetCover: '设为配方封面',
|
||
recipeGalleryCoverSaved: '已设为配方封面',
|
||
recipeGalleryCoverError: '无法设置配方封面。',
|
||
recipeGalleryLoadError: '无法读取配方图库。',
|
||
recipeGalleryScanHint: '已检查最近 {count} 张含工作流数据的 PNG。',
|
||
recipeGalleryOpenImage: '查看原图',
|
||
recipeGalleryCompare: '参数对比',
|
||
recipeGalleryComparison: '配方与出图参数',
|
||
recipeGalleryComparisonLoading: '正在读取这张图片的参数…',
|
||
recipeGalleryComparisonError: '无法读取这张图片的参数。',
|
||
recipeGalleryNoDifferences: '没有发现可显示的参数差异。',
|
||
recipeGalleryDifferenceHint: '以下是节点参数的差异;图库匹配本身只关注节点类型。',
|
||
recipeGalleryRecipeValue: '配方',
|
||
recipeGalleryImageValue: '图片',
|
||
recipeDetailModels: '模型与复现',
|
||
recipeDetailParameters: '参数笔记本',
|
||
recipeDetailParametersHint: '这里展示配方保存的完整参数;长文本可展开并复制。参数图库只匹配相同参数,不会因为本地路径不同而失效。',
|
||
recipeParameterSnapshots: '参数快照',
|
||
recipeParameterSnapshotsHint: '每次保存配方都会留下一个只读版本。',
|
||
recipeParameterShowing: '当前显示的参数笔记',
|
||
recipeParameterCurrentRecipe: '当前配方参数',
|
||
recipeParameterActive: '当前',
|
||
recipeParameterRefresh: '刷新快照',
|
||
recipeParameterLoading: '正在读取参数快照…',
|
||
recipeParameterLoadError: '无法读取参数快照。',
|
||
recipeParameterNoSnapshots: '这个配方还没有参数快照。',
|
||
recipeParameterUntitled: '未命名参数快照',
|
||
recipeParameterDelete: '删除参数笔记',
|
||
recipeParameterDeleteConfirm: '确定删除参数笔记“{name}”吗?此操作无法撤销。',
|
||
recipeParameterDeleteError: '无法删除参数笔记,请稍后重试。',
|
||
recipeParameterNew: '新建参数笔记',
|
||
recipeParameterReadCurrent: '读取当前并新建',
|
||
recipeParameterReadCurrentSaving: '正在读取并保存…',
|
||
recipeParameterReadCurrentError: '无法读取当前画布参数。',
|
||
recipeParameterSkeletonMismatch: '当前画布缺少配方骨架节点,未执行任何修改。',
|
||
recipeParameterWidgetMismatch: '当前画布的节点控件与参数笔记不一致:',
|
||
recipeParameterNodeUnavailable: '无法在当前画布中定位匹配节点:',
|
||
recipeParameterApply: '应用到当前工作流',
|
||
recipeParameterApplying: '正在检查骨架并应用…',
|
||
recipeParameterApplied: '已应用 {count} 项参数',
|
||
recipeParameterApplyError: '应用参数失败,当前画布未完成修改。',
|
||
recipeParameterNewHint: '基于当前配方骨架编辑节点参数;种子等运行时变化值会被忽略。保存后会生成新的只读快照,不会覆盖历史记录。',
|
||
recipeParameterName: '笔记名称',
|
||
recipeParameterSave: '保存参数笔记',
|
||
recipeParameterCancel: '取消编辑',
|
||
recipeParameterSaveError: '参数笔记保存失败。',
|
||
recipeParameterSensitiveHidden: '敏感控件已隐藏',
|
||
recipeDetailParameterSummary: '常用参数',
|
||
recipeDetailNodeParameters: '节点参数',
|
||
recipeDetailUnknownNode: '未命名节点',
|
||
recipeDetailWidget: '控件',
|
||
recipeDetailScheduler: '调度器',
|
||
recipeDetailSteps: '步数',
|
||
recipeDetailCFG: 'CFG',
|
||
recipeDetailDenoise: '降噪',
|
||
recipeDetailSeed: '种子',
|
||
recipeParameterGallery: '相同参数的出图',
|
||
recipeParameterGalleryLoading: '正在查找相同参数的历史出图…',
|
||
recipeParameterGalleryEmpty: '没有找到参数完全一致的历史出图。',
|
||
recipeParameterGalleryError: '无法读取参数图库。',
|
||
recipeDetailNoSavedParameters: '此配方没有可展示的参数。',
|
||
recipeDetailVersions: '版本',
|
||
recipeDetailSummary: '摘要',
|
||
recipeDetailModelComposition: '模型组成',
|
||
recipeDetailBaseModel: '主模型',
|
||
recipeDetailIdentity: '已验证身份',
|
||
recipeDetailUnverified: '未验证模型',
|
||
recipeDetailMissingNodes: '缺失节点类型',
|
||
recipeDetailFingerprint: '工作流指纹',
|
||
recipeDetailNotIndexed: '尚未索引',
|
||
recipeDetailLoraSummary: 'LoRA',
|
||
recipeDetailSampler: '采样器',
|
||
recipeDetailResolution: '分辨率',
|
||
recipeDetailUnavailable: '不可用',
|
||
recipeDetailEditOrigin: '✏️ 编辑来源',
|
||
recipeOriginDialogTitle: '编辑模型来源信息',
|
||
recipeOriginOfficialName: '官方模型名称',
|
||
recipeOriginModelUrl: '官方网址 (Model URL)',
|
||
recipeOriginFetchHash: '🌍 通过 Hash 自动获取',
|
||
recipeOriginFetching: '获取中...',
|
||
recipeOriginFetchFailed: '未找到或网络异常',
|
||
recipeOriginFetchSuccess: '已成功获取!',
|
||
recipeDetailNoNotes: '没有备注。',
|
||
recipeDetailUpdated: '更新时间',
|
||
recipeDetailCopyPrompt: '复制提示词',
|
||
recipeDetailCopyFingerprint: '复制工作流指纹',
|
||
recipeDetailCopyHash: '复制完整哈希',
|
||
recipeDetailPrompts: '提示词',
|
||
recipeDetailPositivePrompt: '正向提示词',
|
||
recipeDetailNegativePrompt: '负面提示词',
|
||
recipeDetailNoPrompts: '此配方没有可安全展示的提示词摘要。',
|
||
recipePromptSupportNotice: '当前仅自动识别 ComfyUI 原生 CLIPTextEncode 与已知官方连接;第三方文本节点请手动标注。',
|
||
recipePromptRoleChoose: '选择提示词角色',
|
||
recipePromptRoleAutomatic: '自动识别',
|
||
recipePromptRoleManual: '用户手动标注',
|
||
recipePromptRolePositive: '正面提示词',
|
||
recipePromptRoleNegative: '负面提示词',
|
||
recipePromptRoleBoth: '正负共用',
|
||
recipePromptRoleIgnored: '忽略',
|
||
recipePromptRoleUnknown: '角色未确定',
|
||
recipePromptRoleSaveError: '无法保存提示词角色,请稍后重试。',
|
||
recipeDetailVolatileIgnored: '运行时变化,已忽略',
|
||
recipeDetailExpandValue: '展开完整内容',
|
||
recipeDetailCollapseValue: '收起内容',
|
||
recipeIdentityVerified: '身份已核验',
|
||
recipeIdentityUnverified: '本地可用,未核验',
|
||
recipeIdentityUnavailable: '本机未找到',
|
||
recipeIdentityHelpDesc: '核验的是物理文件是否一致,不代表判断模型画质或可用性。',
|
||
recipeDetailRefreshAvailability: '检查本机可用性',
|
||
recipeDetailRefreshOrigin: '刷新来源信息',
|
||
recipeDetailRefreshOriginDesc: '刷新当前配方中的所有模型来源信息(支持补充旧配方数据)',
|
||
recipeDetailRefreshing: '检查中…',
|
||
recipeDetailRefreshError: '检查本机可用性失败',
|
||
recipeDetailAvailable: '本机可用',
|
||
recipeDetailMissing: '本机缺失',
|
||
recipeDetailAvailabilityNotChecked: '尚未检查本机',
|
||
recipeDetailNoModelReferences: '没有识别到受支持的模型加载器。其他自定义控件保留在参数和完整工作流中。',
|
||
recipeDetailModel: '模型',
|
||
recipeModelPath: '模型路径',
|
||
recipeOpenLocalModel: '打开本地模型详情',
|
||
recipeMatchLocalModel: '匹配本地模型',
|
||
recipeMatchingLocalModel: '正在匹配本地模型…',
|
||
recipeMatchRecipeModels: '匹配配方模型',
|
||
recipeMatchRecipeModelsDesc: '根据模型哈希、文件大小和模型类别,在本地模型目录中查找对应文件;不会使用原作者路径。',
|
||
recipeMatchingRecipeModels: '正在匹配配方模型…',
|
||
recipeRecipeMatchSummary: '已找到 {found}/{total} 个本地匹配',
|
||
recipeAllModelsMatched: '配方中的模型都已匹配或无需匹配',
|
||
recipeApplyLocalMatch: '应用此匹配',
|
||
recipeApplyLocalMatchDesc: '将匹配到的本地模型路径写入配方工作流',
|
||
recipeApplyingLocalMatch: '正在应用匹配…',
|
||
recipeApplyLocalMatchSuccess: '已应用本地模型匹配',
|
||
recipeApplyLocalMatchError: '无法应用此模型匹配',
|
||
recipeLocalModelNotFound: '暂未找到匹配的本地模型。',
|
||
recipeLocalModelAmbiguous: '找到多个候选,请先补充模型身份信息。',
|
||
recipeLocalModelMatchError: '匹配失败,请稍后重试。',
|
||
recipeDetailSearchParameters: '按节点、类型或控件名称搜索…',
|
||
recipeDetailNoParameters: '没有匹配的安全参数。',
|
||
recipeDetailCurrentVersion: '当前版本',
|
||
recipeCompareVersion: '对比此版本',
|
||
recipeDiffLoading: '正在比较…',
|
||
recipeDiffSummary: '变更摘要',
|
||
recipeDiffBefore: '之前',
|
||
recipeDiffAfter: '之后',
|
||
recipeDiffNoChanges: '两个版本没有检测到有意义的变更。',
|
||
recipeDiffError: '无法读取此历史版本。',
|
||
recipeDiffPinned: '钉选参数',
|
||
recipeDiffPrompts: '提示词',
|
||
recipeDiffModels: '模型引用',
|
||
recipeDiffParameters: '参数摘要',
|
||
recipeDiffWorkflow: '工作流结构',
|
||
recipeDiffPresentation: '展示信息',
|
||
recipeDiffOther: '其他',
|
||
recipeDetailUnknownTime: '未知时间',
|
||
recipeDetailLoadingPreviews: '正在加载本机模型预览…',
|
||
recipeDetailCurrentPreview: '当前本机预览',
|
||
recipeDetailNoPreview: '暂无预览',
|
||
recipeDetailSavedSnapshot: '已保存快照',
|
||
recipeParameterNotebooks: 'RECIPE PARAMETER NOTEBOOKS',
|
||
recipeParameterRename: '重命名',
|
||
recipeParameterRenamePrompt: '请输入参数笔记本的新名称:',
|
||
recipeParameterRenameError: '重命名参数笔记本失败',
|
||
assistantTabActions: '动作',
|
||
assistantTabPresets: '参数笔记本',
|
||
assistantRecipeGroup: '配方',
|
||
assistantDeletedRecipe: '已删除配方',
|
||
assistantUnboundRecipe: '全局无绑定',
|
||
assistantNotebook: '笔记本',
|
||
assistantApplyTo: '应用到',
|
||
assistantNoPresets: '该节点类型暂无参数预设。',
|
||
},
|
||
en: {
|
||
title: '📦 Anomalous Model Browser',
|
||
scan: '🔄 Scan folder and sync Civitai data',
|
||
scanTitle: 'Scan Folder',
|
||
scanConfirm: 'Notice:\nThe scan process will automatically compare with Civitai and rename your local files.\nStart scan?',
|
||
scanning: 'Scanning...',
|
||
scanBg: '🚀 Scan started in background!',
|
||
scanDone: 'Done',
|
||
scanCompleteMsg: '✅ Scan Complete!\n\n⚠️ Note: Please click [Refresh] to sync the model list since files were renamed.',
|
||
eco: '🔋 Eco Mode (Play video on hover)',
|
||
autoPlay: '🎬 AutoPlay Videos (High perf cost)',
|
||
togglePlayTitle: 'Toggle Play Mode',
|
||
clean: '🧹 Clean orphaned .info files',
|
||
cleanTitle: 'Clean Duplicate Info',
|
||
cleanConfirm: 'This will globally scan and delete all redundant .civitai.info files. Continue?',
|
||
cleaning: 'Cleaning',
|
||
cleanDone: '✅ Clean Complete! Deleted',
|
||
files: 'files.',
|
||
cleanFail: '❌ Failed: ',
|
||
cleanErr: '❌ Error: ',
|
||
folders: '📂 Folders',
|
||
collapseAll: '➖ Collapse All',
|
||
expandAll: '➕ Expand All',
|
||
noModels: 'No models found in this folder.',
|
||
noPreview: 'No preview available',
|
||
clickScan: 'Click Scan',
|
||
back: '⬅️ Back',
|
||
delModel: '🗑️ Delete',
|
||
delConfirm: 'Are you sure you want to permanently delete',
|
||
delConfirm2: ' and all its associated configs, previews, and cache files? This action is irreversible!',
|
||
delSuccess: '✅ Delete Complete!\n',
|
||
delNote: '\n\n⚠️ Note: Please restart ComfyUI, otherwise continuing to use it due to cache will cause errors.',
|
||
delFail: '❌ Delete Failed: ',
|
||
copyAll: '📋 Copy All',
|
||
copied: '✅ Copied!',
|
||
clickToCopy: 'Click to copy: ',
|
||
compatibleModels: '🔗 Compatible Models',
|
||
refresh: 'Refresh',
|
||
loading: 'Loading…',
|
||
loadingCompatible: 'Loading...',
|
||
backToPrev: '🔙 Back to prev',
|
||
applyToCanvas: '➕ Add Node',
|
||
applySuccess: '✅ Added to workflow',
|
||
help: 'Help',
|
||
helpTitle: '📖 User Manual',
|
||
helpContent: `
|
||
<div style="line-height: 1.6; font-size: 0.95em; color: #eee; padding: 10px;">
|
||
<h3 style="color:#00ffcc; margin-top:0;">📖 Step-by-Step Guide</h3>
|
||
<div style="margin:0 0 14px;padding:12px 14px;border:1px solid rgba(255,193,7,.55);border-radius:9px;background:rgba(255,193,7,.1);color:#ffe4a3;"><strong>🧪 Beta features and data protection</strong><br>Workflow Recipes and the Node Assistant's Parameter Presets integration are currently beta features; the Node Assistant's Actions tab is not part of this beta. Before updating the plugin, importing another person's recipe, restoring a version, deleting a recipe, or applying parameters, save the current canvas and back up the <code>workflows/anomalous_recipes</code> and <code>workflows/anomalous_parameters</code> folders in your ComfyUI user directory. Model preview snapshots do not contain model files and are not model backups.</div>
|
||
<p><strong>1. 🔄 Prerequisites (Scan Wizard)</strong><br>Location: The <strong>Scan (🔄)</strong> icon at the bottom left.<br>This is the most crucial step! Open the Scan Wizard and execute a scan. Keep your network connected. (API-KEY may be needed in Settings for NSFW Civitai models). Scanning activates all core features.</p>
|
||
<p><strong>2. 🩺 Fix Broken Nodes (Model Doctor)</strong><br>Location: The 2nd icon <strong>(Stethoscope 🩺)</strong> from the bottom left.<br>When importing a workflow/image exported by this plugin and nodes turn red, open the Model Doctor to intelligently identify and replace them with correct local paths.</p>
|
||
<p><strong>3. 🤖 Node actions and parameter presets (Node Assistant)</strong><br>Location: The 3rd icon <strong>(Robot 🤖)</strong> from the bottom left.<br>After selecting a canvas node, Actions can visually replace its model or insert a LoRA before/after a compatible MODEL + CLIP chain. Parameter Presets reads same-type node values saved by Workflow Recipes and groups them by recipe. Click one record to apply it to the selected node. For example, selecting a KSampler can load its sampler, scheduler, steps, CFG, and denoise values in one click; volatile values such as seeds are ignored.</p>
|
||
<p><strong>4. 🧰 Workflow Recipes and Parameter Notebooks</strong><br>Location: Open the <strong>Creative Workspace</strong> and switch to <strong>Workflow Recipes</strong>.<br>A recipe saves the complete workflow, cover, tags, notes, model references, and common parameters. It can be appended to the canvas or shared as an import/export package. Details include Overview, Parameter Notebook, Gallery, and Versions for local model matching, full parameter viewing/copying, output comparison, and version comparison/restoration. Parameter notes can capture fresh values from a matching live canvas or edit safe controls; Apply to Current Workflow writes only after the recipe skeleton matches. Third-party prompt nodes that cannot be classified reliably can be labelled manually.</p>
|
||
<p><strong>5. ⚙️ Settings Panel</strong><br>Location: The <strong>Gear (⚙️)</strong> icon at the bottom left.<br>Adjust language and UI scale. Open “Model Settings” to choose always-play or hover-play video covers and optimized thumbnails or original covers. Detail pages always retain original image quality.</p>
|
||
<p><strong>6. 📑 Top Navigation & Prompt Notes</strong><br>Location: Top-right tabs <strong>Models (📦)</strong>, <strong>Gallery (🖼️)</strong>, <strong>Creative Workspace (📑)</strong>, and <strong>Dock (◧)</strong>.<br>Open Prompt Notes in the Creative Workspace and click <strong>➕</strong>. Select a Base Model, Main Model, and LoRAs; use <strong>📝 Edit Raw/Paste</strong> for bilingual prompts, chunking, find/replace, and tag editing; then click <strong>🚀 Send to Canvas</strong> to assemble the nodes.</p>
|
||
<p><strong>7. 📁 Folder Manager</strong><br>Location: Inside the Settings (⚙️) panel, click <strong>📁 Manage Folders</strong>.<br>Use this to hide unneeded built-in folders. Hidden folders will be completely skipped by background scans and I/O reads, achieving true "zero performance cost". You can also drag and drop to reorder how folders appear in the sidebar.</p>
|
||
<p><strong>8. 📥 Workflow Export & Import (Share Code)</strong><br>Location: The <strong>Import/Export (📥)</strong> icon to the left of the Settings gear.<br>You can encode your current workflow into a single share code for easy sharing on social platforms. Others can simply copy this code and paste it here to instantly import the workflow. The system will also automatically pre-check if the required models exist locally.</p>
|
||
<p><strong>9. 💬 Submit Feedback / Report Bug</strong><br>Location: Inside the Settings (⚙️) panel, click <strong>💬 Submit Feedback / Report Bug</strong>.<br>If you encounter bugs or have feature requests, click this to go directly to our GitHub Issues page.</p>
|
||
</div>`,
|
||
notebooks: 'Notebooks',
|
||
notebookTitle: 'Notebook Manager',
|
||
workspace: 'Workspace',
|
||
workspaceTitle: 'Creative Workspace',
|
||
promptNotes: 'Prompt Notes',
|
||
createNotebook: 'New',
|
||
saveNotebook: '💾 Save',
|
||
deleteNotebook: '🗑️ Delete',
|
||
renameNotebook: '✏️ Rename',
|
||
baseModel: 'Base Model',
|
||
mainModel: 'Main Model',
|
||
sendToCanvas: '🚀 Send to Canvas',
|
||
translate: 'Translate',
|
||
newNotebookName: 'New Notebook Name',
|
||
noBaseModel: 'Select a Base Model first',
|
||
dialogOk: 'OK',
|
||
dialogCancel: 'Cancel',
|
||
editModel: 'Edit Model',
|
||
scanModelPrecisely: 'Scan This Model',
|
||
unsupportedAutoApply: 'Unsupported model type for auto-apply.',
|
||
createNodeFailed: 'Failed to create node: ',
|
||
galleryLoading: 'Loading...',
|
||
galleryErrorPrefix: 'Error: ',
|
||
galleryDelete: 'Delete',
|
||
galleryDeleteConfirm: 'Delete this image permanently?',
|
||
galleryDeleteConfirmHint: 'This cannot be undone.',
|
||
galleryDeleting: 'Deleting...',
|
||
galleryDeleteFailed: 'Delete failed: ',
|
||
galleryNoMore: 'No more images',
|
||
galleryScrollMore: 'Scroll down to load more',
|
||
galleryLoadFailed: 'Load failed',
|
||
galleryEmpty: 'Gallery is empty',
|
||
galleryClose: 'Close Gallery',
|
||
galleryHistoryTitle: 'Generated History: {name}',
|
||
galleryScanning: 'Loading, scanning metadata...',
|
||
galleryNoModelImages: 'No images found generated by this model.',
|
||
gallerySetCover: 'Set Cover',
|
||
gallerySetCoverConfirm: 'Set this image as the cover?',
|
||
galleryCoverSuccess: 'Cover set successfully!',
|
||
gallerySelectingCoverPrefix: 'Selecting cover for ',
|
||
gallerySelectingCoverSuffix: '. Click an image below.',
|
||
galleryLoadImagesError: 'Error loading images',
|
||
galleryCancel: 'Cancel',
|
||
detailBackDoctor: '⬅ Back to Doctor',
|
||
detailBackAssistant: '⬅ Back to Assistant',
|
||
detailJumpToBottom: 'Jump to bottom',
|
||
detailEdit: '⚙️ Edit',
|
||
detailNotesTitle: '📓 Custom Notes',
|
||
detailEditNotes: 'Edit Notes',
|
||
detailGeneratedGallery: '🖼️ View Generated Gallery',
|
||
detailTrainedWords: 'Trained Words:',
|
||
detailDescription: 'Description:',
|
||
detailNotes: 'Notes:',
|
||
detailNoCompatibleModels: 'No compatible models found.',
|
||
detailCompatibleLoadFailed: 'Failed to load.',
|
||
detailToggleSound: 'Toggle Sound',
|
||
detailNoCover: 'No Cover',
|
||
detailPickGallery: 'Pick from Gallery',
|
||
detailUploadLocal: 'Upload Local',
|
||
detailUploadError: 'Error: ',
|
||
detailUploadFailed: 'Upload failed: ',
|
||
detailModelInfo: 'Edit Model Info',
|
||
detailFile: 'File:',
|
||
detailCustomNamePlaceholder: 'Custom Name (Leave empty to use original)',
|
||
detailNotesPlaceholder: '📓 Custom Notes...',
|
||
detailPhysicalRename: 'Physical Rename on Disk',
|
||
detailPhysicalRenameDesc: 'Virtual rename only if unchecked. Safe for originals.',
|
||
detailResetAll: 'Reset All',
|
||
detailResetConfirm: 'Reset all custom info for this model?',
|
||
detailResetCoverPreserved: 'No recoverable Civitai backup or original cover was found. The current cover was kept to avoid losing the only image; the custom name and notes were still reset.',
|
||
detailResetCoverFailed: 'The cover restore could not be completed. Check file permissions or locks; the custom name and notes were still reset.',
|
||
detailResetFailed: 'Reset failed.',
|
||
detailCancel: 'Cancel',
|
||
detailSaveChanges: 'Save Changes',
|
||
detailSaving: 'Saving...',
|
||
detailSelectModels: 'Select Models',
|
||
detailFolders: 'Folders',
|
||
detailSelectedItems: 'Selected {count} items',
|
||
detailSelectedItemsPrefix: 'Selected ',
|
||
detailSelectedItemsSuffix: ' items',
|
||
detailNothingSelected: 'Nothing selected',
|
||
detailLoadedModels: 'Loaded {loaded} / {total} models',
|
||
detailComputing: 'Computing...',
|
||
detailSelectNoPreview: 'Select No Preview',
|
||
detailSelectNoDesc: 'Select No Desc',
|
||
detailSelectAll: 'Select All',
|
||
detailClear: 'Clear',
|
||
detailConfirm: 'Confirm',
|
||
detailLoading: 'Loading...',
|
||
detailAllLoaded: '✅ All models loaded',
|
||
detailScrollMore: 'Scroll for more...',
|
||
detailNoModels: 'No models found.',
|
||
detailApiRestart: '❌ Backend API request failed!\n\nYou must restart the ComfyUI process for the newly written backend code to take effect.',
|
||
doctorTitle: 'Global Health Center',
|
||
doctorAutoScanOn: 'Auto-Detect on ComfyUI Startup [ON]',
|
||
doctorAutoScanOff: 'Auto-Detect on ComfyUI Startup [OFF]',
|
||
doctorRefresh: '🔄 Refresh',
|
||
doctorRefreshTitle: 'Reload model list and clear errors',
|
||
doctorGraphUnavailable: 'The current graph or node is unavailable.',
|
||
doctorMissingChainInputs: 'The node does not expose both MODEL and CLIP inputs.',
|
||
doctorUnconnectedChainInputs: 'Both MODEL and CLIP inputs must already be connected.',
|
||
doctorMissingChainOutputs: 'The node does not expose both MODEL and CLIP outputs.',
|
||
doctorAmbiguousBranches: 'Multiple downstream branches were detected; choose an explicit chain first.',
|
||
doctorInvalidDownstream: 'An existing downstream link is invalid and cannot be safely changed.',
|
||
doctorUnsupportedInsertion: 'This insertion is not available for the selected node.',
|
||
doctorCreateLoraFailed: 'Unable to create a standard LoRA Loader node.',
|
||
doctorLoraNotReady: 'The LoRA list is not ready. Refresh ComfyUI model lists and try again.',
|
||
assistantSelectNode: 'select any node in the canvas',
|
||
assistantNoModelParameter: 'No supported model parameter on this node',
|
||
assistantSelectedNode: 'Selected node',
|
||
assistantQuickActions: 'Quick actions',
|
||
assistantChangeWidget: 'Change {name}',
|
||
assistantChangeCurrent: 'Change current model',
|
||
assistantVisualPicker: '{type} · Visual picker',
|
||
assistantInsertBefore: 'Insert LoRA before',
|
||
assistantInsertAfter: 'Insert LoRA after',
|
||
assistantConnectInputs: 'Connect to node inputs',
|
||
assistantConnectOutputs: 'Connect to node outputs',
|
||
doctorTotal: 'Total',
|
||
doctorHealthy: '🟢 Healthy',
|
||
doctorMissing: '🔴 Missing',
|
||
doctorNoWorkflowModels: 'No models found in this workflow',
|
||
doctorAutoRedirected: 'Auto-Redirected',
|
||
doctorReady: 'Ready',
|
||
doctorMissingStatus: 'Missing',
|
||
doctorCivitai: '🌐 Civitai',
|
||
doctorViewHash: '🔑 View Hash',
|
||
doctorHashModalTitle: 'Model Hash & Provenance Details',
|
||
doctorWorkflowHash: 'Workflow Embedded Hash (Provenance)',
|
||
doctorLocalHash: 'Local Model Hash (Local Disk)',
|
||
doctorNoHashInWorkflow: 'Not available (Uninjected or unscanned during export)',
|
||
doctorNoLocalHash: 'No local record (Unscanned or file missing)',
|
||
doctorCopied: 'Hash copied to clipboard!',
|
||
doctorFileSize: 'File Size',
|
||
doctorDeepHashScan: '🔍 Deep Hash Scan',
|
||
doctorScanStarting: '⏳ Starting scan engine...',
|
||
doctorScanning: '⏳ Scanning ({current}/{total}) {filename}',
|
||
doctorScanError: '❌ Scan error: ',
|
||
doctorMatching: '⏳ Matching and resolving red nodes...',
|
||
doctorDeepScanSummary: 'Deep scanned {total} models with missing info.',
|
||
doctorNoLocalMatch: '❌ Scan finished, but no local match found.\n\n{summary}\n\nThis means the model is truly missing from your disk, or the original source file with hash was deleted.\nPlease click [🌐 Civitai] to download it from the cloud.',
|
||
doctorScanSuccess: '✅ Deep Scan successful! Node auto-healed!\n\n{summary}',
|
||
doctorPollError: '❌ Poll Error: ',
|
||
doctorScanFailed: '❌ Scan Error: ',
|
||
doctorManualReplace: '🔀 Manual Replace',
|
||
doctorOriginalPath: 'Original: {path}',
|
||
assistantPreviewFailed: 'Failed to load preview',
|
||
betaFeature: 'Beta feature',
|
||
assistantBetaNotice: 'The Parameter Notebook integration is still in beta. Save the current workflow before applying a preset; it changes the selected node while ignoring volatile values such as seeds. The Actions tab is not part of this beta.',
|
||
assistantHistoryTitle: '🖼️ History ({count})',
|
||
assistantViewAll: 'View All →',
|
||
assistantRestoreWorkflow: 'Click to restore workflow',
|
||
assistantViewGallery: 'Click to view full gallery',
|
||
pickerNoCompatible: 'No compatible models are available.',
|
||
pickerEyebrow: 'Node Assistant · Model Picker',
|
||
pickerInsertBeforeTitle: '⬅ Insert LoRA Before Node',
|
||
pickerInsertAfterTitle: 'Insert LoRA After Node ➡',
|
||
pickerChangeTitle: '🔀 Change Current Model',
|
||
pickerFolders: '📁 Folders',
|
||
pickerSearch: '🔍 Search name or full path…',
|
||
pickerMainAll: 'Main model: All types',
|
||
pickerNameAsc: 'Name A–Z',
|
||
pickerNameDesc: 'Name Z–A',
|
||
pickerByFolder: 'By Folder',
|
||
pickerLoadingCovers: '⏳ Loading model covers…',
|
||
pickerCancel: 'Cancel',
|
||
pickerInsertConfirm: 'Insert & Auto-Connect',
|
||
pickerReplaceConfirm: 'Confirm Replacement',
|
||
pickerCoversFailed: '⚠️ Covers failed to load; models remain selectable by name.',
|
||
doctorNodeLabel: 'Node',
|
||
doctorAllHealthy: '🎉 Awesome! All models in this workflow are healthy.',
|
||
doctorLoadingPreview: 'Loading preview...',
|
||
doctorNoPreview: 'No preview',
|
||
doctorProfile: '📖 View Profile',
|
||
doctorBase: 'Base',
|
||
doctorTriggerWords: 'Trigger Words',
|
||
doctorClickCopy: 'Click to copy',
|
||
doctorCopyAll: '📋 Copy All',
|
||
doctorNotes: '📝 My Notes',
|
||
pickerSelected: 'Selected: {path}',
|
||
pickerChooseModel: 'Choose a model. Existing connections and strengths will be preserved.',
|
||
pickerCompatibleMain: '✨ Compatible LoRAs are filtered for the main model {name}. Use the filter above to show all types.',
|
||
pickerCompatibleTag: '✨ No connected main model was identified, so the current LoRA tag {name} is used.',
|
||
pickerCompatibleNoTags: 'ℹ Main model {name} was identified, but no matching LoRA tags were found, so all models remain visible.',
|
||
pickerCompatibleUnknown: 'ℹ The main model type could not be identified. All LoRAs remain visible and can be filtered manually.',
|
||
pickerAllModels: 'All Models',
|
||
pickerResults: '{count} results',
|
||
pickerCurrent: 'Current',
|
||
pickerBaseModel: 'Base model',
|
||
pickerRoot: 'Root',
|
||
pickerNoMatches: 'No models match the current filters.',
|
||
pickerOperationFailed: 'Operation failed: ',
|
||
notebookSelectMain: 'Please select a Main Model first.',
|
||
mainPreflightTitle: '📥 Pre-flight Import Workflow',
|
||
mainPreflightDesc: 'Paste the workflow JSON here. We will extract and validate all model dependencies before loading.',
|
||
mainCancel: 'Cancel',
|
||
mainAnalyzePreflight: '🔍 Analyze & Pre-flight',
|
||
mainForceLoad: '🚀 Force Load to Canvas',
|
||
mainNoDependencies: '✅ No model dependencies detected.',
|
||
mainDetectedModels: 'Detected {count} model resources:',
|
||
mainDownloadCivitai: 'Download',
|
||
mainReady: 'Ready',
|
||
mainInvalidJson: 'Invalid JSON!',
|
||
mainOpenTitle: 'Open Anomalous Model Browser',
|
||
mainRetryInit: '插件界面初始化失败,点击可重试',
|
||
mainRetryInitEn: 'The plugin UI failed to initialize. Click to retry.',
|
||
mainExportTitle: '📦 Export Workflow Share Code',
|
||
mainSkeletonOption: 'Skeleton (Compact, best for comments, loses coords)',
|
||
mainFullOption: 'Full (Keeps coords and colors, longer string)',
|
||
mainGenerate: 'Generate',
|
||
mainCopyClipboard: 'Copy',
|
||
mainClose: 'Close',
|
||
mainCopied: '✅ Copied successfully!',
|
||
mainImportTitle: '📥 Import Workflow Share Code',
|
||
mainSharePlaceholder: 'Paste AMB0- or AMB1- share code here...',
|
||
mainImportLoad: 'Import & Load',
|
||
mainShareEmpty: '❌ Share code is empty',
|
||
mainImportedNodes: '✅ Successfully imported {count} nodes',
|
||
mainDecodeFailed: '❌ Decode Failed: ',
|
||
mainUnifiedTitle: '🔄 Workflow Share & Import',
|
||
mainExportWorkflow: '📤 Export Workflow to Share Code',
|
||
mainImportWorkflow: '📥 Import Workflow from Share Code',
|
||
sidebarToggle: 'Toggle Sidebar',
|
||
sidebarDoctor: 'Model Doctor',
|
||
sidebarAssistant: 'Node Assistant',
|
||
sidebarPreflight: '📥 Preflight Import',
|
||
sidebarSettings: 'Settings Hub',
|
||
sidebarScanWizard: '🔄 Scan Wizard',
|
||
sidebarScanComplete: '✅ Scan/Rename completed! Data updated.',
|
||
sidebarScanWizardTitle: 'Scan Wizard',
|
||
sidebarGlobalScanWizard: 'Global Scan Wizard',
|
||
sidebarSingleModelScan: '🎯 Single Model Scan: {files}',
|
||
sidebarGlobalWizardTitle: 'Global Scan Wizard',
|
||
sidebarApiKey: 'API Key',
|
||
sidebarApiKeyPrompt: 'Enter Civitai API Key (leave blank to clear):',
|
||
sidebarKeySaved: '✅ Key Saved',
|
||
sidebarSaveFailed: '❌ Save failed: ',
|
||
sidebarStep0: 'Step 0. Scan Target',
|
||
sidebarOpenSelector: '📂 Open Advanced Model Selector',
|
||
sidebarSelectedZero: '0 models selected',
|
||
sidebarSelectedCount: '{count} models selected',
|
||
sidebarTargetGlobal: 'Default Global Scan',
|
||
sidebarTargetGlobalDesc: 'Scan all models in the system for covers and metadata',
|
||
sidebarTargetCustom: 'Advanced Selection',
|
||
sidebarTargetCustomDesc: 'Select specific models across folders, launches sequential scan',
|
||
sidebarStep1: 'Step 1. Fetch Data',
|
||
sidebarOnline: 'Online Full Matching',
|
||
sidebarOnlineDesc: 'Connects to Civitai to fetch comprehensive model covers, trigger words, author notes, and tags. Recommended for daily use.',
|
||
sidebarOffline: 'Offline Fast Read',
|
||
sidebarOfflineDesc: 'No network required. Extremely fast extraction of basic metadata via local tensor computation, but info is limited.',
|
||
sidebarStep2: 'Step 2. Normalize Naming',
|
||
sidebarNormalize: 'Auto-Normalize Naming',
|
||
sidebarNormalizeDesc: 'Automatically rename messy model files to the official standard format: <b>ModelName_VersionName.safetensors</b>.<br><span style="color:#8AB4F8; display:inline-block; margin-top:4px;">e.g. </span> <span style="color:#ff6b6b; text-decoration:line-through;">model_final(1).safetensors</span> ➔ <span style="color:#28a745;">Beautiful_Mix_V1.0.safetensors</span>',
|
||
sidebarVirtualRename: 'Virtual Rename (Safe)',
|
||
sidebarVirtualRenameDesc: 'Inject standard names into the browser only, without modifying actual files on disk. Safely reversible.',
|
||
sidebarPhysicalRename: 'Physical Rename',
|
||
sidebarPhysicalRenameDesc: 'Permanently rename the underlying <code>.safetensors</code> and associated files on disk.',
|
||
sidebarStep3: 'Step 3. Workflow Protection & Fix',
|
||
sidebarProvenance: 'Model Provenance Binding',
|
||
sidebarProvenanceDesc: 'Global effect. Implicitly embed exact model hashes into generated images and saved workflows, ensuring missing models can always be auto-fixed.',
|
||
sidebarOverwrite: 'Force Overwrite Configs',
|
||
sidebarOverwriteDesc: 'Ignore existing .info files and force re-scan/overwrite. Useful for fixing mismatched models.',
|
||
sidebarSmartFix: 'Smart Fix Current Workflow',
|
||
sidebarSmartFixDesc: 'After scanning, automatically attempt to fix missing model errors on the current canvas.',
|
||
sidebarNoModelsSelected: 'No models selected',
|
||
sidebarScanFailed: 'Scan failed: ',
|
||
sidebarCancel: 'Cancel',
|
||
sidebarExecute: 'Execute Scan',
|
||
sidebarSwitchToEnglish: '🌐 Language: EN',
|
||
sidebarSwitchToChinese: '🌐 语言: 中文',
|
||
sidebarImportExport: '📥 Import / Export Workflow (Share Code)',
|
||
sidebarGlobalQuickScan: '🌍 Global Quick Scan (No rename/No media)',
|
||
sidebarGlobalQuickScanShort: '🌍 Global Quick Scan (No rename/No media)',
|
||
sidebarGlobalQuickConfirm: 'Start global quick scan to sync all hashes?',
|
||
sidebarScanning: '⏳ Scanning...',
|
||
sidebarGlobalStarted: '🚀 Global Scan started in background!',
|
||
sidebarScanDone: '✅ Scan Complete',
|
||
sidebarError: 'Error: ',
|
||
sidebarLocalScanOn: '☑ Local metadata scan for non-Civitai [ON]',
|
||
sidebarLocalScanOff: '☐ Local metadata scan for non-Civitai [OFF]',
|
||
sidebarLocalScanOnEn: '☑ Local metadata scan for non-Civitai [ON]',
|
||
sidebarLocalScanOffEn: '☐ Local metadata scan for non-Civitai [OFF]',
|
||
sidebarCheckMissing: '🔍 Check & Auto-Scan Missing Info',
|
||
sidebarChecking: '⏳ Checking...',
|
||
sidebarMissingScanning: '⚠️ Missing info found, Auto-Scanning...',
|
||
sidebarInfoComplete: '✅ Info Complete',
|
||
sidebarAllInfoComplete: '✨ All Model Info is Complete',
|
||
sidebarUiScale: 'UI Scale',
|
||
sidebarResetLayout: '🔄 Reset Layout',
|
||
sidebarResetConfirm: 'Reset window position, scale and dock state?',
|
||
sidebarInjectHash: '🟢 Inject Workflow Hash',
|
||
sidebarSkipHash: '⚪ Skip Workflow Hash',
|
||
sidebarManageFolders: '📁 Manage Folders',
|
||
sidebarFeedback: '💬 Submit Feedback / Report Bug',
|
||
sidebarModelSettings: '🖼️ Model Settings',
|
||
sidebarModelCardSettings: 'Model Card Settings',
|
||
sidebarModelCardDescription: 'Only changes cards in the model browser. Model files and original covers remain untouched.',
|
||
sidebarVideoPlayback: 'Video cover playback',
|
||
sidebarVideoHelp: 'Always play is more lively; hover play uses less GPU memory and power.',
|
||
sidebarAlwaysPlay: 'Always play',
|
||
sidebarHoverPlay: 'Play on hover (Recommended)',
|
||
sidebarCardQuality: 'Card image quality',
|
||
sidebarCardQualityHelp: 'Optimized thumbnails are card-only; details still show the original cover.',
|
||
sidebarOptimizedThumbnail: 'Optimized thumbnail (Recommended)',
|
||
sidebarOriginalCover: 'Original cover (More resource use)',
|
||
sidebarModelSettingsNote: 'The plugin automatically caches and evicts thumbnails, and releases videos offscreen or when closed.',
|
||
sidebarDone: 'Done',
|
||
sidebarModuleNotLoaded: 'Module not loaded, please refresh!',
|
||
sidebarExpandAll: '➕ Expand All',
|
||
sidebarCollapseAll: '➖ Collapse All',
|
||
sidebarSearchModels: '🔍 Search models...',
|
||
sidebarFolderManagerTitle: '📁 Manage Folders',
|
||
sidebarFolderManagerDesc: 'Drag and drop to reorder folders. Click the eye icon to hide unneeded folders. Hidden folders are skipped during scanning and consume zero performance.',
|
||
sidebarCategoryMode: 'Category Mode (ComfyUI)',
|
||
sidebarPhysicalMode: 'Physical Mode (Local)',
|
||
sidebarFolderLoadFailed: 'Failed to load folder types.',
|
||
sidebarFolderModeError: 'Error switching mode',
|
||
sidebarVisible: 'Visible',
|
||
sidebarHidden: 'Hidden',
|
||
sidebarSaveReload: 'Save & Reload',
|
||
sidebarSaveConfigError: 'Error saving config: ',
|
||
hashResolverFixed: '🪄 Anomalous successfully fixed {count} missing model(s)!\n\n💡 Tip: ComfyUI V1 caches errors heavily. Please manually click the [Refresh] button in the "Workflow Overview" side panel, or refresh your browser (F5) to prevent them from turning red again on workflow switch.',
|
||
closeHelp: 'Close Manual',
|
||
delSure: '⚠️ Sure?',
|
||
dockTitle: 'Dock to Left',
|
||
replaceAll: 'Replace All',
|
||
editRaw: '📝 Edit Raw / Paste',
|
||
findPlaceholder: 'Find...',
|
||
replacePlaceholder: 'Replace with...',
|
||
models: 'Models',
|
||
gallery: 'Gallery',
|
||
apiKeyConfig: '🔑 Civitai API Key Config (For downloading previews)',
|
||
apiKeyPrompt: 'Enter your Civitai API Key:',
|
||
settingsBtn: 'Settings',
|
||
closeSettings: '✖ Close Settings',
|
||
doctorBtn: 'Node Assistant',
|
||
importBtn: '📥 Import / Export Workflow (Share Code)',
|
||
recipeTitle: 'Workflow Recipes',
|
||
recipeBetaNotice: 'Workflow Recipes are still in beta. Before updating the plugin or importing, restoring, deleting, or applying parameters, save the canvas and back up anomalous_recipes and anomalous_parameters under your user workflows directory.',
|
||
recipeClose: 'Close Workflow Recipes',
|
||
recipeSaveCurrent: 'Save Current Workflow',
|
||
recipeSaveTitle: 'Save Workflow Recipe',
|
||
recipeName: 'Name',
|
||
recipeDefaultName: 'New Workflow Recipe',
|
||
recipeNameRequired: 'Enter a recipe name.',
|
||
recipeTags: 'Tags',
|
||
recipeTagsHint: 'For example: portrait, SDXL, upscale',
|
||
recipeNotes: 'Notes',
|
||
recipeNotesHint: 'Why this version works well…',
|
||
recipeThumbnail: 'Workflow thumbnail',
|
||
recipeCancel: 'Cancel',
|
||
recipeSave: 'Save',
|
||
recipeSaving: 'Saving…',
|
||
recipeSaveReceipt: 'Saved: {nodes} nodes, {links} links, {groups} groups.',
|
||
recipeSaveReceiptMismatch: 'Saved, but the integrity receipt differs from the current canvas. Reopen the recipe to verify it.',
|
||
recipeEmpty: 'No Workflow Recipes yet. Save a workflow that is working well.',
|
||
recipeLoadError: 'Could not load Workflow Recipes.',
|
||
recipeUntitled: 'Untitled Recipe',
|
||
recipeSearchPlaceholder: 'Search names, notes, or tags…',
|
||
recipeClearFilters: 'Clear filters',
|
||
recipeNoTags: 'No tags yet',
|
||
recipeNoMatches: 'No recipes match. Clear the search or tag filters.',
|
||
recipeFilterByTag: 'Filter by this tag',
|
||
recipeImport: 'Import package',
|
||
recipeExport: 'Export package',
|
||
recipeExportError: 'Could not export the Workflow Recipe package.',
|
||
recipeImportError: 'Could not import the Workflow Recipe package.',
|
||
recipeExportSnapshotsConfirm: 'Include model preview snapshots in the export?\n\nSnapshots are presentation data; video covers are reduced to lightweight stills and original videos are never packed.',
|
||
recipeExportHistoryConfirm: 'Include historical versions in the export?\n\nHistory may contain older prompts and notes.',
|
||
recipeExportRedactIdentityConfirm: 'Remove model SHA-256, size, and provenance information?\n\nChoose OK to remove those identity fields.',
|
||
recipeDialogNo: 'No',
|
||
recipeImportSummary: 'The recipe package passed inspection. Import these contents?',
|
||
recipeImportAssets: 'Preview assets',
|
||
recipeImportHistory: 'Historical versions',
|
||
recipeImportRenamePrompt: 'This recipe name already exists. Enter the imported name:',
|
||
recipeModel: 'Model',
|
||
recipeLoras: 'LoRAs',
|
||
recipePrompt: 'Positive prompt',
|
||
recipeSteps: 'Steps',
|
||
recipeRestore: 'Restore version',
|
||
recipeAppendCanvas: 'Append to Canvas',
|
||
recipeAppendError: 'Could not append this recipe to the current canvas.',
|
||
recipeDelete: 'Delete',
|
||
recipeDeleteConfirm: 'Delete this Workflow Recipe?',
|
||
recipeDeleteError: 'Could not delete this Workflow Recipe.',
|
||
recipeSaveError: 'Could not save this Workflow Recipe.',
|
||
recipeNodeParams: 'Node parameters',
|
||
recipeUnknownNode: 'Unknown node',
|
||
recipeCopyParameter: 'Copy parameter value',
|
||
recipeCopied: 'Copied',
|
||
recipeCopyFailed: 'Copy failed',
|
||
recipeAdvancedInfo: 'Advanced information',
|
||
recipeInlineEditName: 'Click to edit the name',
|
||
recipeInlineEditNotes: 'Click to edit notes',
|
||
recipeInlineEditTags: 'Edit tags',
|
||
recipeInlineSave: 'Save',
|
||
recipeInlineCancel: 'Cancel',
|
||
recipeInlineSaving: 'Saving…',
|
||
recipeInlineError: 'Could not save. Try again.',
|
||
recipeInlineNameRequired: 'Name cannot be empty.',
|
||
recipeSomeParamsInWorkflow: 'Other complex or sensitive parameters remain in the full workflow.',
|
||
recipeMoreNodesInWorkflow: 'Other nodes remain in the full workflow.',
|
||
recipeMissingNodes: 'These node types are currently missing; the restored workflow may not run',
|
||
recipeBindImage: 'Bind cover image',
|
||
recipeNoImage: 'No image',
|
||
recipeCanvasPreview: 'Current canvas',
|
||
recipeLoadingRecentImages: 'Loading recent outputs…',
|
||
recipeRecentImages: 'Recent outputs',
|
||
recipeRecentImagesUnavailable: 'Recent outputs are currently unavailable.',
|
||
recipeChoosePinnedParams: 'Choose key parameters',
|
||
recipePinnedParams: 'Key parameters',
|
||
recipeKeepImage: 'Keep current cover',
|
||
recipeEdit: 'Edit',
|
||
recipeEditTitle: 'Edit Workflow Recipe',
|
||
recipeEditNodeParams: 'Edit node parameters',
|
||
recipeComplexParam: 'Complex values are shown only; the full value remains safely stored in the 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.',
|
||
recipeEditCanvas: 'Edit on canvas',
|
||
recipeEditCanvasConfirm: 'Loading replaces the current canvas. After structural edits, use Update Current Recipe to save a new version. Continue?',
|
||
recipeUpdate: 'Save updates',
|
||
recipeUpdateCurrent: 'Update Current Recipe',
|
||
recipeUpdateError: 'Could not update this Workflow Recipe.',
|
||
recipeViewDetails: 'View details',
|
||
recipeDetailBack: 'Back to recipes',
|
||
recipeDetailOverview: 'Overview',
|
||
recipeGallery: 'Gallery',
|
||
recipeGalleryLoading: 'Finding matching history images…',
|
||
recipeGalleryEmpty: 'No matching result was found in the latest 200 PNGs with workflow metadata.',
|
||
recipeGalleryRefresh: 'Refresh matches',
|
||
recipeGallerySetCover: 'Set as recipe cover',
|
||
recipeGalleryCoverSaved: 'Recipe cover set',
|
||
recipeGalleryCoverError: 'Could not set the recipe cover.',
|
||
recipeGalleryLoadError: 'Could not load the recipe gallery.',
|
||
recipeGalleryScanHint: 'Checked the latest {count} PNGs with workflow metadata.',
|
||
recipeGalleryOpenImage: 'View full image',
|
||
recipeGalleryCompare: 'Compare parameters',
|
||
recipeGalleryComparison: 'Recipe vs image parameters',
|
||
recipeGalleryComparisonLoading: 'Reading this image parameters…',
|
||
recipeGalleryComparisonError: 'Could not read this image parameters.',
|
||
recipeGalleryNoDifferences: 'No displayable parameter differences were found.',
|
||
recipeGalleryDifferenceHint: 'These are node-parameter differences; gallery matching only uses node types.',
|
||
recipeGalleryRecipeValue: 'Recipe',
|
||
recipeGalleryImageValue: 'Image',
|
||
recipeDetailModels: 'Models & reproducibility',
|
||
recipeDetailParameters: 'Parameter Notebook',
|
||
recipeDetailParametersHint: 'This view contains the saved parameters. Long values can be expanded and copied. The parameter gallery matches values, not local paths.',
|
||
recipeParameterSnapshots: 'Parameter snapshots',
|
||
recipeParameterSnapshotsHint: 'Each recipe save creates one read-only snapshot.',
|
||
recipeParameterShowing: 'Showing parameter note',
|
||
recipeParameterCurrentRecipe: 'Current recipe parameters',
|
||
recipeParameterActive: 'Current',
|
||
recipeParameterRefresh: 'Refresh snapshots',
|
||
recipeParameterLoading: 'Loading parameter snapshots…',
|
||
recipeParameterLoadError: 'Could not load parameter snapshots.',
|
||
recipeParameterNoSnapshots: 'This recipe has no parameter snapshots yet.',
|
||
recipeParameterUntitled: 'Untitled parameter snapshot',
|
||
recipeParameterDelete: 'Delete parameter note',
|
||
recipeParameterDeleteConfirm: 'Delete the parameter note “{name}”? This cannot be undone.',
|
||
recipeParameterDeleteError: 'Could not delete the parameter note. Please try again.',
|
||
recipeParameterNew: 'New parameter note',
|
||
recipeParameterReadCurrent: 'Read current and create',
|
||
recipeParameterReadCurrentSaving: 'Reading and saving…',
|
||
recipeParameterReadCurrentError: 'Could not read parameters from the current canvas.',
|
||
recipeParameterSkeletonMismatch: 'The current canvas is missing recipe skeleton 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',
|
||
recipeParameterApplying: 'Checking the skeleton and applying…',
|
||
recipeParameterApplied: 'Applied {count} 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.',
|
||
recipeParameterName: 'Note name',
|
||
recipeParameterSave: 'Save parameter note',
|
||
recipeParameterCancel: 'Cancel editing',
|
||
recipeParameterSaveError: 'Could not save the parameter note.',
|
||
recipeParameterSensitiveHidden: 'Sensitive widget hidden',
|
||
recipeDetailParameterSummary: 'Common parameters',
|
||
recipeDetailNodeParameters: 'Node parameters',
|
||
recipeDetailUnknownNode: 'Unnamed node',
|
||
recipeDetailWidget: 'Widget',
|
||
recipeDetailScheduler: 'Scheduler',
|
||
recipeDetailSteps: 'Steps',
|
||
recipeDetailCFG: 'CFG',
|
||
recipeDetailDenoise: 'Denoise',
|
||
recipeDetailSeed: 'Seed',
|
||
recipeParameterGallery: 'Outputs with the same parameters',
|
||
recipeParameterGalleryLoading: 'Finding historical outputs with the same parameters…',
|
||
recipeParameterGalleryEmpty: 'No historical output with identical parameters was found.',
|
||
recipeParameterGalleryError: 'Could not load the parameter gallery.',
|
||
recipeDetailNoSavedParameters: 'This recipe has no displayable parameters.',
|
||
recipeDetailVersions: 'Versions',
|
||
recipeDetailSummary: 'Summary',
|
||
recipeDetailModelComposition: 'Model composition',
|
||
recipeDetailBaseModel: 'Base model',
|
||
recipeDetailIdentity: 'Verified identities',
|
||
recipeDetailUnverified: 'Unverified models',
|
||
recipeDetailMissingNodes: 'Missing node types',
|
||
recipeDetailFingerprint: 'Workflow fingerprint',
|
||
recipeDetailNotIndexed: 'Not indexed yet',
|
||
recipeDetailLoraSummary: 'LoRA',
|
||
recipeDetailSampler: 'Sampler',
|
||
recipeDetailResolution: 'Resolution',
|
||
recipeDetailUnavailable: 'Unavailable',
|
||
recipeDetailEditOrigin: '✏️ Edit Origin',
|
||
recipeOriginDialogTitle: 'Edit Model Origin',
|
||
recipeOriginOfficialName: 'Official Model Name',
|
||
recipeOriginModelUrl: 'Official Model URL',
|
||
recipeOriginFetchHash: '🌍 Auto-fetch via Hash',
|
||
recipeOriginFetching: 'Fetching...',
|
||
recipeOriginFetchFailed: 'Not found or network error',
|
||
recipeOriginFetchSuccess: 'Successfully fetched!',
|
||
recipeDetailNoNotes: 'No notes.',
|
||
recipeDetailUpdated: 'Updated',
|
||
recipeDetailCopyPrompt: 'Copy prompt',
|
||
recipeDetailCopyFingerprint: 'Copy workflow fingerprint',
|
||
recipeDetailCopyHash: 'Copy full hash',
|
||
recipeDetailPrompts: 'Prompts',
|
||
recipeDetailPositivePrompt: 'Positive prompt',
|
||
recipeDetailNegativePrompt: 'Negative prompt',
|
||
recipeDetailNoPrompts: 'This recipe 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',
|
||
recipePromptRoleManual: 'Manually labelled',
|
||
recipePromptRolePositive: 'Positive prompt',
|
||
recipePromptRoleNegative: 'Negative prompt',
|
||
recipePromptRoleBoth: 'Shared positive / negative',
|
||
recipePromptRoleIgnored: 'Ignore',
|
||
recipePromptRoleUnknown: 'Role unknown',
|
||
recipePromptRoleSaveError: 'Could not save the prompt role. Please try again.',
|
||
recipeDetailVolatileIgnored: 'Runtime-changing value ignored',
|
||
recipeDetailExpandValue: 'Show full value',
|
||
recipeDetailCollapseValue: 'Collapse value',
|
||
recipeIdentityVerified: 'Identity verified',
|
||
recipeIdentityUnverified: 'Local available, unverified',
|
||
recipeIdentityUnavailable: 'Not found locally',
|
||
recipeIdentityHelpDesc: 'Verification checks if the physical file matches the saved hash, it does not judge model quality.',
|
||
recipeDetailRefreshAvailability: 'Check local availability',
|
||
recipeDetailRefreshOrigin: 'Refresh Origin Info',
|
||
recipeDetailRefreshOriginDesc: 'Refresh all model origin information in this recipe (supports backfilling old recipes)',
|
||
recipeDetailRefreshing: 'Checking…',
|
||
recipeDetailRefreshError: 'Could not check local availability.',
|
||
recipeDetailAvailable: 'Available locally',
|
||
recipeDetailMissing: 'Missing locally',
|
||
recipeDetailAvailabilityNotChecked: 'Not checked locally',
|
||
recipeDetailNoModelReferences: 'No supported model loaders were detected. Other custom widgets remain in Parameters and the full workflow.',
|
||
recipeDetailModel: 'Model',
|
||
recipeModelPath: 'Model path',
|
||
recipeOpenLocalModel: 'Open local model details',
|
||
recipeMatchLocalModel: 'Match local model',
|
||
recipeMatchingLocalModel: 'Matching local model…',
|
||
recipeMatchRecipeModels: 'Match recipe models',
|
||
recipeMatchRecipeModelsDesc: 'Find local files by model hash, file size, and model category; the author’s path is not used.',
|
||
recipeMatchingRecipeModels: 'Matching recipe models…',
|
||
recipeRecipeMatchSummary: 'Found {found}/{total} local matches',
|
||
recipeAllModelsMatched: 'All recipe models are already matched or need no match',
|
||
recipeApplyLocalMatch: 'Apply match',
|
||
recipeApplyLocalMatchDesc: 'Write the matched local model path into the recipe workflow',
|
||
recipeApplyingLocalMatch: 'Applying match…',
|
||
recipeApplyLocalMatchSuccess: 'Local model match applied',
|
||
recipeApplyLocalMatchError: 'Could not apply this model match',
|
||
recipeLocalModelNotFound: 'No matching local model was found.',
|
||
recipeLocalModelAmbiguous: 'Multiple candidates found; add model identity information first.',
|
||
recipeLocalModelMatchError: 'Matching failed. Try again later.',
|
||
recipeDetailSearchParameters: 'Search node, type, or widget name…',
|
||
recipeDetailNoParameters: 'No safe parameters match the search.',
|
||
recipeDetailCurrentVersion: 'Current version',
|
||
recipeCompareVersion: 'Compare version',
|
||
recipeDiffLoading: 'Comparing…',
|
||
recipeDiffSummary: 'Change summary',
|
||
recipeDiffBefore: 'Before',
|
||
recipeDiffAfter: 'After',
|
||
recipeDiffNoChanges: 'No meaningful changes were detected between these versions.',
|
||
recipeDiffError: 'Could not read this historical version.',
|
||
recipeDiffPinned: 'Pinned parameters',
|
||
recipeDiffPrompts: 'Prompts',
|
||
recipeDiffModels: 'Model references',
|
||
recipeDiffParameters: 'Parameter summary',
|
||
recipeDiffWorkflow: 'Workflow structure',
|
||
recipeDiffPresentation: 'Presentation',
|
||
recipeDiffOther: 'Other',
|
||
recipeDetailUnknownTime: 'Unknown time',
|
||
recipeDetailLoadingPreviews: 'Loading local model previews…',
|
||
recipeDetailCurrentPreview: 'Current Local Preview',
|
||
recipeDetailNoPreview: 'No Preview',
|
||
recipeDetailSavedSnapshot: 'Snapshot Saved',
|
||
recipeParameterNotebooks: 'RECIPE PARAMETER NOTEBOOKS',
|
||
recipeParameterRename: 'Rename',
|
||
recipeParameterRenamePrompt: 'Enter a new name for this parameter notebook:',
|
||
recipeParameterRenameError: 'Failed to rename parameter notebook',
|
||
assistantTabActions: 'Actions',
|
||
assistantTabPresets: 'Parameter Presets',
|
||
assistantRecipeGroup: 'Recipe',
|
||
assistantDeletedRecipe: 'Deleted Recipe',
|
||
assistantUnboundRecipe: 'Global Unbound',
|
||
assistantNotebook: 'Notebook',
|
||
assistantApplyTo: 'Apply to',
|
||
assistantNoPresets: 'No parameter presets found for this node type.',
|
||
}
|
||
};
|
||
|
||
const DEFAULT_LOCALE = 'zh';
|
||
const FALLBACK_LOCALE = 'en';
|
||
const hasOwn = (object, key) => Object.prototype.hasOwnProperty.call(object, key);
|
||
|
||
export const supportedLocales = Object.freeze(Object.keys(i18n));
|
||
|
||
export function normalizeLocale(value) {
|
||
const raw = String(value ?? '').trim().toLowerCase().replace(/_/g, '-');
|
||
if (!raw) return '';
|
||
const base = raw.split('-')[0];
|
||
return hasOwn(i18n, base) ? base : '';
|
||
}
|
||
|
||
export function resolveLocale(value = globalThis.anomalous_browser_lang) {
|
||
return normalizeLocale(value) || DEFAULT_LOCALE;
|
||
}
|
||
|
||
export function formatTranslation(template, params = {}) {
|
||
if (typeof template !== 'string') return template;
|
||
return template.replace(/\{([A-Za-z0-9_.-]+)\}/g, (token, key) => (
|
||
hasOwn(params, key) ? String(params[key]) : token
|
||
));
|
||
}
|
||
|
||
export function translate(key, params = {}, locale = resolveLocale()) {
|
||
const activeLocale = resolveLocale(locale);
|
||
const template = i18n[activeLocale]?.[key]
|
||
?? i18n[FALLBACK_LOCALE]?.[key]
|
||
?? i18n[DEFAULT_LOCALE]?.[key]
|
||
?? key;
|
||
return formatTranslation(template, params);
|
||
}
|
||
|
||
export function createTranslator(locale) {
|
||
return (key, params = {}) => translate(key, params, locale);
|
||
}
|