Многоязычная игра (переводы)
Одна игра, одна статистика, одни коды — а текст каждый игрок читает на своём языке. Переводы лежат рядом с игрой и подменяют текст при показе; там, где перевода нет, игрок видит оригинал. Игроку, у которого язык совпадает с языком игры, ничего не подменяется вообще.
Это рекомендуемый способ для перевода текста, ссылок и картинок. Старый приём с шаблоном {% match lang %} (Шаблоны) продолжает работать и остаётся правильным выбором там, где языку нужна не другая версия того же текста (это как раз переводится), а другая структура: свой набор html-блоков, которого нет у других языков, своя логика в скрипте задания, а не просто другая строка в нём, или ветвление по языку, скомбинированное с другим шаблоном - по коду, по команде, по бонусу. А для перевода текста игры новые игры лучше делать переводами: текст задания не превращается в простыню из N копий, правка вёрстки не размножается по языкам, а редактор показывает, что ещё не переведено.
Включение
В редакторе игры, вкладка «Настройки игры», блок «Локализация»:
- Язык игры — язык, на котором игра написана. Пока он не выбран, никакой локализации у игры нет: ничего не считается, ничего не хранится, редактор выглядит как обычно.
- Языки перевода — галочки языков, на которые игра переводится. Рядом с каждым — «падает на»: на какой язык показывать то, что на этом языке ещё не переведено. Пусто — сразу на язык игры.
- Строка «остальные языки» — куда отправлять игрока, языка которого у игры нет вовсе.
Пример: игра написана по-русски, переведена на украинский и английский, а польский падает на украинский (он ближе, чем русский). Игрок-поляк увидит польский текст там, где он есть, украинский — там, где польского ещё нет, и русский — там, где нет и украинского.
Как только появился хотя бы один язык перевода, в редакторе появляется вкладка «Перевод».
Вкладка "Перевод"
Это таблица пар «оригинал → перевод». Слева строка из игры, справа поле для перевода. Открывается она на непереведённых строках — на том, что осталось сделать.
- Строки собираются автоматически. Большой текст (задание, подсказка, афиша, финишный текст) режется на абзацы; короткие поля (название игры, название задания, название кода, описание подсказки, формат ответа) идут целиком. Размечать в тексте ничего не надо.
- Раскладка — переключатель справа над таблицей. «По полям» (по умолчанию) ставит строки под заголовком их поля — «Задание 7 → Текст задания» — и в том порядке, в каком они идут в тексте: так абзац переводят, видя соседние.
«Списком» даёт сплошной список, где адрес написан у каждой строки; так удобнее с короткими полями — у названия кода поле это одна строка, и заголовков выходит больше, чем работы.

