diff --git a/.gitignore b/.gitignore index a66a20d..246b1d7 100644 --- a/.gitignore +++ b/.gitignore @@ -124,4 +124,5 @@ Thumbs.db temp/ output/ models/ -input/ \ No newline at end of file +input/ +test/ \ No newline at end of file diff --git a/__init__.py b/__init__.py index c14b0ce..9688bde 100644 --- a/__init__.py +++ b/__init__.py @@ -1,8 +1,11 @@ """智能保存图片 - ComfyUI节点包""" +import os + __all__ = [ "NODE_CLASS_MAPPINGS", "NODE_DISPLAY_NAME_MAPPINGS", + "WEB_DIRECTORY", ] __author__ = "kj" @@ -10,4 +13,7 @@ __email__ = "2990346238@qq.com" __version__ = "0.1.0" # 从子包导入节点映射 -from .src.SmartSaveImage import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS \ No newline at end of file +from .src.SmartSaveImage import NODE_CLASS_MAPPINGS, NODE_DISPLAY_NAME_MAPPINGS + +# 声明Web目录以支持国际化 - 指向当前目录让ComfyUI能找到locales文件夹 +WEB_DIRECTORY = os.path.dirname(__file__) \ No newline at end of file diff --git a/locales/en-US/nodeDefs.json b/locales/en-US/nodeDefs.json deleted file mode 100644 index 6461a7c..0000000 --- a/locales/en-US/nodeDefs.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "SmartFolderManager": { - "title": "Smart Folder Manager", - "inputs": { - "images": "Input images for extracting size info and passing to save node", - "base_folder": "Base folder path, can be relative or absolute path", - "create_subfolders": "Whether to automatically create subfolders", - "enable_date_folder": "Whether to create date folder", - "enable_model_folder": "Whether to create model folder", - "enable_seed_folder": "Whether to create seed folder", - "enable_prompt_folder": "Whether to create prompt folder", - "enable_custom_folder": "Whether to use custom folder", - "date_format": "Date format: yyyy=year MM=month dd=day hh=hour mm=minute ss=second", - "include_time": "Whether to include time in date", - "model_source": "Model info source: auto=from metadata/external input, manual=manual selection", - "manual_model_name": "Manual model selection (only effective when model_source=manual)", - "model_input": "Input from model loader node (only effective when model_source=auto)", - "seed": "Seed value (manual input or connect external node)", - "positive_prompt": "Positive prompt (manual input or connect external node)", - "negative_prompt": "Negative prompt (manual input or connect external node)", - "custom_subfolder": "Custom subfolder name", - "model_short_name": "Use model short name (remove extension)", - "prompt_max_length": "Maximum length for prompt folder name", - "sanitize_names": "Clean illegal characters in filenames" - }, - "outputs": { - "images": "Passed image data", - "folder_path": "Generated folder path", - "metadata_json": "Extracted metadata JSON" - } - }, - "SmartImageSaver": { - "title": "Smart Image Saver", - "inputs": { - "images": "Images to save (usually from SmartFolderManager)", - "folder_path": "Save path (from SmartFolderManager)", - "metadata_json": "Metadata JSON (from SmartFolderManager)", - "filename_prefix": "Filename prefix", - "file_format": "Image format", - "preview_mode": "Save mode", - "add_timestamp": "Add timestamp to filename", - "add_counter": "Add counter (for multiple images)", - "counter_start": "Counter start value", - "counter_padding": "Counter padding (zero-fill)", - "jpeg_quality": "JPEG quality (1-100)", - "webp_quality": "WebP quality (1-100)", - "webp_lossless": "WebP lossless compression", - "png_compression": "PNG compression level (0-9)", - "embed_metadata": "Embed metadata into image", - "embed_workflow": "Embed workflow information", - "overwrite_existing": "Overwrite existing files", - "create_backup": "Create backup for overwritten files", - "optimize_size": "Optimize file size" - }, - "outputs": { - "images": "Saved images" - } - } -} diff --git a/locales/en-US/main.json b/locales/en/main.json similarity index 100% rename from locales/en-US/main.json rename to locales/en/main.json diff --git a/locales/en/nodeDefs.json b/locales/en/nodeDefs.json new file mode 100644 index 0000000..7b1f06c --- /dev/null +++ b/locales/en/nodeDefs.json @@ -0,0 +1,185 @@ +{ + "SmartFolderManager": { + "display_name": "Smart Folder Manager", + "description": "Smart folder manager - manages folder structure and metadata collection", + "inputs": { + "images": { + "name": "Images", + "tooltip": "Input images for extracting size info and passing to save node" + }, + "base_folder": { + "name": "Base Folder", + "tooltip": "Base folder path, can be relative or absolute path" + }, + "create_subfolders": { + "name": "Create Subfolders", + "tooltip": "Whether to automatically create subfolders" + }, + "folder_structure": { + "name": "Folder Structure", + "tooltip": "Choose folder organization method", + "options": { + "date_only": "Date Only", + "model_only": "Model Only", + "date_model": "Date + Model", + "model_date": "Model + Date", + "custom": "Custom" + } + }, + "date_format": { + "name": "Date Format", + "tooltip": "Date format: yyyy=year MM=month dd=day hh=hour mm=minute ss=second" + }, + "include_time": { + "name": "Include Time", + "tooltip": "Whether to include time in date" + }, + "model_source": { + "name": "Model Source", + "tooltip": "Model info source: auto=from metadata/external input, manual=manual selection", + "options": { + "auto": "Auto Detect", + "manual": "Manual Select" + } + }, + "manual_model_name": { + "name": "Manual Model Name", + "tooltip": "Manual model selection (only effective when model_source=manual)" + }, + "model_input": { + "name": "Model Input", + "tooltip": "Input from model loader node (only effective when model_source=auto)" + }, + "seed": { + "name": "Seed", + "tooltip": "Seed value (manual input or connect external node)" + }, + "positive_prompt": { + "name": "Positive Prompt", + "tooltip": "Positive prompt (manual input or connect external node)" + }, + "negative_prompt": { + "name": "Negative Prompt", + "tooltip": "Negative prompt (manual input or connect external node)" + }, + "custom_subfolder": { + "name": "Custom Subfolder", + "tooltip": "Custom subfolder name" + }, + "model_short_name": { + "name": "Model Short Name", + "tooltip": "Use model short name (remove extension)" + }, + "prompt_max_length": { + "name": "Prompt Max Length", + "tooltip": "Maximum length for prompt folder name" + }, + "sanitize_names": { + "name": "Sanitize Names", + "tooltip": "Clean illegal characters in filenames" + } + }, + "outputs": { + "0": { + "name": "Images", + "tooltip": "Passed image data" + }, + "1": { + "name": "Folder Path", + "tooltip": "Generated folder path" + }, + "2": { + "name": "Metadata JSON", + "tooltip": "Extracted metadata JSON" + } + } + }, + "SmartImageSaver": { + "display_name": "Smart Image Saver", + "description": "Smart image saver - handles image saving, format conversion and compression", + "inputs": { + "images": { + "name": "Images", + "tooltip": "Images to save (usually from SmartFolderManager)" + }, + "folder_path": { + "name": "Folder Path", + "tooltip": "Save path (from SmartFolderManager)" + }, + "metadata_json": { + "name": "Metadata JSON", + "tooltip": "Metadata JSON (from SmartFolderManager)" + }, + "filename_prefix": { + "name": "Filename Prefix", + "tooltip": "Filename prefix" + }, + "file_format": { + "name": "File Format", + "tooltip": "Image format", + "options": { + "png": "PNG Format", + "jpeg": "JPEG Format", + "webp": "WebP Format", + "bmp": "BMP Format", + "tiff": "TIFF Format" + } + }, + "preview_mode": { + "name": "Preview Mode", + "tooltip": "Save mode", + "options": { + "save_and_preview": "Save and Preview", + "preview_only": "Preview Only", + "save_only": "Save Only" + } + }, + "add_timestamp": { + "name": "Add Timestamp", + "tooltip": "Add timestamp to filename" + }, + "add_counter": { + "name": "Add Counter", + "tooltip": "Add counter (for multiple images)" + }, + "counter_start": { + "name": "Counter Start", + "tooltip": "Counter start value" + }, + "counter_padding": { + "name": "Counter Padding", + "tooltip": "Counter padding (zero-fill)" + }, + "jpeg_quality": { + "name": "JPEG Quality", + "tooltip": "JPEG quality (1-100)" + }, + "webp_quality": { + "name": "WebP Quality", + "tooltip": "WebP quality (1-100)" + }, + "webp_lossless": { + "name": "WebP Lossless", + "tooltip": "WebP lossless compression" + }, + "png_compression": { + "name": "PNG Compression", + "tooltip": "PNG compression level (0-9)" + }, + "embed_metadata": { + "name": "Embed Metadata", + "tooltip": "Embed metadata into image" + }, + "embed_workflow": { + "name": "Embed Workflow", + "tooltip": "Embed workflow information" + } + }, + "outputs": { + "0": { + "name": "Images", + "tooltip": "Saved images" + } + } + } +} \ No newline at end of file diff --git a/locales/zh-CN/nodeDefs.json b/locales/zh-CN/nodeDefs.json deleted file mode 100644 index 310fcc4..0000000 --- a/locales/zh-CN/nodeDefs.json +++ /dev/null @@ -1,59 +0,0 @@ -{ - "SmartFolderManager": { - "title": "智能文件夹管理", - "inputs": { - "images": "输入图片,用于提取尺寸信息并传递给保存节点", - "base_folder": "基础文件夹路径,可以是相对路径或绝对路径", - "create_subfolders": "是否自动创建子文件夹", - "enable_date_folder": "是否创建日期文件夹", - "enable_model_folder": "是否创建模型文件夹", - "enable_seed_folder": "是否创建种子文件夹", - "enable_prompt_folder": "是否创建提示词文件夹", - "enable_custom_folder": "是否使用自定义文件夹", - "date_format": "日期格式: yyyy=年 MM=月 dd=日 hh=时 mm=分 ss=秒", - "include_time": "是否在日期中包含时间", - "model_source": "模型信息来源:auto=从元数据/外部输入获取,manual=手动选择", - "manual_model_name": "手动选择模型(仅在model_source=manual时生效)", - "model_input": "从模型加载器节点输入(仅在model_source=auto时生效)", - "seed": "种子值(手动输入或连接外部节点)", - "positive_prompt": "正向提示词(手动输入或连接外部节点)", - "negative_prompt": "负向提示词(手动输入或连接外部节点)", - "custom_subfolder": "自定义子文件夹名称", - "model_short_name": "使用模型短名称(去除扩展名)", - "prompt_max_length": "提示词文件夹名最大长度", - "sanitize_names": "清理文件名中的非法字符" - }, - "outputs": { - "images": "传递的图片数据", - "folder_path": "生成的文件夹路径", - "metadata_json": "提取的元数据JSON" - } - }, - "SmartImageSaver": { - "title": "智能图片保存", - "inputs": { - "images": "要保存的图片(通常来自SmartFolderManager)", - "folder_path": "保存路径(来自SmartFolderManager)", - "metadata_json": "元数据JSON(来自SmartFolderManager)", - "filename_prefix": "文件名前缀", - "file_format": "图片格式", - "preview_mode": "保存模式", - "add_timestamp": "在文件名中添加时间戳", - "add_counter": "添加计数器(多张图片时)", - "counter_start": "计数器起始值", - "counter_padding": "计数器位数(补零)", - "jpeg_quality": "JPEG质量(1-100)", - "webp_quality": "WebP质量(1-100)", - "webp_lossless": "WebP无损压缩", - "png_compression": "PNG压缩级别(0-9)", - "embed_metadata": "嵌入元数据到图片", - "embed_workflow": "嵌入工作流信息", - "overwrite_existing": "覆盖已存在的文件", - "create_backup": "为覆盖的文件创建备份", - "optimize_size": "优化文件大小" - }, - "outputs": { - "images": "保存的图片" - } - } -} diff --git a/locales/zh-CN/main.json b/locales/zh/main.json similarity index 100% rename from locales/zh-CN/main.json rename to locales/zh/main.json diff --git a/locales/zh/nodeDefs.json b/locales/zh/nodeDefs.json new file mode 100644 index 0000000..4021374 --- /dev/null +++ b/locales/zh/nodeDefs.json @@ -0,0 +1,185 @@ +{ + "SmartFolderManager": { + "display_name": "智能文件夹管理", + "description": "智能文件夹管理器 - 负责管理文件夹结构和元数据收集", + "inputs": { + "images": { + "name": "图像", + "tooltip": "输入图片,用于提取尺寸信息并传递给保存节点" + }, + "base_folder": { + "name": "基础文件夹", + "tooltip": "基础文件夹路径,可以是相对路径或绝对路径" + }, + "create_subfolders": { + "name": "创建子文件夹", + "tooltip": "是否自动创建子文件夹" + }, + "folder_structure": { + "name": "文件夹结构", + "tooltip": "选择文件夹组织方式", + "options": { + "date_only": "仅日期", + "model_only": "仅模型", + "date_model": "日期+模型", + "model_date": "模型+日期", + "custom": "自定义" + } + }, + "date_format": { + "name": "日期格式", + "tooltip": "日期格式: yyyy=年 MM=月 dd=日 hh=时 mm=分 ss=秒" + }, + "include_time": { + "name": "包含时间", + "tooltip": "是否在日期中包含时间" + }, + "model_source": { + "name": "模型来源", + "tooltip": "模型信息来源:auto=从元数据/外部输入获取,manual=手动选择", + "options": { + "auto": "自动获取", + "manual": "手动选择" + } + }, + "manual_model_name": { + "name": "手动模型名", + "tooltip": "手动选择模型(仅在model_source=manual时生效)" + }, + "model_input": { + "name": "模型输入", + "tooltip": "从模型加载器节点输入(仅在model_source=auto时生效)" + }, + "seed": { + "name": "随机种", + "tooltip": "种子值(手动输入或连接外部节点)" + }, + "positive_prompt": { + "name": "正向提示词", + "tooltip": "正向提示词(手动输入或连接外部节点)" + }, + "negative_prompt": { + "name": "负向提示词", + "tooltip": "负向提示词(手动输入或连接外部节点)" + }, + "custom_subfolder": { + "name": "自定义子文件夹", + "tooltip": "自定义子文件夹名称" + }, + "model_short_name": { + "name": "模型短名称", + "tooltip": "使用模型短名称(去除扩展名)" + }, + "prompt_max_length": { + "name": "提示词最大长度", + "tooltip": "提示词文件夹名最大长度" + }, + "sanitize_names": { + "name": "清理文件名", + "tooltip": "清理文件名中的非法字符" + } + }, + "outputs": { + "0": { + "name": "图像", + "tooltip": "传递的图片数据" + }, + "1": { + "name": "文件夹路径", + "tooltip": "生成的文件夹路径" + }, + "2": { + "name": "元数据JSON", + "tooltip": "提取的元数据JSON" + } + } + }, + "SmartImageSaver": { + "display_name": "智能图片保存", + "description": "智能图片保存器 - 负责图片保存、格式转换和压缩", + "inputs": { + "images": { + "name": "图像", + "tooltip": "要保存的图片(通常来自SmartFolderManager)" + }, + "folder_path": { + "name": "文件夹路径", + "tooltip": "保存路径(来自SmartFolderManager)" + }, + "metadata_json": { + "name": "元数据JSON", + "tooltip": "元数据JSON(来自SmartFolderManager)" + }, + "filename_prefix": { + "name": "文件名前缀", + "tooltip": "文件名前缀" + }, + "file_format": { + "name": "文件格式", + "tooltip": "图片格式", + "options": { + "png": "PNG格式", + "jpeg": "JPEG格式", + "webp": "WebP格式", + "bmp": "BMP格式", + "tiff": "TIFF格式" + } + }, + "preview_mode": { + "name": "预览模式", + "tooltip": "保存模式", + "options": { + "save_and_preview": "保存并预览", + "preview_only": "仅预览", + "save_only": "仅保存" + } + }, + "add_timestamp": { + "name": "添加时间戳", + "tooltip": "在文件名中添加时间戳" + }, + "add_counter": { + "name": "添加计数器", + "tooltip": "添加计数器(多张图片时)" + }, + "counter_start": { + "name": "计数器起始值", + "tooltip": "计数器起始值" + }, + "counter_padding": { + "name": "计数器填充", + "tooltip": "计数器位数(补零)" + }, + "jpeg_quality": { + "name": "JPEG质量", + "tooltip": "JPEG质量(1-100)" + }, + "webp_quality": { + "name": "WebP质量", + "tooltip": "WebP质量(1-100)" + }, + "webp_lossless": { + "name": "WebP无损", + "tooltip": "WebP无损压缩" + }, + "png_compression": { + "name": "PNG压缩", + "tooltip": "PNG压缩级别(0-9)" + }, + "embed_metadata": { + "name": "嵌入元数据", + "tooltip": "嵌入元数据到图片" + }, + "embed_workflow": { + "name": "嵌入工作流", + "tooltip": "嵌入工作流信息" + } + }, + "outputs": { + "0": { + "name": "图像", + "tooltip": "保存的图片" + } + } + } +} \ No newline at end of file diff --git a/src/SmartSaveImage/nodes/folder_manager.py b/src/SmartSaveImage/nodes/folder_manager.py index fef2d69..8f46977 100644 --- a/src/SmartSaveImage/nodes/folder_manager.py +++ b/src/SmartSaveImage/nodes/folder_manager.py @@ -13,6 +13,11 @@ class SmartFolderManager: RETURN_TYPES = ("IMAGE", "STRING", "STRING") RETURN_NAMES = ("images", "folder_path", "metadata_json") FUNCTION = "generate_path" + + # 为翻译插件提供类名标识 + @classmethod + def get_comfy_class(cls): + return "SmartFolderManager" def __init__(self): self.metadata_extractor = MetadataExtractor() diff --git a/src/SmartSaveImage/nodes/image_saver.py b/src/SmartSaveImage/nodes/image_saver.py index 34f90b5..43fc340 100644 --- a/src/SmartSaveImage/nodes/image_saver.py +++ b/src/SmartSaveImage/nodes/image_saver.py @@ -17,6 +17,11 @@ class SmartImageSaver: RETURN_TYPES = ("IMAGE",) RETURN_NAMES = ("images",) FUNCTION = "save_images" + + # 为翻译插件提供类名标识 + @classmethod + def get_comfy_class(cls): + return "SmartImageSaver" def __init__(self): self.metadata_builder = MetadataBuilder()