Nodes/comfyui-AGSoft/📝💬AGSoft Dialogue Keeper
ComfyUI Node

📝💬AGSoft Dialogue Keeper

Machine translation is bad at dialogue — this node puts the original lines back

By Art-xmaster·Created about a year ago·Updated a day ago· 24
📝💬AGSoft Dialogue Keeper
    • text
    original_text
    translated_text
    template‹d›....‹/d› + markers
    tag_start<d>
    tag_end</d>
    markers" ", « », “ ”, ‘ ’, „ “, ‚ ‘, ‹ ›

    The one trick it exists for

    Run a story, a roleplay log, or a novel chapter through any machine translator and you get clean prose - and flat, lifeless dialogue. Every character suddenly talks like the same translation-service native speaker, and the names and turns of phrase you actually wanted kept in the original language are gone. 📝💬AGSoft Dialogue Keeper is a post-processor that fixes exactly that: give it the original text and the translation, and it finds every quoted or tagged line of dialogue and swaps the original wording back into the translated result. It's a find-and-replace surgeon, not a translator - no model, no API key, no GPU, runs in a millisecond.

    It ships in the comfyui-AGSoft pack, which is built around a Russian text-and-video workflow (the AGSoft Translate node alongside it translates via free web services). If you're localizing text where dialogue should stay in the source language, this is the node the pack was really made for. If you only translate plain paragraphs, you don't need it.

    How it works

    Under the hood it's plain string surgery with regex - zero magic. It scans original_text for spans wrapped in your chosen template tags and/or quote-pair markers, scans translated_text with the same pattern, then replaces each translated span with the matching original one. When both sides have the same number of dialogues it just pairs them in order. When counts differ (the translator merged or dropped a line), it warns in the console and tries to align by marker type instead - decent, but imperfect.

    The one design detail that looks like a bug but isn't: the template dropdown shows ‹d›....‹/d› with fancy single quotes instead of <d>....</d>. ComfyUI's dropdown eats angle brackets as HTML, so the author renders them HTML-safe. It means the same thing.

    The inputs that matter

    You only set two things for the basic case:

    • original_text (required) - the source text before translation. The node hunts here for the dialogue spans to copy back.
    • translated_text (required) - the translation. Everything stays as-is except the spans it recognizes as dialogue.

    Then the marking scheme, which is where the real choices live:

    • template - the dropdown. Default is ‹d›....‹/d› + markers, i.e. look for <d>...</d> tags and any quote pair. [Russian] variants tell you the intent: keep Russian dialogue in the English translation. markers only skips tags entirely; Custom tags uses your own tag_start/tag_end pair like [dialog][/dialog].
    • markers - the list of quote-pair delimiters. Defaults to the full quote zoo (" ", « », “ ”, ‘ ’, „ “, …) so whatever curly quotes your source uses get caught. You can add multi-character markers like << >> (or <<|>> when you need an explicit open/close).

    The single output is text - wire it into a Show Text node (this pack has 📝AGSoft Show Text and 👁️ AGSoft Show Any) or into whatever downstream step consumes your patched translation.

    Install

    The pack installs like any custom node, and this particular node has no extra dependencies - the whole thing is standard Python. The pack's requirements.txt only lists translators, and that's for AGSoft Translate, not this node.

    cd ComfyUI/custom_nodes
    git clone https://github.com/Art-xmaster/comfyui-AGSoft.git
    

    Then restart ComfyUI. Easier: ComfyUI Manager → search "comfyui-AGSoft" → Install. You'll find the node under AGSoft → Text. Note the README is mostly Russian, and extended docs live on the author's Telegram channel - that's a heads-up, not a blocker; the tooltips in the node are bilingual.

    Where people get burned

    Tag mode assumes your translation step keeps the <d>...</d> tags intact. Free web translators often strip or mangle markup, so if you get an unchanged output plus a console warning about "No dialogues matched," that's usually why - check whether the tags survived in the translated text, or switch to markers only.

    Quote mode has its own trap: if the translator "normalized" the quote characters (turned « » into " "), the original and translated spans no longer share a marker type and alignment falls back to fuzzy matching. Keep your markers list covering what the translation actually outputs, not just what your source uses.

    If either input is empty, or nothing matches, or anything throws, the node fails safe and returns the translation unchanged - which is polite, but means a silent no-op is the symptom to watch for when it looks like the node "did nothing." Check the ComfyUI console for the [AGSoftDialogueKeeper] warning lines; they tell you exactly which branch it took.

    CategoryAGSoft/Text

    Inputs (6)

    NameTypeDefaultDescription
    original_textSTRINGField original_text: original text before translation. The node searches this text for dialogues inside selected tags/markers and copies them back into the translated result. --- Поле original_text: исходный текст до перевода. Нода ищет в нём диалоги внутри выбранных тегов/маркеров и копирует их обратно в переведённый результат.
    translated_textSTRINGField translated_text: translated text. The main English translation is kept, but fragments matching dialogues are replaced by the original Russian fragments from original_text. --- Поле translated_text: переведённый текст. Основной английский перевод сохраняется, но фрагменты, признанные диалогами, заменяются русскими фрагментами из original_text.
    templateoptCOMBO‹d›....‹/d› + markersField template: dialogue marker template. The menu shows ‹d› instead of <d> (HTML-safe notation). Options: ‹d›....‹/d› = <d>....</d>, ‹d›[Russian]....‹/d› = <d>[Russian]....</d>, [d]....[/d], markers only (all symbol pairs from the markers field), combinations with + markers, Custom tags (uses tag_start, tag_end and markers). --- Поле template: шаблон маркеров диалогов. В меню ‹d› вместо <d> (HTML-безопасная запись). Варианты: ‹d›....‹/d› = <d>....</d>, ‹d›[Russian]....‹/d› = <d>[Russian]....</d>, [d]....[/d], markers only (все пары символов из поля markers), комбинации с + markers, Custom tags (использует tag_start, tag_end и markers).
    tag_startoptSTRING<d>Field tag_start: opening tag for Custom tags mode. Examples: <d>, [dialog], {{say}}. Works only together with tag_end. In preset templates this field is ignored. --- Поле tag_start: открывающий тег для режима Custom tags. Примеры: <d>, [dialog], {{say}}. Работает только вместе с tag_end. В пресетных шаблонах это поле игнорируется.
    tag_endoptSTRING</d>Field tag_end: closing tag for Custom tags mode. Examples: </d>, [/dialog], {{/say}}. Works only together with tag_start. In preset templates this field is ignored. --- Поле tag_end: закрывающий тег для режима Custom tags. Примеры: </d>, [/dialog], {{/say}}. Работает только вместе с tag_start. В пресетных шаблонах это поле игнорируется.
    markersoptSTRING" ", « », “ ”, ‘ ’, „ “, ‚ ‘, ‹ ›Field markers: list of symbol pairs that wrap dialogues. By default it contains quotes " ", « », “ ”, ‘ ’, but you can put any symbols or multi-character markers. Used by templates with + markers and by Custom tags. Write pairs separated by commas, spaces or new lines; for multi-character markers use space or vertical bar: << >> or <<|>>. In Custom tags an empty field means no markers; in preset templates an empty field uses the default list. --- Поле markers: список пар символов, оборачивающих диалоги. По умолчанию содержит кавычки " ", « », “ ”, ‘ ’, но можно вставлять любые символы и многозначные маркеры. Используется шаблонами с + markers и режимом Custom tags. Пишите пары через запятую, пробел или с новой строки; для многозначных маркеров используйте пробел или вертикальную черту: << >> или <<|>>. В Custom tags пустое поле означает без маркеров; в пресетных шаблонах пустое поле использует стандартный список.

    Outputs (1)

    NameTypeDescription
    textSTRING