EnglishУкраїнськаGitHub

AI-переклад

Мова: English · Українська

Picoripi розмовляє з LLM через Settings → AI Translation. Збірка глосарія — Settings → AI Glossary (опційно той самий ключ). Рекомендований локальний проксі: 5. Gemini Web2API.

Обробники: handlers/translation_handler.py, handlers/translation/. Провайдери: core/translation/providers.py. Типові значення: core/translation/config.py. Промпти: Edit Prompts JSON і translation_prompts/prompts.json плагіна.

Файли промптів зливаються по ключах, пізніші перекривають раніші: translation_prompts/prompts.json → plugins/common/defaults/prompts.json → plugins/<name>/translation_prompts/prompts.json → копія-перевизначення проєкту або користувача. Файл плагіна, що містить лише розділ translation, все одно отримує розділи glossary, glossary_occurrence_update та mempalace зі спільного файлу (core/translation/prompt_files.py).

Прохід перевірки — необов'язковий другий запит на кожен фрагмент у тій самій розмові, що й переклад: модель бачить ті самі правила, рядки глосарію, мовців, адресатів і сцену, свою чернетку та прохання виправити лише справжні помилки (зміст, неперекладені слова, терміни глосарію, рід і відмінок, ти/ви, описки, кальки). Вона повертає лише виправлені рядки з причиною (у журналі налагодження); виправлення проходить ті самі перевірки, що й чернетка, а все, що їх не пройшло, лишає чернетку. Типово увімкнений; "review_enabled": false у конфігурації перекладу вимикає його, а "review_model" задає для нього іншу модель. Він додає один запит на кожен фрагмент. Виміряно на вичитаному Minish Cap (2026-10-04): він змінює приблизно один рядок із дванадцяти й у двох випадках із трьох робить краще.

Одне джерело — один переклад у межах прогону. Перед початком прогону блока (або проєкту) рядки з точно однаковим текстом згортаються: один надсилається, решта отримує його переклад, коли фрагмент повертається. Два рядки згортаються лише тоді, коли збігається й усе інше, що визначає формулювання, — мовець, адресат, вікно, у яке текст має вміститися, відомості плагіна про рядок і ваші ручні перевизначення сюжету; тож репліка, яку вимовляють два різні персонажі, все одно перекладається двічі. Рядок, що вже має переклад, згортання не перезаписує — так само, як його не перезаписує модель. Щоб надсилати кожен рядок, задайте "fold_duplicates": false у конфігурації перекладу. Плагін може замінити в цьому тесті вікно і контекст перекладу власним контекстом (get_duplicate_context_for_string, D46): так роблять посібники 3DS, тож один абзац з однаковим текстом у двох посібниках перекладається один раз. Придатність перевіряється для кожного місця: перевірка розкладки плагіна (get_text_fit_problems_for_string) відхиляє місце, де текст не вміщається, і воно лишається неперекладеним після прогону (смуга стану показує кількість; перекладіть його або запустіть знову). Кожен прогін також веде пам'ять прогону: коли в пізнішому фрагменті трапляється рядок, що відрізняється від уже перекладеного лише тегами, регістром чи пробілами, запит містить already_translated_in_this_run (не більше 10 рядків), а моделі сказано зберігати формулювання. Пам'ять очищується на початку нового прогону; друга фаза режиму «спершу сюжет, потім решта» продовжує пам'ять першої.

