简介这是一款专为ComfyUI用户打造的中文提示词输入自定义插件针对不熟悉英文术语的创作者设计可直接通过中文关键词完成AI生图参数调整与创意表达大幅降低上手门槛。资源包为ZIP压缩格式共619个文件包括224个JSON节点配置、101个JavaScript脚本、9个Python脚本以及大量PNG预览图、CSS样式和示例文档整体约16.96MB解压到CustomNode目录即可生效。目前已有769人学习下载适合零基础新手和希望提升AI绘画效率的中文用户使用。该插件内含完整的界面适配配置、节点样式与自定义字体、可视化示例和安装指引读者既能直接安装使用也能通过文件结构了解插件开发思路为后续自研节点提供参考。借助这一工具中文用户可以在ComfyUI中更流畅地表达创意享受AI绘画带来的便利。1. 为什么在 ComfyUI 里直接敲中文出图会翻车在 ComfyUI 里输入中文提示词很多人第一反应是“加个文本框不就行了”其实真正的卡点不在输入框而在背后那层文本编码。ComfyUI 内置的文本编码器是基于英文语料训练的你硬塞一句中文进去得到的是一个信息损失严重的条件向量画面经常出现主体对了、风格崩了、细节丢了的情况。这个现象不是玄学而是编码器的词表里根本没有中文的位置。于是“自定义插件 中文提示词输入”才成了一个值得认真做的方向在输入和编码之间补一层可控的翻译与术语映射让中文提示词真正变成可用的生产步骤而不是每次手动查词典、翻完再改。下面这套方案会从插件骨架讲起一直做到能稳定挂在 ComfyUI 里日常使用的程度。2. 先搞懂自定义节点的加载骨架从init.py 到节点面板2.1 目录结构与两个注册字典ComfyUI 的自定义节点并不是把 Python 文件丢进custom_nodes就能自动识别它依赖一套固定的注册机制。一个最干净的插件目录长这样custom_nodes/ └── comfyui-zh-prompt/ ├── __init__.py ├── zh_prompt_node.py └── web/web/目录在没有自定义前端 JS 的时候可以留空但目录本身建议保留因为新版 ComfyUI 扫描插件时会检查WEB_DIRECTORY指向的路径是否存在。真正决定节点能不能出现在面板里的是__init__.py里的两个字典。NODE_CLASS_MAPPINGS用于把字符串 ID 映射到 Python 类NODE_DISPLAY_NAME_MAPPINGS用于定义显示名两者缺一不可。如果显示名映射漏了ComfyUI 会直接用类名当显示名虽然不影响运行但在节点列表里很难看。另外一个实务点字符串 ID 要保证全局唯一。不同作者写的插件如果撞了同一个 IDComfyUI 启动时会采用“后加载者覆盖先加载者”的策略你辛苦写的节点可能直接被别人的同名节点顶掉。所以给节点起内部 ID 时最好带项目前缀比如zh_prompt_translate_node而不是图省事写个translate。2.2 最小插件骨架注册一个空节点先跑通一个最小骨架确认加载链路没有断再去填充翻译逻辑。下面是__init__.py的完整内容# __init__.py from .zh_prompt_node import ZhCnPromptNode NODE_CLASS_MAPPINGS { ZhCnPromptNode: ZhCnPromptNode, } NODE_DISPLAY_NAME_MAPPINGS { ZhCnPromptNode: 中文提示词输入, } WEB_DIRECTORY ./web __all__ [NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS]WEB_DIRECTORY ./web是近几版 ComfyUI 的硬性要求。如果你用的是较老版本web 目录会自动识别但新版没有这个声明就可能出现“Python 类明明注册了前端面板就是找不到”的怪问题。这一点先记住后面的避坑章节会再展开。然后是zh_prompt_node.py先写一个只做透传的占位节点验证“能在面板里拖出来并且执行不报错”# zh_prompt_node.py class ZhCnPromptNode: classmethod def INPUT_TYPES(cls): return { required: { zh_text: (STRING, { multiline: True, default: 一只橘猫坐在窗台上, }), }, } RETURN_TYPES (STRING,) RETURN_NAMES (en_prompt,) FUNCTION run CATEGORY 中文提示词输入 def run(self, zh_text): return (zh_text,)INPUT_TYPES里的multiline: True让前端渲染出一个多行文本框这是 ComfyUI 里标准的多行文本控件声明方式。RETURN_TYPES声明输出类型是字符串配套的RETURN_NAMES给出端口名称。FUNCTION指定执行入口方法名节点每次执行时都会调用run方法并把输入参数按名字传进来。注意返回值必须是元组哪怕只有一个输出也要写成(zh_text,)写成普通字符串会直接报错。把文件放好后重启 ComfyUI打开节点搜索面板输入“中文提示词输入”能搜到并且能执行就说明加载链路通了。2.3 三种常用的输入控件声明文本、下拉与多行做提示词输入插件最常用的输入控件有三种。第一种是上面那种多行文本适合写完整的中文提示词第二种是单行文本适合做phrase这种短词组输入第三种是下拉框适合做工作模式切换。三种控件写法如下classmethod def INPUT_TYPES(cls): return { required: { zh_text: (STRING, {multiline: True, default: }), mode: ([translate_only, translate_and_return_list], {default: translate_only}), }, optional: { extra_note: (STRING, {default: best quality}), }, }下拉框的写法是给一个字符串列表作为可选值ComfyUI 会自动渲染成下拉控件optional区块里的参数不在默认端口里强制显示但对提示词类插件来说把“补充英文风格词”这种不常用的输入放到 optional 里能让主界面保持干净。这里有一个经常被忽略的细节STRING控件若想设置“当前值不可为空”需要把 default 留空并在节点端自行校验ComfyUI 本身不会因为空字符串给你报错它只是沉默地把空字符串传进来。所以翻译节点里遇到空输入时要在代码里明确返回一个回落提示词而不是继续调翻译接口。3. 实现中文转英文提示词节点翻译、缓存与术语保护3.1 节点代码带缓存和重试的翻译逻辑空节点跑通之后接着把翻译逻辑填进去。下面这版代码是我在实际使用时一直保留的结构它做了三件事缓存同名提示词的翻译结果、对专有名词做占位保护、请求超时后自动重试一次。# zh_prompt_node.py import hashlib import json import time from pathlib import Path import requests BASE_DIR Path(__file__).parent CACHE_FILE BASE_DIR / translation_cache.json TRANSLATE_API 替换成你申请到的翻译接口地址 TERM_DICT { 杰作: masterpiece, 高质量: best quality, 高细节: highly detailed, 电影光: cinematic lighting, 赛璐璐: cel shading, 全身像: full body shot, } class ZhCnPromptNode: classmethod def INPUT_TYPES(cls): return { required: { zh_text: (STRING, { multiline: True, default: 一只橘猫坐在窗台上午后阳光杰作级, }), timeout: (INT, {default: 10, min: 3, max: 60, step: 1}), use_cache: (BOOLEAN, {default: True}), }, optional: { term_map: (STRING, { multiline: True, default: , placeholder: 每行一个: 中文:英文, }), }, } RETURN_TYPES (STRING,) RETURN_NAMES (en_prompt,) FUNCTION run CATEGORY 中文提示词输入 def run(self, zh_text, timeout, use_cache, term_map): cache_key hashlib.md5( (zh_text || term_map).encode(utf-8) ).hexdigest() if use_cache: cache self._load_cache() if cache_key in cache: return (cache[cache_key],) guarded_text, placeholder_map self._protect_terms(zh_text, term_map) translated self._request_translation(guarded_text, timeout) en_text self._restore_terms(translated, placeholder_map) if use_cache: cache[cache_key] en_text self._save_cache(cache) return (en_text,)cache_key用zh_text和term_map拼接后取 MD5这样改了术语映射也会走新的缓存不会互相污染。_protect_terms是这套节点的核心思路把“杰作”“赛璐璐”这类词从中文句子里抽出来换成大括号占位符让翻译接口先翻译剩下的普通句子翻译完成后再把英文术语填回去。这样做的原因很实际——机器翻译遇到“赛璐璐”这类动画术语时经常翻出离谱的地名音译占位保护能直接绕过这个问题。3.2 关键方法与参数说明继续补齐上面的三个私有方法。它们对应了三个容易翻车的环节接口调用、术语表解析、占位还原。def _load_cache(self): if not CACHE_FILE.exists(): return {} try: return json.loads(CACHE_FILE.read_text(encodingutf-8)) except (json.JSONDecodeError, OSError): return {} def _save_cache(self, cache): try: CACHE_FILE.write_text( json.dumps(cache, ensure_asciiFalse, indent2), encodingutf-8, ) except OSError: pass def _protect_terms(self, text, term_map): mapping {} for zh, en in TERM_DICT.items(): if zh in text: mapping[zh] en if term_map and term_map.strip(): for line in term_map.splitlines(): if : not in line: continue zh, en line.split(:, 1) zh, en zh.strip(), en.strip() if zh and en: mapping[zh] en placeholder_map {} guarded text for i, (zh, en) in enumerate(mapping.items()): placeholder f{{{{term_{i}}}}} guarded guarded.replace(zh, placeholder) placeholder_map[placeholder] en return guarded, placeholder_map def _restore_terms(self, translated, placeholder_map): for placeholder, en in placeholder_map.items(): if placeholder in translated: translated translated.replace(placeholder, en) else: translated , en return translated def _request_translation(self, text, timeout): for attempt in range(2): try: resp requests.post( TRANSLATE_API, json{q: text}, timeouttimeout, ) if resp.status_code 200: data resp.json() if isinstance(data.get(translatedText), str): return data[translatedText] if isinstance(data.get(data), dict): return data[data][translated] except requests.Timeout: pass time.sleep(1) raise RuntimeError(翻译接口超时请检查网络或调大 timeout 参数)TERM_DICT是内置的默认映射表适合通用画风词term_map是用户在节点面板上临时追加的映射优先级更高适合某个特定项目里的人名、地名或画风词。占位符用的是双层花括号{{term_0}}这种形式绝大多数翻译接口会保留花括号内容不翻译这是做过多个接口后才确认可行的做法。如果翻译接口返回的内容里找不到占位符说明接口把花括号吞掉了这时直接拼到句子末尾至少保证术语不丢。这个“兜底拼回”的行为会让句子结构不完美但比术语丢失导致画错要强得多。节点面板上的参数各有讲究。timeout默认给 10 秒免费接口建议调到 15商用接口 8 到 10 秒足够。use_cache默认开启实际使用中这一项能省掉八成以上的重复请求。term_map默认留空在需要时逐行填写例如吉卜力:Studio Ghibli每行一对映射。对于不指定具体厂商的翻译接口这里留了TRANSLATE_API常量你申请到哪家就填哪家。选接口时重点看两个指标免费额度里的请求频率限制以及返回 JSON 的结构是否固定。不确定响应结构时先用浏览器或命令行工具直接调用一次观察返回再决定_extract_translation里解析哪个字段。3.3 把节点接到现有工作流里两种连接方式这个节点最稳妥的用法是只输出字符串不碰 CLIP 模型。把en_prompt端口连到 ComfyUI 原生的CLIPTextEncode节点上正向提示词一套、反向提示词一套完全复用官方维护的编码逻辑。这样做的最大优势是兼容性——不同时期的 ComfyUI 对CLIPTextEncode内部实现做过多轮调整但节点本身的端口从来没有变过你用字符串中转就永远不用追版本。另一种做法是把 CLIP 编进节点内部直接输出CONDITIONING省掉一个连接线。这类实现需要在节点里拿到clip对象并调用文本编码接口不同版本的方法名有差异容易跟上版本升级。我一般只在做一次性实验时用交付给别人用时始终走字符串输出方案。对绝大多数使用者来说多拉一根线不是负担少依赖一个内部接口才是真正的省心。接好线的典型工作流长这样中文提示词节点输出英文接到正向CLIPTextEncode反向提示词同样接一个中文节点输入“模糊低质量丑陋畸形”这类负面词。首次执行时能明显看到节点有网络请求耗时第二次执行同一句提示词时耗时降到几乎为零因为缓存直接命中了。4. 排查与避坑翻译超时、术语崩坏与节点列表消失4.1 现象一节点列表里找不到刚写的插件明明把整个文件夹丢进了custom_nodes重启之后面板里就是搜不到控制台也没有红色报错。最常见的元凶有三个。第一个是__init__.py里忘记写NODE_CLASS_MAPPINGS或者字典里的类名和实际类对不上。ComfyUI 扫描到没有映射的模块时不会报错只会静默跳过。第二个是requests库没装导致zh_prompt_node.py在 import 阶段就抛异常整组节点加载失败。第三个是版本差异新版 ComfyUI 要求WEB_DIRECTORY声明存在缺失时前端不会加载该插件的节点定义。排查顺序也按这个来先看启动日志里有没有ImportError或ModuleNotFoundError其次确认__init__.py的字典键名与类名一致最后检查WEB_DIRECTORY声明。在__init__.py里临时加一行print(load zh prompt node)是最快的定位方式启动时输出过这行说明模块本身没问题问题一定出在注册字典。4.2 现象二翻译接口超时或频繁返回限流码表现很直接第一次用一切正常连续生成几张图之后节点开始报超时偶尔过几分钟又自己好了。这不是网络断了而是免费翻译接口对短时间内的请求数量做了限制。中文提示词节点的一个隐蔽特性是会随工作流里的采样步数变化被反复调用如果同一句提示词没有命中缓存每次采样都会触发一次新请求。解决办法分三步首先确认use_cache确实开着多数情况开启后同一句提示词只会请求一次其次把timeout调到 15 秒给慢响应留出余量最后在_request_translation的超时分支里补一个退避等待等 1 秒再重试不要立即连续请求。代码里现有实现是重试一次实际需要更稳的队伍可以改成三次重试并把退避时间翻倍递增。4.3 现象三中文翻译成英文后画风全变这是“中文提示词输入”最容易翻车的地方。输入“杰作级高细节电影光”翻译接口给出的结果里这些词要么消失要么被翻成非常普通的英文比如“masterpiece”变成“master work”看似意思相近但稳定扩散模型对于风格质量词的响应存在惯性生图效果直接差一截。解决方式是先保护再翻译也就是_protect_terms正在做的事。把“杰作”映射为固定的masterpiece翻译过程不触碰它生成的英文提示词永远保留目标模型的习惯用语。如果你经常做特定风格比如古风、赛璐璐、写实摄影把对应的英文风格词整理进TERM_DICT一次性投入后面每张图都受益。另外要注意不要只依赖翻译接口的自动翻译来覆盖风格词每个模型偏爱的风格词清单不完全一样用一段时间后按实际输出效果回填映射表比不断调接口更有效。4.4 现象四输出提示词里出现多余句号与分隔符翻译结果是英文但原始中文里的全角逗号、句号可能被直接保留或者接口在句子末尾多补一个句号。ComfyUI 的提示词语法里逗号是有实际含义的多余标点会被解析成空权重或异常分组画面出现明明写“一只猫”却不出猫的情况。处理办法是在翻译前统一做一次标点归一化把全角逗号、句号转成半角翻译完成后再把结果里的连续空格和多余逗号清理干净。这个逻辑如果你已经写完节点再补也不算迟在run方法入口加两行替换就行zh_text zh_text.replace(, ,).replace(。, .).replace(、, ,)空格与逗号的清理放在翻译之后使用简单的re.sub(r\s*,\s*, , , translated)即可。这一步直接避免了大量“提示词写得没问题但画面无法复现”的玄学事故。4.5 验证方法三张图的控制变量对比节点写完不要只看一两次输出就宣布可用用三张图的控制变量对比来验证质量。固定同一个种子和采样器生成三组画面第一组用翻译节点输出的英文第二组用人手修正过的英文第三组完全用原生英文提示词。对比项第一组第二组第三组预期观察主体描述翻译输出人工修正原生英文主体应该一致风格词完整性可能缺已补充完整画风差异主要出在这里细节密度看映射表看映射表原生缺失时细节明显减少如果翻译输出的画面与人工修正后的差距集中在风格词上说明术语表需要补条目如果主体描述本身就漂移说明接口的翻译质量不达标需要换接口或者把节点改为走本地翻译模型。这套验证方式不需要额外工具固定种子跑一次就能定位绝大多数问题。5. 进阶术语字典、本地翻译回退与批量提示词把这套节点推给团队或自己长期使用时有三个体验上的做法可以进一步优化。第一个是维护一份“项目专属术语映射表”不要只依赖代码里的TERM_DICT。每次出图后凡是发现“为什么这里翻译歪了”的词立刻记到term_map输入框里。一段时间后这些映射会沉淀成一份高价值资产关键的是它跟工作流文件一起保存换电脑不丢。吉卜力:Studio Ghibli 新海诚风:Shinkai style 赛博朋克:cyberpunk, neon-lit第二个是考虑本地翻译回退。对免费接口的请求频率限制感到恼火时可以在节点里加一个布尔参数use_local_first优先调用本地部署的翻译模型失败再走远程接口。本地翻译的好处是零延迟、无限流、数据不出机器缺点是首次加载模型耗时较长适合批量出图的场景不适合随手玩几张的轻量使用。实现时只需在_request_translation前面插入一个本地模型分支即可缓存逻辑完全复用。第三个是批量提示词的缓存热身。如果你经常跑多个候选提示词做方案筛选可以在正式出图前先把这批中文提示词逐一过一遍节点让缓存文件提前写满。之后工作流真正执行采样时所有翻译请求全部命中本地缓存整个执行过程不会卡在网络请求上。缓存文件本身可以直接复制到另一台机器团队里分发工作流时顺手带上它新成员连接口都不填就能跑通。这个方向做到这里基本就脱离了“会写一个节点”的阶段变成了一套稳定且自带知识积累的中文提示词生产方案。不要指望某个免费翻译接口永远稳定也别指望内置术语表覆盖所有风格保持“随时往映射表里加一行”的习惯比换更强壮的接口更能长期改善出图效果。希望这些踩过的坑能帮到你。本文还有配套的精品资源点击获取
阅读完成 · 觉得有帮助?