Перевод (Translation)

Материал из Ren'Py Wiki
Перейти к навигации Перейти к поиску

Ren'Py включает обширную основу для перевода визуальных новелл.


Существует четыре основных типа вещей, которые можно перевести:

Диалог
Можно перевести основной диалог скрипта, включая положение для разделения, объединения, пропуска и изменения порядка строк.
Меню и строки интерфейса
Можно перевести весь текст интерфейса.
Изображения и файлы
Сюда можно включить различные изображения и другие файлы, которые используются при выборе языка.
Стили
Можно настроить стили в зависимости от языка, чтобы игра автоматически переключалась на шрифт, соответствующий выбранному языку.


В настоящее время поддержка перевода Ren'Py сосредоточена на санкционированных переводах, когда создатели игры либо выпускают скрипты игры для переводчика, либо сами создают шаблоны перевода. Поддержка неофициальных переводов более ограничена.

Основные и дополнительные языки (Primary and Alternate Languages)[править | править код]

Ren'Py ожидает, что каждая игра будет написана на одном основном языке. Он называется языком None, независимо от того, какой это язык на самом деле. Например, если игра была написана на английском языке, то английский будет языком None.

Если выбран язык None, большая часть функций перевода Ren'Py перевода отключена.

На альтернативные языки ссылаются по именам, которые могут удваиваться как идентификаторы в Python (начинаются с буквы или символа подчеркивания, за которыми следуют буквы, цифры и подчеркивания).

Создание файлов перевода (Generating Translation Files)[править | править код]

Когда доступны скрипты проекта, файлы перевода можно сгенерировать, открыв проект в Ren'Py Launcher и выбрав «Создать переводы». Ren'Py Launcher запросит название языка, который нужно сгенерировать, а затем перейдет к созданию или обновлению файлов перевода.

Файлы перевода находятся в папках под подпапкой «tl» в директории игры. Например, если вы создаёте перевод обучающего проекта, например на французский, файлы перевода будут помещен в tutorial/game/tl/french.

Для каждого файла скрипта игры будет создан один файл перевода. Также будет создан файл common.rpy, содержащий переводы строк, которые являются общими для всех игр, созданных с помощью Ren'Py.

Перевод диалога (Translating Dialogue)[править | править код]

Так как Ren'Py является движком для создания визуальных новелл, мы ожидаем, что большая часть перевода затронет диалог. Ren'Py включает гибкую структуру, которая позволяет разделять, объединять, перестраивать и полностью пропускать диалог.

Единицы перевода[править | править код]

Основная единица перевода – блок из нуля или более переводимых операторов, за которым может следовать один оператор say. Переводимые операторы – операторы voice и nvl. Для примера возьмём следующую игру:

label start:

    e "Спасибо, что взглянули на структуру перевода Ren'Py."

    show eileen happy

    e "Мы нацелены на создание обширной основы для перевода диалогов, строк, изображений и стилей."

    e "Это практически всё, что нужно вашей игре!"

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

В примере, приведенном выше, первой сгенерированной единице присваивается идентификатор start_636ae3f5 и она содержит оператор:

e "Спасибо, что взглянули на структуру перевода Ren'Py."

Вторая единица получает идентификатор start_bd1ad9e1m и содержит:

e "Мы нацелены на создание обширной основы для перевода диалогов, строк, изображений и стилей."

Третья единица имеет идентификатор start_9e949aac и содержит:

e "Это практически всё, что нужно вашей игре!"

Эти единицы перевода создаются Ren'Py автоматически при загрузке игрового скрипта.

Оператор translate[править | править код]

При создании переводов для языка, Ren'Py создаст оператор translate, соответствующий каждой единице перевода. При переводе вышеупомянутого кода, Ren'Py создаст:

# game/script.rpy:95
translate piglatin start_636ae3f5:

    # e "Спасибо, что взглянули на структуру перевода Ren'Py."
    e ""