Пам'ять перекладів серії. Проєкт, що має глосарії серії (вікі 8, Глосарії серії), записує себе в projects.json поруч із кожним із них (назва проєкту → його translation_memory.json) і при відкритті читає файли пам'яті інших проєктів із цього списку (core/translation/series_memory.py; читається раз у воркері завантаження, нічого не копіюється). Далі: ім'я чи окремий термін ніколи не береться з іншої гри; його перекладає глосарій серії (вікі 8, Fill Terms from the Glossary). Речення (більше двох слів, series_sentence_words) з іншої гри пропонується лише тоді, коли увімкнено Пропонувати речення, перекладені в інших іграх серії (Налаштування, сторінка AI; типово вимкнено). Текст має збігатися точно. Мовця порівнюють за англійським іменем; рядок без нього ніколи не стартує позначеним. Кожен запропонований рядок має прапорець у списку Речення з інших ігор серії: англійський текст, переклад з іншої гри і її назву, обидва імені мовців і причину. Безпечний збіг стартує позначеним, коли увімкнено Безпечні збіги починаються з позначкою (типово так); сумнівний (імена мовців різні чи відсутні, адресат різний, текст задовгий для цього вікна, теги не відповідають) стартує без позначки. Вибрати безпечні, Вибрати все і Очистити змінюють позначки. Застосувати вибрані записує лише позначені рядки як правки, які можна скасувати; рядок, що не пройшов перевірку ширини чи тегів, лишається без змін і йде до запиту AI. Нічого не застосовується автоматично. Запит фрагмента містить translated_in_other_games_of_the_series (не більше 10 рядків, кожен із project), запит одного рядка перелічує їх у TRANSLATION MEMORY з позначкою in <project>; а смужка над редактором каже Translated in : "…" з кнопкою Apply here. Та сама смужка каже The same text is in N other place(s) of this project, коли поточний текст має інші копії, а Apply to places with the same context записує поточний (або згаданий) переклад у кожне інше місце проєкту, де той самий текст сказано тим самим мовцем і у тому самому вікні (той самий тест, що й для згортання дублікатів) і текст вміщається у вікно; інші місця не змінюються, а рядок стану рахує їх. Правки незбережені, їх можна скасувати. Рядок іншої гри переноситься, коли обидві гри дають однаковий вид однаковим керуючим тегам у тому самому порядку (get_series_tag_map; наприклад розрив сторінки або ім'я, яке вставляє гра): його теги записуються синтаксисом цієї гри. Тег без відповідника блокує перенесення, а смуга пам'яті пояснює причину.

Пам'ять перекладів між прогонами. Кожен переклад, який Picoripi зберігає як резервну копію (saved_translations.json у теці проєкту, з ключем за позицією), запам'ятовується ще й за вихідним текстом у файлі translation_memory.json поруч. Коли прогін має перекласти рядок, для позиції якого збереженого перекладу немає, але такий самий текст уже перекладено й збережено деінде в проєкті, вікно Cached Translation пропонує і цей переклад — з позначкою (same text elsewhere) — після тієї самої перевірки розкладки, що й для відновлення за позицією: OK заповнює рядок без запиту, Translate Anew надсилає його моделі. Відновлюється лише точно такий самий текст. Текст, що трапляється в проєкті більше одного разу, пропонується лише тоді, коли збережений рядок мав того самого мовця, адресата й контекст (той самий тест, що й для згортання дублікатів); репліку іншого мовця перекладено наново, а рядок, збережений до цього правила, для такого тексту не пропонується, доки репліку не збережено знову. Плагін із власним контекстом повторів (D46) лишає такий рядок для його власного місця. У вікні кожен рядок має прапорець, позначений за замовчуванням: OK заповнює позначені рядки без запиту, рядок без позначки йде до моделі, а Translate Anew надсилає всі рядки моделі. Запит на переклад одного рядка додатково містить розділ TRANSLATION MEMORY (same source elsewhere) — до трьох збережених перекладів того самого тексту, включно з написаннями, що відрізняються лише тегами, регістром чи пробілами, — щоб модель зберегла формулювання; запит на варіанти цього розділу не отримує. Проєкт, збережений до появи цієї можливості, будує пам'ять із наявних збережених перекладів, коли вона вперше знадобиться. Файл > Оновити пам'ять перекладу з контекстом дає рядкам, збереженим до цього правила, їхній контекст (мовця, адресата і ключ згортання) зі збережених перекладів, тож повторюваний текст знову пропонується. Дія виконується у фоновому потоці, її можна скасувати; попередня пам'ять зберігається як translation_memory.before_context.json, а Файл > Повернути пам'ять перекладу до оновлення контексту повертає її.

Сталі написи інтерфейсу. Повторювані слова інтерфейсу — OK, Yes, No, Back — покладіть у розділ глосарію з назвою UI. Рядок гри, який увесь є точно таким терміном (або одним із його псевдонімів; той самий регістр, без зайвих символів), заповнюється перекладом із глосарію ще до початку прогону: без запиту і без запитань. Рядок, що вже має переклад, не чіпається; переклад, який не вкладається в розкладку рядка, силоміць не вставляється; запис, переклад якого ще є непідтвердженою пропозицією ШІ, нічого не фіксує. Інші розділи можна назвати в конфігурації перекладу: "fixed_output_sections": ["UI", "Menu"]; порожній список вимикає цю можливість.

