diff --git a/README.md b/README.md index 725c3f2..ba04a77 100644 --- a/README.md +++ b/README.md @@ -124,6 +124,27 @@ This mask is used internally by "Merge Image Tile", but it can also be useful as ## Miscellaneous Nodes + +### Translate Text + +Node which translates a string into English. The language to translate from is indicated with a +_language directive_ of the form `lang:xx` where xx is a 2-letter language code. Multiple +directives are allowed and change language for any text that comes after, until the next +directive. `lang:en` (the default) passes through text fragments untouched. Useful +for keywords, tags and such. + +Examples: +| Input | Output | +|:-|:-| +| lang:de eine modische handtasche aus grünem kunstleder | a fashionable handbag made of green suede | +| origami paperwork, lang:zh 狐狸和鹤, lang:en mountain view | origami paperwork, Fox and crane, mountain view | + +Translation happens entirely local, powered by [argosopentech/argos-translate](https://github.com/argosopentech/argos-translate): +* Install with `pip install argostranslate` or `pip install -r requirements.txt` +* Models are automatically downloaded on first use. + +There is also a [translation API](#api-translation) for immediate feedback in tool UI. + ### NSFW Filter Checks images for NSFW content using [Safety-Checker](https://huggingface.co/CompVis/stable-diffusion-safety-checker). Images which don't pass the check are blurred to @@ -134,12 +155,12 @@ Inputs: image and sensitivity (0.5 for explicit content only, 0.7+ to include pa **Important:** the filter isn't perfect. Some explicit content may slip through. -## API for model inspection - -There are various types of models that can be loaded as checkpoint, LoRA, ControlNet, etc. which cannot be used interchangeably. The following API helps to categorize and filter them. +## API extensions ### /api/etn/model_info +There are various types of models that can be loaded as checkpoint, LoRA, ControlNet, etc. which cannot be used interchangeably. This endpoint helps to categorize and filter them. + Lists available models with additional classification info. * Paramters: _none_ * Output: list of model files @@ -157,6 +178,16 @@ Lists available models with additional classification info. _Note: currently only supports checkpoints. May add other models in the future._ + +### /api/etn/translate/{lang}/{text} + +Translates `text` into English. `lang` is a 2-letter code indicating the language to translate +from. `text` may also contain _language directives_ to only translate some fragments. +See the [node documentation](#node-translate) for details. + +* Output: JSON string +* Example: `/api/etn/translate/de/eine%20modische%20Handtasche` -> `"a fashionable handbag"` + ## Installation Download the repository and unpack into the `custom_nodes` folder in the ComfyUI installation directory. diff --git a/api.py b/api.py index f5b947d..2f57896 100644 --- a/api.py +++ b/api.py @@ -111,7 +111,7 @@ if _server := getattr(server.PromptServer, "instance", None): try: language = request.match_info.get("lang", "en") text = request.match_info.get("text", "") - result = translate(text, language) + result = translate(f"lang:{language} {text}") return web.json_response(result) except Exception as e: return web.json_response(dict(error=str(e)), status=500) diff --git a/pyproject.toml b/pyproject.toml index 704de65..f64ba63 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [project] name = "comfyui-tooling-nodes" description = "Provides nodes and server API extensions geared towards using ComfyUI as a backend for external tools." -version = "1.2.0" +version = "1.3.0" license = "LICENSE" [project.urls] diff --git a/translation.py b/translation.py index 8787dfb..2e6eea9 100644 --- a/translation.py +++ b/translation.py @@ -23,7 +23,7 @@ def available_languages(): return [("NOT INSTALLED", "NOT INSTALLED")] -def translate(text: str, language: str): +def translate_chunk(text: str, language: str): if text.strip() == "": return text @@ -55,6 +55,11 @@ def translate(text: str, language: str): ) +def translate(text: str): + chunks = Chunk.parse(text) + return " ".join(translate_chunk(c.text, c.lang) for c in chunks) + + class Translate: @staticmethod def INPUT_TYPES(): @@ -65,9 +70,7 @@ class Translate: FUNCTION = "translate" def translate(self, text: str): - chunks = Chunk.parse(text) - translated = " ".join(translate(c.text, c.lang) for c in chunks) - return (translated,) + return (translate(text),) _lang_regex = re.compile(r"(lang:\w\w)")