- Одинаковый текст переводится один раз на всю игру. Если строка встречается в нескольких местах, рядом с ней стоит «мест: N» — наведите мышь, чтобы увидеть где. Правка такой строки меняет её везде. По полям такая строка нарисована в каждом своём поле и помечена «общая строка, мест: N»: это не дубль, а одна и та же запись словаря.
- Состояние строки видно значком: свой перевод, из языка X (пришло по цепочке), база (перевода нет) или не переводится.
- Полнота показывается двумя числами: сколько переведено на этот язык и сколько получится с учётом цепочки. Второе число само по себе обманчиво — оно прячет непереведённое за чужим языком.
- Группы строк — «непереведённые», «переведённые», «непереводимые». Это не выбор одного из трёх, а переключатели: они складываются. По умолчанию включены только непереведённые — это и есть работа; переведённые включают, когда идут вычитывать готовое, непереводимые — когда надо снять пометку.
- Фильтр — строка под группами. Отбирает по оригиналу, регулярным выражением, и работает вместе с группами, а не вместо них: «непереведённые» и подошедшие под фильтр. Применяется по Enter или кнопке «Фильтр», числа на кнопках групп при этом показывают уже отобранное, а рядом с полем стоит «показано: N / M» — сколько строк осталось после фильтра и групп.
Фильтры и массовая пометка
Стрелка у поля открывает готовые фильтры:
- «нет кириллицы» и «нет латиницы» — считаются по тексту без чипсов и подстановок, поэтому
!username!и%offline%латиницей не считаются; - «нет слов» — буква есть, а слова нет: координаты вида
N 49.5905177 34.5434377, схемы, «2+ шт».
Выбранное из списка встаёт в то же поле, так что всегда видно, чем отобрано; готовый фильтр можно и поправить — как только тронули текст, он становится обычным регэкспом. Свой фильтр можно сохранить («сохранить фильтр» рядом с полем) — он попадёт в тот же список, во вторую его половину, и убирается оттуда кнопкой «забыть фильтр». Сохранённые фильтры личные и общие на все игры: это инструмент того, кто разбирает словарь, а не свойство игры.
Ради этого фильтр и нужен: справа от него — список «со всеми показанными…». В нём те же три пункта, что в конце каждой строки таблицы («переводим», «не переводить в этом языке», «не переводить нигде»), только применяются они разом ко всему, что сейчас показано — то есть к фильтру вместе с группами. Спрашивается с числом в обе стороны: снятие пачкой опаснее пометки — оно возвращает в работу то, что исключили осознанно. Вся пачка — один шаг отмены, и каждая строка видна в окне сохранения.
Типичный сценарий: фильтр «нет кириллицы» → в списке остались бренды, имена и ссылки → пометить их разом → счётчик полноты перестал упираться в то, что переводить никто не собирался.
Разметка внутри строки
Жирный, ссылки, картинки и шаблоны внутри абзаца в переводе не пишутся руками: на их месте стоят чипсы — маленькие рамки с номером.
Кликните по чипсу — он встанет в перевод там, где стоит курсор.
Чипсы можно переставлять (порядок слов в языках разный), но каждый должен быть в переводе ровно один раз — иначе перевод не сохранится и редактор скажет об этом.
Так же ведут себя подстановки — !username!, !task_n! и прочие: они остаются в переводе как есть, просто в нужном месте фразы.
Полезное следствие: сами теги, адреса ссылок и классы живут только в оригинале. Поправили ссылку в задании — она поменялась во всех языках сразу.
Что не переводится
- Коды-ответы не переводятся никогда. Это и делает статистику общей. Ответы на разных языках просто дописываются синонимами через запятую в том же коде.
- Не переводить эту строку — переключатель в конце строки таблицы, два режима: «не переводить в этом языке» и «не переводить нигде». Для брендов, имён собственных, латинских цитат. Такие строки уходят из «непереведённых» и не мешают счётчику полноты дойти до 100%.
translate=«no»в HTML задания — более сильный способ: такой кусок не станет строкой вовсе, и его не тронет даже автоперевод браузера. Для кодовых слов и ответов внутри текста это важнее, чем кажется: автоматически переведённое кодовое слово ломает игру.
Ссылки и файлы
Адреса картинок, звуков, видео и ссылок по умолчанию не переводятся — почти все они языконезависимы. Но перевод адреса можно завести: так игрок уходит на страницу своего языка или получает озвучку на своём языке, а абзац и вёрстка остаются одни на всех.
Адрес стоит в таблице там, где он стоит в тексте, обычной строкой: ссылка внутри абзаца — под самим абзацем, с отступом; картинка, стоящая в поле одна, — строкой сама по себе. Переводите абзац — видите и его ссылку, отдельно её искать не надо.
Во всём остальном это такая же строка, как текстовая: те же группы («непереведённые» и прочие), тот же переключатель «не переводить». Отличие одно — в счёт полноты адреса не идут.
Субтитры оверлеем делать не надо — HTML это уже умеет: несколько <track srclang=«…»> в одном <video>, браузер выберет сам.
Устаревшие переводы
Идентичность строки — её текст. Поправили оригинал — перевод к нему больше не подходит, строка снова становится непереведённой, а старый перевод уезжает в раздел «Устаревшие переводы». Если правка была мелкой (опечатка), редактор сам предложит его вернуть кнопкой «восстановить» прямо под новой строкой. Ненужные можно удалить — по одной или все сразу.
Переводы из другой игры
Внизу вкладки: «Загрузить переводы из игры» — номер игры и кнопка. Возьмутся только те пары, чей оригинал есть и в этой игре; отчёт скажет, сколько совпало и сколько пропущено. Существующие переводы по умолчанию не перезаписываются. Осмысленно для серии игр одного автора с одним языком оригинала: у игры на другом языке совпадений не будет.
Перевод файлом
Рядом с выбором языка — две кнопки. «Скачать строки на перевод» отдаёт файл game_<id>_<lang>.json со строками этого языка: непереведённые — пустыми, уже переведённые — заполненными, чтобы у переводчика был глоссарий и контекст. Помеченные «не переводить» и адреса ссылок и файлов в него не идут. «Загрузить переводы из файла» принимает его назад — пары ложатся в черновик, рядом появляется отчёт «Загружено: N, пропущено: M». Пустой перевод в файле ничего не стирает: наполовину заполненный файл — это «перевели пока столько».
Если включён фильтр или показаны не все группы, рядом появляется вторая кнопка — «только показанные (N)»: она отдаёт тот же файл, но из отобранных строк. Живой сценарий — «доехало полсотни новых строк» или «отдать переводчику задание 7». Число на кнопке говорит, сколько именно уедет, а полный файл остаётся в один клик рядом.
Так переводят вне редактора: в CAT-программе, у живого переводчика или чат-ботом — Перевод игры с помощью AI.
Как это сохраняется
Переводы — часть черновика редактора, наравне с текстом. Переводить можно и несохранённое задание: написали задание, тут же перевели, сохранили одной кнопкой. Правка оригинала и починка переводов уезжают на сервер одной операцией, так что момента, когда игроки видят новый текст со старым переводом, не возникает.
Переводы едут вместе с игрой в её JSON — секцией translations — и приезжают обратно при импорте. Копия игры получает и переводы; копирование одного задания в другую игру переводы не переносит (словарь общий на игру, чужие строки там были бы мусором) — для этого есть «Загрузить переводы из игры».
Проверка
Откройте игру с явным языком: https://qeng.org/game/1234/?lang=uk. Проверьте и язык, которого у игры нет, — так видно, работает ли строка «остальные языки».
Тот же уровень на языке игры и на украинском: подменился текст, а вёрстка, картинки и коды остались одни на всех.
Чего переводы пока не касаются
- названия платных товаров;
gt(…)внутри тега<script>, вставленного прямо в текст задания, подсказки или бонуса, - движок его переводит, а вкладка «Перевод» такую строку пока не предлагает. Отдельное поле «Скрипт задания» это ограничение не касается — оно переводится целиком.
Для них пока работает прежний способ — {% match lang %}.
Смотрите также
- Перевод домена — шапка, меню, подвал и страницы домена переводятся так же и той же таблицей.