Розкладка відповіді. Модель пише слова, Picoripi їх верстає. Кожен рядок має клас розкладки (core/translation/layout_class.py): його називає плагін (layout_class у get_translation_context_for_string, за типом вікна) або рушій вгадує з оригіналу: кілька коротких рядків без розділових знаків у кінці — це lines (меню, назва, вибір, титри), усе інше — prose. Запит каже, який саме (layout_class: "lines" на елементі; prose — типово) і дає бюджет у літерах замість пікселів: max_chars_per_line, виміряний українською абеткою у шрифті гри (lines_per_window × max_chars_per_line на сторінку). Для prose модель може писати кожну сторінку суцільним текстом; при застосуванні відповіді слова кожної сторінки переносить верстальник (core/typesetter.py) зі шрифтом гри: заповнює до цільової ширини (warn_width), ніколи не лишає «і», «в», «на» та інші одно- і дволітерні службові слова в кінці рядка, ніколи не лишає одне слово на останньому рядку, а за ціль виходить лише до межі (max_width), коли цього вимагають ці правила. Той самий верстальник розбиває надто широкий рядок в автовиправленні ширини. Рядок класу lines зберігає рядки моделі як є. Відповідь і далі має зберегти порожні рядки (розриви сторінок) і кінцевий перенос, інакше її чанк валиться. Прохід скорочення: після чернетки (і перевірки) Picoripi верстає кожен елемент; prose-елемент, якому після цього треба більше вікон, ніж в оригіналі, або lines-елемент із рядком, ширшим за межу, один раз повертається до моделі в тій самій розмові з shorten_by_letters (скільки літер, виміряно) і причиною; скорочений рядок береться лише тоді, коли влазить краще, інакше лишається чернетка. "shorten_enabled": false у конфігурації перекладу вимикає прохід. Підсумок прогону рахує layout: N did not fit, M shortened. Дві ширини типу вікна — його ціль і межа; плагін, який знає лише одну з них, задає width_tolerance_percent у config.json (типово 5), і друга виводиться.

Запит на один рядок також містить рядок Addressee:, коли плагін знає, до кого звернено репліку, — ту саму відомість, що й елемент пакетного запиту.

Форми звертання (ти/ви). Tools → Forms of Address... — невелика таблиця, збережена в проєкті (address_forms у метаданих .uiproj, core/address_forms.py): Characters з рисами вільними словами (child, adult, elder, royalty, deity, male, female...; список починається з імен, які показує поле Speaker), Rules між рисами в порядку пріоритету (типово: будь-хто → royalty, deity або elder на ви, далі child → adult на ви, adult → child на ти, child → child на ти; * — будь-хто) і Pairs (один мовець до одного адресата), які сильніші за будь-яке правило. Для рядка, адресата якого називає плагін, перша збіжна пара чи правило стає address_form: "formal" або "informal" в елементі пакета і рядком Address form: у запиті одного рядка; перевірочний прохід звіряє ти/ви з ним. Немає збігу — немає поля: модель вирішує, як раніше. Налаштуйте раз на старті проєкту — працює для кожного наступного прогону.


Увімкнути провайдера

Settings → AI Translation

Поле Значення
Target Language напр. Ukrainian, Spanish, German
Active Provider Disabled · OpenAI Compatible · Ollama Chat · Gemini · Perplexity
Preset Save Preset / Delete Preset (збереження з наявним ім’ям перезаписує)
Parallel Requests 1–16, типово 6. Паралельні запити під час пакетного/чанкованого перекладу
Test Provider Один крихітний запит. Неактивне, поки провайдер Disabled

OpenAI Compatible (для Web2API):

Поле Нотатки
API Key Bearer-токен (поле пароля)
API Key Env Var типове ім’я OPENAI_API_KEY (також з .env через settings_manager)
Endpoint плейсхолдер містить https://api.openai.com/v1 або http://127.0.0.1:8081/v1
Model плейсхолдер gpt-4o-mini або gemini-3.7-flash
Temperature 0.0–2.0, типово 0.0
Max Output Tokens 0 = Provider default
Request Timeout 1–600 с, типово 60. З Web2API ставте 180 s

Ollama Chat API: Base URL http://localhost:11434, Model llama3, таймаут типово 120 с, Keep Alive.