# game/script.rpy:99
translate piglatin start_bd1ad9e1:

    # e "Мы нацелены на создание обширной основы для перевода диалогов, строк, изображений и стилей."
    e ""

# game/script.rpy:101
translate piglatin start_9e949aac:

    # e "Это практически всё, что нужно вашей игре!"
    e ""

Это можно перевести, отредактировав сгенерированные файлы. Готовый перевод может выглядеть так:

# game/script.rpy:95
translate piglatin start_636ae3f5:

    # e "Спасибо, что взглянули на структуру перевода Ren'Py."
    e "Ankthay ouyay orfay akingtay away ooklay atway ethay En'Pyray anslationtray ameworkfray."

# game/script.rpy:99
translate piglatin start_bd1ad9e1:

    # e "Мы нацелены на создание обширной основы для перевода диалогов, строк, изображений и стилей."
    e "Eway aimway otay ovidepray away omprehensivecay ameworkfray orfay anslatingtray ialogueday, ingsstray, imagesway, andway ylesstay

# game/script.rpy:101
translate piglatin start_9e949aac:

    # e "Это практически всё, что нужно вашей игре!"
    e "Ettypray uchmay everythingway ouryay amegay eedsnay!"

При обнаружении блока в основном скрипте, Ren'Py проверяет, существует ли оператор translate, соответствующий этому блоку. Если да, то Ren'Py выполняет оператор translate вместо переведенного блока, показывая пользователю перевод.

Более сложные переводы[править | править код]

Операторы translate не должны включать переводы, соответствующие языку оригинала один в один. Например, можно разделить длинную строку:

# game/script.rpy:99
translate piglatin start_bd1ad9e1:

    # e "Мы нацелены на создание обширной основы для перевода диалогов, строк, изображений и стилей."
    e "Eway aimway otay ovidepray away omprehensivecay ameworkfray..."
    e "...orfay anslatingtray ialogueday, ingsstray, imagesway, andway ylesstay."

Или оператор можно удалить, заменив его на оператор pass:

# game/script.rpy:101
translate piglatin start_9e949aac:

     # e "Это практически всё, что нужно вашей игре!"
     pass

Кроме того, можно запускать недиалоговые операторы, такие как условные конструкции или Python. Например, мы можем перевести:

e "Вы набрали [points] очков!"

в:

# game/script.rpy:103
translate piglatin start_36562aba:

    # e "Вы набрали [points] очков!"
    e $ latin_points = to_roman_numerals(points)
    e "Ouyay oredscay [latin_points] ointspay!"

Советы[править | править код]

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

translate None mylabel_03ac197e_1:
    "..."

Добавление меток также может внести путаницу в процесс перевода. Чтобы предотвратить это, метки, которым задаётся положение hide, игнорируются при создании переводов:

label ignored_by_translation hide:
    "..."


Хотя блоки перевода могут включать код на языке Python, этот код не должен иметь побочных эффектов, видимых за пределами блока. Это связано с тем, что при смене языков перезапускается блок перевода, что приводит к многократному возникновению побочных эффектов.

Переводы меню и строк (Menu and String Translations)[править | править код]

В дополнение к диалогу, Ren'Py способен переводить текст, содержащийся в меню и других строках. Перевод интерфейса – взаимно однозначная замена. Везде, где строка найдена, она будет заменена на одну замену.

При создании переводов Ren'Py проверять файлы скриптов на наличие меню и строк, заключенных в функцию _(). Затем Ren'Py помещает строки в блок translate strings. Например, если у нас есть следующий скрипт:

define e = Character(_("Эйлин"))

# ...

menu:

     "Идти на Запад":
        # ...

     "Направиться на Восток":
        # ...

Ren'Py сгенерирует следующий код:

translate piglatin strings:

    old "Эйлин"
    new ""

    old "Идти на Запад"
    new ""

    old "Направиться на Восток"
    new ""

