Перевод игр нейросетью: локализация строк без сломанных тегов

Как перевести тысячи игровых строк так, чтобы не сломались плейсхолдеры, теги и вёрстка интерфейса: формат пакета, проверки, повторы и стоимость.

5 мин · · автоматизация · разработка

Нейросеть для перевода игр снимает большую часть ручной работы, но игровые строки — коварный материал. В реплике Hello, {player}! You found %d coins. модель легко «переведёт» имя переменной или потеряет %d, и игра вылетит или покажет пустое место. Ниже процесс, который переводит строки из JSON, CSV и PO-файлов и автоматически ловит поломки до того, как они попадут в билд.

Почему игровой текст переводить сложнее обычного

У игровых строк есть четыре особенности, которые портят автоматический перевод:

  1. Плейсхолдеры и теги. {name}, %s, %d, {{count}}, <b>…</b>, [color=red], \n. Их нельзя ни переводить, ни терять.
  2. Ограничения длины. Кнопка, рассчитанная на слово Play, не вместит Начать игру. Русский текст обычно длиннее английского.
  3. Нет контекста. Строка Run — это «Бежать», «Запустить» или «Забег»? Без подсказки модель выберет наугад.
  4. Единая терминология. Предмет Iron Sword должен называться одинаково в квестах, инвентаре и подсказках.

Все четыре решаются на уровне формата запроса, а не «умным» промптом.

Формат пакета: ID, контекст, лимит

Не отправляйте строки целыми файлами. Разбейте их на пакеты по 30–60 штук и передавайте как JSON-список с идентификатором, исходным текстом и подсказками:

bash
[
  {"id": "ui.play", "text": "Play", "context": "кнопка главного меню", "max_len": 12},
  {"id": "npc.smith.01", "text": "Need a hand, {player}?", "context": "кузнец, дружелюбный тон"},
  {"id": "item.sword", "text": "Iron Sword", "context": "название предмета"}
]

Поля context и max_len вы заполняете сами или выгружаете из движка. Даже короткая пометка вроде «кнопка» или «диалог героя» помогает модели выбрать нужное значение слова. В системный промпт добавьте правила и словарь:

bash
Ты переводишь игровые строки с английского на русский.
Правила:
- Верни JSON-список объектов {"id": ..., "text": ...} в том же порядке.
- Плейсхолдеры ({name}, %s, %d, {{x}}), теги (<b>, [color=red]) и \n копируй без изменений.
- Уважай max_len: если не помещается, сократи формулировку.
- Используй словарь терминов, не придумывай другие варианты.
Словарь: Iron Sword = Железный меч; Health = Здоровье

Словарь держите коротким и подставляйте в каждый пакет: он одинаково работает для всех строк и обеспечивает единые названия.

Скрипт: перевод пакета с проверкой

Пример на Python с официальным SDK openai (документация по клиенту: Python API). Адрес — https://api.zukko.pro/v1:

bash
import json, re
from openai import OpenAI

client = OpenAI(base_url="https://api.zukko.pro/v1", api_key="fetch_ваш_ключ")
SYSTEM = open("system.txt", encoding="utf-8").read()
TOKEN_RE = re.compile(r"\{\{?\w+\}?\}|%[sd]|%\d*\.?\d*[dsf]|<[^>]+>|\[/?\w+(?:=\w+)?\]|\\n")

def tokens(s: str) -> list[str]:
    return sorted(TOKEN_RE.findall(s))