Google Gemini API: Base URL необов’язковий (http://127.0.0.1:8081/v1 або порожньо для API Google), API Key необов’язковий для локального проксі, Model gemini-3.7-flash.

Perplexity API: Bearer-токен, Base URL https://api.perplexity.ai, плейсхолдер моделі sonar-medium-8x7b-chat.

Edit Prompts JSON редагує збережені шаблони. Для разової правки Ctrl-клік AI Translate або AI Variation.

Global → Show prompt editor before AI requests відкриває редактор на кожному запиті.

У редакторі системний промпт закінчується рядком --- REQUEST RULES (added by Picoripi …) ---, а далі йдуть сталі правила для цього типу запиту (формат відповіді, розмітка рядків, глосарій, теги, необов’язкові поля контексту). Вони однакові для кожного фрагмента прогону, тож провайдер може їх кешувати; їх можна змінити на один запуск, але при збереженні промпта зберігається лише частина над цим рядком. Повідомлення користувача містить заголовок і дані: для блока — layout_defaults один раз і по одному рядку на кожну репліку лише з тим, що властиве саме їй.

Типовий конфіг provider — "disabled", поки не виберете.


Переклад у редакторі

AI Translate (над Editable):

Якщо вже йде задача: діалог AI Busy.

Нічого не вибрано (physical_block_idx == -1): кнопка нічого не робить.

AI Variation:

AI Chat (тулбар, Ctrl+Shift+C): вікно AI Chat. Обговорити переклади. Ctrl+Enter / Send надсилає; Enter — новий рядок. Опційно Web Search. Містить кнопку Retry («Повторити», Ctrl+Shift+R) для миттєвого перезапуску останньої репліки (зі зміною моделі/налаштувань або після збою мережі) без повторного введення тексту, кнопку Stop під час генерації, чергу повідомлень із бейджем [In Queue] та дію Reset Context («Скинути контекст»). Чат не пише в Editable; скопіюйте пропозицію самі або скористайтесь AI Translate.


Конвеєри та режими пакетного перекладу

Пакетний переклад можна запустити з головного тулбара (кнопка AI), заголовка дерева блоків, пункту Tools → AI Batch Translation ➔ або кроку 5 Майстра локалізації. Це відкриває діалогове вікно AI Batch Translation Dialog (AIBatchTranslationDialog).

Доступні режими

  1. Translate Story First (Chronological): - Використовує core/translation/block_classifier.py та зіставлення зі скриптом MemePalace для виділення реплік основного сюжету. - Перекладає рядки в хронологічному порядку, тож сюжетний текст готовий раніше за допоміжні блоки.
  2. Translate Remaining Blocks (Semantic & System): - Перекладає решту блоків інтерфейсу, меню, інвентарю, крамниць і міні-ігор. - Використовує той самий глосарій і контекст рядка, що й будь-який інший прогін. Більше нічого з фази 1 не переноситься: узгодженість із сюжетом дають глосарій і вже перекладені сусідні рядки.
  3. Run Full Pipeline (Story ➔ Semantic): - Автоматично виконує фазу 1, а потім одразу фазу 2 в єдиному багатоетапному проході.
  4. Translate All Blocks (Chronological Legacy): - Об'єднує всі блоки в єдиний хронологічний таймлайн і перекладає суцільним потоком.

Мультиагентний консиліум перекладу

Під час пакетного перекладу обробка реплік виконується спільною взаємодією кількох агентів ШІ: - Основний перекладач: генерує варіанти тексту з урахуванням лімітів ширини та керівних тегів. - Вбудований арбітр / редактор (Arbiter/Editor): агент-супервізор, який перевіряє термінологію за активним глосарієм, коригує фразування та стежить за єдністю тону персонажів перед збереженням перекладу.

Що потрапляє в промпт

Рушій не хардкодить словник гри. Плагін може додати (get_translation_context_for_string):

Ключ Ефект у промпті
window_type Window Type: <value>
content_role Content Role: <value>
role_instruction вставляється дослівно (плагін сам учить модель свої ролі)
has_speaker False пропускає пошук спікера
glossary_section секція для нового терміна з цього рядка
force_glossary рядок мусить дати запис глосарія

Плюс спікер (після Merge Speakers), входження глосарія (далі, з нижчим пріоритетом, рядки зв'язаного глосарію серії для термінів, яких немає в глосарії проєкту — 8), сцена MemePalace якщо зібрана, опційно get_ai_flow_context_for_string / get_ai_flow_overview.

Як прогін ділиться на запити. Один запит містить щонайбільше 12 рядків. Рядки однієї сцени MemePalace їдуть разом; у межах сцени (і серед рядків без сцени) репліки однієї розмови — як про неї повідомляє плагін через get_ai_flow_group_for_string — лишаються в одному запиті, коли вміщаються, тож запитання не відокремлюється від відповідей, а вибір — від варіантів. Розмова ріжеться лише тоді, коли вона сама довша за 12 реплік. Плагіни без цього гачка отримують звичайний поділ за кількістю. Переклад, розпочатий до цієї версії, продовжується з тим поділом, з яким його було почато.

Мовно-залежні директиви транскрипції

Системні та плагінні промпти підтримують блоки умовних директив за мовою перекладу: [IF_TARGET_LANG: <Language>]...[/IF_TARGET_LANG]. Коли цільова мова збігається (наприклад, Ukrainian), директиви розгортаються, надаючи моделі суворі академічні правила практичної транскрипції та транслітерації: - Англійський проривний звук G передається як українська Ґ (Ganon -> Ґанон, Goron -> Ґорон, Gengar -> Ґенґар), тоді як придиховий H передається як Г (Hyrule -> Гайрул, Hogwarts -> Гоґвортс). - Спільний корінь Hy- [haɪ] у всесвіті Zelda послідовно уніфікується через Г та дифтонг ай: Hyrule -> Гайрул, Hylia -> Гайлія, Hylian -> гайлійський / гайлієць (зокрема всі похідні назви, істоти й риби: Lake Hylia -> озеро Гайлія, Hylian Shield -> гайлійський щит, Hyrule Bass -> гайрульський окунь, Hylian Loach -> гайлійський в'юн). Категорично заборонені російські кальки «Хайрул» та розсинхронні читання «Гілія / Хілія / гілійці». - Японські імена та терміни передаються за академічною системою Коваленка (shi -> сі, chi -> ті, tsu -> цу, ji -> дзі, дзвінкий проривний g -> ґ) з категоричним неприйняттям поліванівщини через російське посередництво (Satoshi -> Сатосі, Shigeru -> Сіґеру, Fuji -> Фудзі). Якщо обрано іншу цільову мову (наприклад, Spanish), такі блоки автоматично вирізаються, зберігаючи промпти абсолютно чистими від непотрібної кирилиці (вимога AUD-L1).

Контекст референсних перекладів

Коли завантажено зовнішні патчі або розпаковані мультимовні ROM, відповідні репліки з усіх доступних референсних мов додаються до промпту у блоці REFERENCE TRANSLATIONS (для окремого рядка) або у полі reference_translations (для пакетного перекладу).

Рушій встановлює чіткі межі роботи моделі: - Первинне джерело: переклад завжди здійснюється з оригінального тексту (Input text (Original source): або поле "text"). - Виключно контекст: референсні переклади слугують виключно контекстними свідченнями для уточнення змісту, інтонації репліки та статі персонажа з інших релізів чи локалізацій. - Сувора заборона: промпт прямо забороняє перекладати з будь-якої референсної мови чи копіювати референсний переклад як цільовий результат. - Скільки: запит на один рядок показує всі завантажені референсні мови. Пакетний запит типово надсилає всі завантажені мови для кожного рядка; щоб обмежити кількість, задайте "max_reference_languages" у блоці налаштувань перекладу (першими йдуть мови, завантажені раніше; 0 — не надсилати). Російська, якщо завантажена, завжди йде останньою, і промпт позначає її як найменш надійний орієнтир, тож обмеження відкидає її першою.


AI глосарія

Settings → AI Glossary

Поле Нотатки
Provider OpenAI Compatible · Ollama · Gemini
API Key
Use API key from AI Translation
Model
Text Chunk Size 1000–32000 символів
Parallel Requests 1–16. Ширше за кількість акаунтів проксі лише ставить зайве в чергу на кулдаун
Retry Delay 0–600 с. Серверний Retry-After перемагає

Запуск пайплайну: Tools → Prepare Glossary… або крок майстра Prepare and enrich the glossary. Див. 8.


Parallel Requests

translation_workers_spin / glossary_workers_spin. Проксі з ротацією кількох акаунтів (Web2API) можуть 4–8. Один акаунт: ставте 1.


Чого не робити