From 32794fa30f14fc70e01c52ca2585ea56cf553903 Mon Sep 17 00:00:00 2001 From: liuqianhonga Date: Thu, 2 Jan 2025 15:22:47 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0String=20Translate=E8=8A=82?= =?UTF-8?q?=E7=82=B9=EF=BC=8CString=20List=E6=94=AF=E6=8C=81=E5=BE=AA?= =?UTF-8?q?=E7=8E=AF=E9=80=89=E5=8F=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 95 ++++++++++++++++++++++++++----------- __init__.py | 4 +- nodes/string_list.py | 110 +++++++++++++++++++++++++++++++------------ 3 files changed, 151 insertions(+), 58 deletions(-) diff --git a/README.md b/README.md index bd56050..b050c52 100644 --- a/README.md +++ b/README.md @@ -73,56 +73,63 @@ arg1: "世界" ## StringList 节点使用说明 -StringList 节点允许你灵活地选择和翻译字符串。你可以通过手动输入、随机选择或指定编号选择字符串,并可选地将其翻译为英文。 +StringList 节点允许你灵活地选择和翻译字符串。你可以通过手动输入、随机选择、顺序循环或指定编号选择字符串,并可选地将其翻译为英文。 ### 节点参数 -- **random_select_count** (必需):随机选择字符串的数量。特殊值: +- **p1_select_by_numbers** (可选):最高优先级,通过输入序号(如 "1,3,5")选择指定位置的字符串 +- **p2_select_sequential** (可选):第二优先级,布尔值,默认为 `False`。启用后,每次调用按顺序返回下一个字符串,到达列表末尾后自动从头开始 +- **p3_select_random_count** (必需):最低优先级,随机选择字符串的数量。特殊值: - `-1`:返回所有输入字符串 - `0`:返回空列表 - `1-10`:随机选择指定数量的字符串 -- **selected_numbers** (可选):指定要选择的字符串编号,多个编号用逗号分隔,如"1,3,5"。当此字段有值时,`random_select_count` 失效 - **translate_output** (可选):布尔值,默认为 `False`。启用后,将选定的字符串从自动检测的语言翻译为英文 - **string1** - **string10** (必需):多行字符串输入字段,用于手动输入字符串 - **string_list** (可选):额外的字符串列表输入,用于合并外部字符串列表 ### 使用示例 -1. 随机选择字符串: +1. 按序号选择字符串(最高优先级): ```python -random_select_count: 3 -translate_output: False +p1_select_by_numbers: "1,3,5" string1: "你好" string2: "世界" string3: "欢迎" +string4: "使用" +string5: "ComfyUI" +输出: ["你好", "欢迎", "ComfyUI"] +``` + +2. 顺序循环选择(第二优先级): +```python +p2_select_sequential: True +string1: "第一个" +string2: "第二个" +string3: "第三个" +第一次输出: ["第一个"] +第二次输出: ["第二个"] +第三次输出: ["第三个"] +第四次输出: ["第一个"] # 自动从头开始 +``` + +3. 随机选择字符串(最低优先级): +```python +p3_select_random_count: 3 +string1: "你好" +string2: "世界" +string3: "欢迎" +string4: "使用" +string5: "ComfyUI" 输出: 随机选择3个字符串 ``` -2. 指定编号选择字符串: +4. 启用翻译: ```python -selected_numbers: "1,3" +p1_select_by_numbers: "1,2" translate_output: True string1: "你好" string2: "世界" -string3: "欢迎" -输出: ["Hello", "Welcome"] -``` - -2. 指定编号选择字符串: -```python -selected_numbers: "1,3" -translate_output: False -string1: "你好" -string2: "世界" -string3: "欢迎" -输出: ["你好", "欢迎"] -``` - -3. 使用外部字符串列表: -```python -random_select_count: 2 -string_list: ["额外1", "额外2"] -输出: 随机选择2个字符串并合并外部列表 +输出: ["hello", "world"] ``` ## StringListFromCSV 节点使用说明 @@ -410,3 +417,37 @@ target_type: "DICT" - 不会返回默认值,确保数据的准确性 - 对于LIST类型,空字符串会返回空列表 - 对于DICT类型,输入必须是有效的JSON格式字符串 + +## String Translate 节点使用说明 + +String Translate 节点提供单独的字符串翻译功能,可以将输入的字符串翻译为英文。 + +### 节点参数 + +- **string** (必需):要翻译的字符串 +- **translate_output** (必需):布尔值,默认为 `False`。控制是否执行翻译: + - `False`:直接返回原字符串 + - `True`:将字符串翻译为英文 + +### 使用示例 + +1. 基础翻译: +```python +string: "你好,世界" +translate_output: True +输出: "Hello, world" +``` + +2. 不执行翻译: +```python +string: "你好,世界" +translate_output: False +输出: "你好,世界" +``` + +### 特点 + +- 支持自动语言检测 +- 使用必应翻译服务 +- 适合单个字符串的快速翻译 +- 与 StringList/StringListFromCSV 节点的翻译功能相同 diff --git a/__init__.py b/__init__.py index f7b2388..eb066c4 100644 --- a/__init__.py +++ b/__init__.py @@ -1,5 +1,5 @@ from .nodes.string_formatter import StringFormatter -from .nodes.string_list import StringList, StringListFromCSV, StringListToCSV, JsonToCSV +from .nodes.string_list import StringTranslate, StringList, StringListFromCSV, StringListToCSV, JsonToCSV from .nodes.show_translate_string import ShowTranslateString from .nodes.string_matcher import StringMatcher from .nodes.time_formatter import TimeFormatter @@ -7,6 +7,7 @@ from .nodes.string_converter import StringConverter NODE_CLASS_MAPPINGS = { "StringFormatter": StringFormatter, + "StringTranslate": StringTranslate, "StringList": StringList, "StringListFromCSV": StringListFromCSV, "StringListToCSV": StringListToCSV, @@ -19,6 +20,7 @@ NODE_CLASS_MAPPINGS = { NODE_DISPLAY_NAME_MAPPINGS = { "StringFormatter": "🐟String Formatter", + "StringTranslate": "🐟String Translate", "StringList": "🐟String List", "StringListFromCSV": "🐟String List From CSV", "StringListToCSV": "🐟String List To CSV", diff --git a/nodes/string_list.py b/nodes/string_list.py index 15450ac..e970375 100644 --- a/nodes/string_list.py +++ b/nodes/string_list.py @@ -6,11 +6,9 @@ from ..translation_utils import TranslationUtils class BaseStringList: """Base class for string list operations""" - - RETURN_TYPES = ("LIST", "STRING",) - RETURN_NAMES = ("string_list", "strings",) - FUNCTION = "process" - CATEGORY = "String Helper" + + def __init__(self): + self.current_index = 0 @staticmethod def get_encoding(csv_path): @@ -53,7 +51,7 @@ class BaseStringList: Args: csv_file: Path to the CSV file - rows_to_write: List of dictionaries with keys 'string', 'zh'/'translate_string', and 'tags' + rows_to_write: List of dictionaries with keys 'string', 'zh', and 'tags' append_mode: Whether to append to existing file check_duplicates: Whether to check and skip duplicate strings @@ -127,27 +125,44 @@ class BaseStringList: print("Invalid number format. Please use comma-separated numbers (e.g., '1,3,5')") return [] - def process_string_selection(self, input_strings, random_select_count, selected_numbers, translate_output, string_list=None): - """Process string selection with common logic""" + def process_string_selection(self, input_strings, p3_select_random_count, p1_select_by_numbers, translate_output, p2_select_sequential=False, string_list=None): + """Process string selection with common logic + + Args: + input_strings: List of input strings to select from + p1_select_by_numbers: Priority 1 - Select strings by their numbers (comma-separated) + p2_select_sequential: Priority 2 - Select strings sequentially + p3_select_random_count: Priority 3 - Number of strings to select randomly + translate_output: Whether to translate the selected strings + string_list: Optional additional strings to append + """ # Early return if no input strings if not input_strings: return ([], []) # Process string selection - if selected_numbers.strip(): - # Use selected numbers if provided - selected_input_strings = self.get_selected_strings(input_strings, selected_numbers) + if p1_select_by_numbers.strip(): + # Use selected numbers if provided (highest priority) + selected_input_strings = self.get_selected_strings(input_strings, p1_select_by_numbers) + elif p2_select_sequential: + # Use sequential selection if enabled (second priority) + if not input_strings: + selected_input_strings = [] + else: + selected_input_strings = [input_strings[self.current_index]] + # Update index for next selection + self.current_index = (self.current_index + 1) % len(input_strings) else: - # Otherwise use random selection - if random_select_count == -1: + # Otherwise use random selection (lowest priority) + if p3_select_random_count == -1: # Use all input strings selected_input_strings = input_strings - elif random_select_count == 0: + elif p3_select_random_count == 0: # Select none selected_input_strings = [] else: # Randomly select specified number of strings - count = min(random_select_count, len(input_strings)) + count = min(p3_select_random_count, len(input_strings)) selected_input_strings = random.sample(input_strings, count) # Combine with optional string_list if provided @@ -164,23 +179,46 @@ class BaseStringList: # Return the same list for both outputs return (final_strings, final_strings) +class StringTranslate(BaseStringList): + @classmethod + def INPUT_TYPES(s): + return { + "required": { + "translate_output": ("BOOLEAN", {"default": False}), + "string": ("STRING", {"multiline": True}), + } + } + + RETURN_TYPES = ("STRING",) + RETURN_NAMES = ("string",) + FUNCTION = "process_string" + CATEGORY = "String Helper" + + def process_string(self, string, translate_output): + if translate_output: + final_strings = self.translate_strings(string) + return (final_strings,) + return (string,) class StringList(BaseStringList): @classmethod def INPUT_TYPES(cls): return { "required": { - "random_select_count": ("INT", { + "p1_select_by_numbers": ("STRING", { + "default": "", + "placeholder": "Priority 1: Comma-separated numbers (e.g. 1,3,5)" + }), + "p2_select_sequential": ("BOOLEAN", { + "default": False, + }), + "p3_select_random_count": ("INT", { "default": -1, "min": -1, "max": 10, "step": 1, "display": "number" }), - "selected_numbers": ("STRING", { - "default": "", - "placeholder": "e.g. 1,3,5 (leave empty to use random_select_count)" - }), "translate_output": ("BOOLEAN", { "default": False, }), @@ -240,15 +278,17 @@ class StringList(BaseStringList): } } + RETURN_TYPES = ("LIST", "STRING",) + RETURN_NAMES = ("string_list", "strings",) OUTPUT_IS_LIST = (False, True) FUNCTION = "process" CATEGORY = "String Helper" IS_CHANGED = True - def process(self, random_select_count, selected_numbers, translate_output, string1, string2, string3, string4, string5, string6, string7, string8, string9, string10, string_list=None): + def process(self, p1_select_by_numbers, p2_select_sequential, p3_select_random_count, translate_output, string1, string2, string3, string4, string5, string6, string7, string8, string9, string10, string_list=None): # Create a list of all strings from inputs, including empty ones input_strings = [string1, string2, string3, string4, string5, string6, string7, string8, string9, string10] - return self.process_string_selection(input_strings, random_select_count, selected_numbers, translate_output, string_list) + return self.process_string_selection(input_strings, p3_select_random_count, p1_select_by_numbers, translate_output, p2_select_sequential, string_list) class StringListFromCSV(BaseStringList): @@ -268,18 +308,21 @@ class StringListFromCSV(BaseStringList): "multiline": False, "placeholder": "Filter by tags (comma-separated)" }), - "random_select_count": ("INT", { + "p1_select_by_numbers": ("STRING", { + "default": "", + "multiline": False, + "placeholder": "Priority 1: Comma-separated numbers (e.g. 1,3,5)" + }), + "p2_select_sequential": ("BOOLEAN", { + "default": False, + }), + "p3_select_random_count": ("INT", { "default": -1, "min": -1, "max": 999999, "step": 1, "display": "number" }), - "selected_numbers": ("STRING", { - "default": "", - "multiline": False, - "placeholder": "Comma-separated numbers (e.g., 1,3,5)" - }), "translate_output": ("BOOLEAN", { "default": False, }), @@ -331,14 +374,21 @@ class StringListFromCSV(BaseStringList): return filtered_rows - def read_strings_from_csv(self, csv_file, use_translated, filter_tags, random_select_count, selected_numbers, translate_output, reuse_last_result, string_list=None): + def read_strings_from_csv(self, csv_file, use_translated, filter_tags, p1_select_by_numbers, p2_select_sequential, p3_select_random_count, translate_output, reuse_last_result, string_list=None): # If reusing last result and it exists, return it directly if reuse_last_result and self.last_result is not None: return self.last_result # Read and process strings input_strings = self.read_csv_file(csv_file, filter_tags, use_translated) - result = self.process_string_selection(input_strings, random_select_count, selected_numbers, translate_output, string_list) + result = self.process_string_selection( + input_strings, + p3_select_random_count, + p1_select_by_numbers, + translate_output, + p2_select_sequential, + string_list + ) # Save result for future reuse self.last_result = result