def translate_batch(items: list[dict], model="deepseek-v4.1-flash") -> dict:
    resp = client.chat.completions.create(
        model=model,
        temperature=0.2,

Ключевая функция здесь find_bad: она сравнивает набор плейсхолдеров и тегов в оригинале и переводе. Любое расхождение — повод перевести строку заново. Регулярное выражение TOKEN_RE подгоните под формат вашей игры: у каждого движка свой синтаксис разметки.

Дальше цикл: перевели пакет, нашли испорченные строки, отправили только их ещё раз (можно более сильной моделью), после двух попыток остаток складываем в файл для ручной правки. Если запросов много, ориентируйтесь на статью про асинхронную обработку тысяч запросов, а общие приёмы работы с локализационными файлами смотрите в материале про перевод i18n файлов.

Форматы: JSON, CSV, PO

Модель всегда работает с одной и той же внутренней структурой id → текст, а форматы файлов — это адаптеры на входе и выходе.

  • JSON. Плоский словарь или вложенный: обойдите дерево и соберите ключи через точку. Записывая результат, восстановите ту же структуру и тот же порядок ключей, чтобы diff в git оставался читаемым.
  • CSV. Читайте стандартным csv-модулем с encoding="utf-8", переводите нужную колонку и записывайте в новую. Не склеивайте строки вручную: запятые и кавычки внутри текста ломают разбор.
  • PO. Подойдёт библиотека polib: po = polib.pofile("ru.po"), у записей поля msgid и msgstr, сохранение через po.save(). Контекст записи (msgctxt) передавайте в поле context.

Для файлов из чужих движков сначала выгрузите строки в одну из этих форм утилитой для вашего движка, а после перевода загрузите обратно. Если вы переводите чужую игру или мод, проверьте условия лицензии и правила издателя: это вопрос права, а не техники.

Сколько стоит перевод игры

Расчёт на 18 октября 2026. Допущения: 20 000 строк, пакеты по 50, то есть 400 запросов. На запрос: системный промпт со словарём 1 500 токенов плюс 50 строк по 30 токенов = 3 000 токенов входа; русский перевод пакета с JSON-обвязкой около 2 500 токенов выхода. Итого 400 × 3 000 = 1,2M входа и 400 × 2 500 = 1,0M выхода. Реальные цифры смотрите в usage ответа; русский текст обычно занимает больше токенов, чем английский.

Формула: вход × цена входа + выход × цена выхода.

МодельРасчётИтого
deepseek-v4.1-flash1,2 × $0,013 + 1,0 × $0,038$0,054
gpt-6.1-sol1,2 × $0,27 + 1,0 × $1,32$1,64
claude-sonnet-5-51,2 × $0,4 + 1,0 × $2$2,48
claude-opus-5-51,2 × $0,8 + 1,0 × $4$4,96

Добавьте запас на повторы: если примерно каждая десятая строка переводится дважды, это плюс около 10% к итогу. Цены меняются: актуальный список — GET https://api.zukko.pro/v1/models. Практичная схема: дешёвая модель делает основной проход, более сильная переводит только то, что не прошло проверки. Подбирать модель стоит на пробной выборке из 100–200 строк, которую вы прочитаете сами: заранее сказать, кто лучше передаст стиль вашей игры, нельзя.

Ключ для скрипта создайте в кабинете и задайте на него лимит расхода: ошибка в цикле не должна съесть весь баланс.

Частые вопросы

Как не сломать плейсхолдеры при переводе?

Скажите модели в промпте копировать их без изменений и проверяйте результат кодом: сравнивайте наборы плейсхолдеров и тегов в оригинале и переводе. Строки с расхождением отправляйте на повторный перевод.

Как учесть ограничение длины строки?

Передавайте max_len вместе с каждой строкой, а после ответа проверяйте длину. Слишком длинные строки переводите заново с просьбой сократить. Окончательную проверку делайте в самой игре, на реальных элементах интерфейса.

Чем переводить: дорогой моделью или дешёвой?

Начните с дешёвой на пробной выборке и прочитайте результат. Для сюжетных диалогов стоит попробовать модель посильнее, для интерфейса и предметов часто хватает недорогой. Выбор делайте по своей выборке, а не по общим обещаниям.

Можно ли переводить файл целиком одним запросом?

Для небольших файлов можно, но надёжнее пакеты по 30–60 строк с идентификаторами: проще проверять, повторять сбойные части и не терять порядок строк.

zukko

Платите в 25×
меньше

за Claude Code & ChatGPT

Один ключ fetch_* и base URL api.zukko.pro — в Cursor, Claude Code, Codex и любом SDK.

Нейросеть для перевода игр: строки без поломок · Zukko