Который затем может быть переведен, как:

translate piglatin strings:

    old "Эйлин"
    new "Eileenway"

    old "Идти на Запад"
    new "Ogay Estway"

    old "Направиться на Восток"
    new "Eadhay Eastway"

Переводы строк также применяются к диалоговым строкам, которые не переводятся как диалог.

Если одна и та же строка используется в нескольких местах кода, её можно выделить с помощью текстового тега {#...}. Несмотря на то, что строки отображаются одинаково, Ren'Py рассматривает все эти отдельные строки для перевода:

"New"
"New{#project}"
"New{#game}"
"New{#playlist}"

Оператор translate strings также можно использовать для перевода языка None. Это может быть использовано для перевода пользовательского интерфейса Ren'Py, когда игра написана на языке, отличном от английского.

translate None strings:
     old "Start Game"
     new "Начать игру"

Возможность замены перевода[править | править код]

Замену строк можно перевести с помощью флага преобразования !t. Таким образом следующий код будет переведен с помощью комбинации систем диалога и перевода строк:

if mood_points > 5:
    $ mood = _("хорошо")
else:
    $ mood = _("ужасно")

"Я чувствую себя [mood!t]."

Извлечение и объединение переводов строк [править | править код]

Перевод строк можно извлечь из одного проекта и переместить в другой. Это многоэтапный процесс:

  • Выберите в Ren'Py Launcher исходный проект и нажмите «Создать переводы».
  • Введите язык для извлечения и нажмите «Извлечь строки для перевода».
  • Вернитесь в главное меню Ren'Py Launcher, выберете целевой проект и нажмите «Создать переводы».
  • Введите язык для объединения с ранее извлеченными данными (часто один и тот же язык) и выберите «Объединить строки перевода».


Есть несколько вариантов, которые управляют процессом объединения:

Заменить существующие переводы
Когда пункт выбран, это приведёт к замене уже существующих нетривиальных переводов (те из них, которые не являются пустой или исходной строкой). По умолчанию объединение не будет перезаписывать уже существующие нетривиальные переводы.
Обратить языки
Меняет строки перед объединением. Это может пригодиться, например, для созданию русско-английского перевода с помощью набора англо-русских переводов.

Переводы изображений и файлов (Image and File Translations)[править | править код]

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

Ren'Py решает эту проблему, путём поиска изображения в папке перевода. Например, если используется французский язык и загружено изображение library.png, Ren'Py будет использовать "game/tl/french/library.png", отдавая ей предпочтение перед "game/library.png".

Переводы стилей (Style Translations)[править | править код]

При переводе игры может потребоваться изменить стили, особенно связанные со шрифтами. Ren'Py обрабатывает это с помощью блоков translate style и translate python. Эти блоки могут изменять языковые переменные и стили. Например:

translate french style default:
    font "stonecutter.ttf"

или то же самое:

translate french python:
    style.default.font = "stonecutter.ttf"

При активации языка (либо в начале игры, или после смены языка), Ren'Py сбрасывает стили с их содержанием в конце фазы инициализации. Затем он запускает все блоки translate style и translate python, связанные с текущим языком, гарантируя при этом, что блоки, фигурирующие в файле ранее, выполняются в первую очередь. Наконец, он восстанавливает стили, позволяя изменениям вступить в силу.

Переводы стилей могут быть добавлены в любой .rpy файл.

Язык по умолчанию (Default Language)[править | править код]

Язык по умолчанию выбирается следующим способом:

  • Если установлена переменная среды RENPY_LANGUAGE, используется язык, установленный RENPY_LANGUAGE.
  • Если установлена переменная config.language, используется язык, установленный config.language.
  • Если игра раньше когда-либо выбирала данный язык, то он используется.
  • Если игра запускается впервые, а config.enable_language_autodetect принимает значение True, Ren'Py пытается автоматически определить язык с помощью config.locale_to_language_function.
  • Если игра запускается впервые, используется переменная config.default_language (По умолчанию используется язык None.)
  • В иных случаях используется язык None.

Перевод действия, функций и переменных (Translation Actions, Functions, and Variables)[править | править код]

Основным способом переключения языков является action Language.


Language(language)
Изменяет язык игры на указанный в language.
language
Строка, задающая язык, на который необходимо перевести, либо значение None, чтобы по умолчанию использовать язык скрипта игры.


action Language можно использовать для добавления в настройки возможности выбрать язык. Например:
frame:
    style_prefix "pref"
    has vbox

    label _("Language")
    textbutton "Английский язык" action Language(None)
    textbutton "Французский язык" action Language("french")


Есть две функции, связанные с переводом:

renpy.change_language(language, force=False)

Изменяет текущий язык на указанный в language, который может быть строкой или значением None, чтобы использовать язык по умолчанию.

renpy.known_languages()

Возвращает набор известных языков. Не предусматривает язык по умолчанию при значении None.


Кроме того, существует несколько функций, связанных с переводом строк::

_(s)
(Одинарное подчёркивание) Возвращает s без изменений. Ren'Py просканирует строки, заключенные в эту функцию, и добавит их в список переводимых строк. Строки не будут переведены, пока они не будут показаны.
__(s)
(Двойное подчёркивание) Возвращает s, сразу же переведенную на текущий язык. Строки, заключенные в эту функцию, будут добавлены в список переводимых строк. Обратите внимание, что строка может быть дважды переведена, если она совпадает с переводом строки при его отображении.
_p(s)
Переформатирует строку и помечает её как переводимую. Строка будет переведена при отображении отображаемого текста. Это сделано в целях определения многострочного использования в строках, а именно:
define config.about = _p("""
    Эти две линии будут объединены вместе,
    чтобы образовать длинную строку.

    Эта линия будет отдельно.
    """)

Переформатирование выполняется путём разбиения текста на строки, удаления пробелов в начале и конце каждой строки. Пустые строки удаляются в конце. Когда есть пустая строка, она вставляется в отдельные абзацы. Тег {p} разрывает строку, но не добавляет пустую.

Это может быть использовано в переводе строки с использованием конструкции:

old "Эти две линии будут объединены вместе, чтобы образовать длинную строку.\n\nЭта линия будет отдельно."
new _p("""
    Эти две линии будут объединены вместе,
    чтобы образовать длинную строку. Bork bork bork.

    Эта линия будет отдельно. Bork bork bork.
    """)


Существует две языковые переменные. Одна из них – переменная config.language, которая применяется для изменения языка игры, установленного по умолчанию.

_preferences.language
Наименование текущего языка или значение None, если используется язык по умолчанию Её следует рассматривать, как переменную только для чтения. Для изменения языка вызовите renpy.change_language().

Несанкционированные переводы (Unsanctioned Translations)[править | править код]

Заметка: Лучше всего спросить разрешения у создателей игры, прежде чем создавать несанкционированный перевод.

Ren'Py включает небольшую поддержку для создания переводов без активного содействия создателей игры. Эта поддержка заключается в возможности автоматического создания файла перевода строк из всех строк в игре. Поскольку переводы строк используются для непереведенного диалога, данная технология делает возможным перевод игры.


Для создания файла перевода строк, выполните следующие действия:

  • Задайте для переменной среды RENPY_LANGUAGE язык, на который вы хотите перевести.
  • Задайте для переменной среды RENPY_UPDATE_STRINGS непустое значение.
  • Пройдите игру, пока не появится весь текст.

Это обновит файл "game/tl/language/strings.rpy" с шаблоном перевода, содержащим все строки в нём.


Если игра не поддерживает смену языка, может быть целесообразно использовать блок init python для установки переменной config.language на нужном языке.

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

Источник[править | править код]

Статья "Translation" на английском языке.


На главную страницу Официальная документация движка Вернуться к началу статьи