Локализация игр в Unreal Engine 4

Hello there! Моё имя Денис Кузнецов, и я работаю в движке Unreal Engine 4 (уже в 5).

Подготовка игры к локализации — важная часть разработки игр, и в этой статье мы разберем, как это сделать.

Локализация игр в Unreal Engine 4

Как и многие другие (но это не точно, и, надеюсь, что это не так), когда я работал над игрой «Cat Movies», мы решили отложить этап настройки локализации на более поздние итерации разработки и, как оказалось, зря.

Локализация в UE реализована шикарно, и если помнить, что достаточно весь текст, который будет переводиться, хранить в FText (Text в Blueprint’ах) полях, то в целом, с выхватом текста из игры нет никаких проблем. Достаточно открыть Localization Dashboard, потыкать пару кнопок — и вуаля.

И, не смотря на всю простоту этого действия, мы все же столкнулись с рядом проблем, из-за чего пришлось часть кода перелопачивать.

Как хранить текст

Ребята из Epic Games упростили сборку текста до максимума, сводя все к одному клику и дальнейшему переводу. Все очень просто — для локализации используется тип данных FText (Text в Blueprint’ах), в который сохраняется текст, и этот текст в дальнейшем собирается системой локализации и предоставляется для перевода.

Как это работает?

FText — это не стандартный тип данных, который хранит в себе данные. Он, конечно, хранит в себе данные, но не те, которые мы ожидаем.

FText — это указатель. Он указывает на то, в какой таблице хранится текст. То есть, когда мы присваиваем переменной этого типа какой либо текст, то текст сохраняется в виртуальной таблице, а сама переменная теперь хранит имя таблицы и ключ, по которому в этой таблице можно найти текст.

Таким образом, получается, что сам текст хранится где-то в другом месте (тонкости реализации этого мы не будем рассматривать, так как нам это не особо-то и интересно) , а при переключении локализации по нужному адресу происходит подмена текста (ну, или я так хочу думать) .

Локализация игр в Unreal Engine 4

Когда запускается сбор текста, то система локализации собирает все Text — переменные из всех блюпринтов, виджетов и таблиц, и выкатывает один огромный список текста, который можно экспортировать в *. po и переводить.

Наша экономическая стратегия — игра в интерфейсы. В ней очень мало взаимодействия с трехмерным миром, поэтому она имеет большой набор виджетов, через которые игрок будет контролировать почти весь игровой процесс. У нас есть много названий (например, отделов или этапов создания фильмов или каких-то навыков, бонусов и т.д.), которые используются в различных виджетах, между собой совсем не связанных. Есть описания каких-то объектов (например, описание бонусов), и это тоже используется не однократно в различных не связанных виджетах.

И вот тут начинается сложность. Если мы будем в каждом виджете заново писать названия отделов, то в какой-то момент в одном из виджетов название отделов будет написано не так. Осложняется это дело тем, что сами «описания» (например, описание отдела) в большом кол-ве знаков сложно отследить, чтобы везде были одинаковыми (естественно, мы так не делали) . Еще больше веселья в том, что у нас большая часть виджетов используется, как шаблон, в который залетают данные из различных источников, и исходя из того, какой это был источник, меняются названия и тексты внутри кода.

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

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

Все стало куда печальнее, когда я решил залезть в локализацию и наконец-то опробовать ее от и до, чтобы понимать, все ли мы верно делаем. Я вытянул весь текст из игры и понял, что в коде, не смотря на то, что мы стремились избегать повторения, оказалось огромное количество повторяемых элементов текста.

Перевод — дело человеческое. Если будет возможность ошибиться, человеки обязательно ошибутся. И чтобы этого избежать или хотя бы минимизировать, нужно сводить все тексты к единому шаблону. То есть, вывести куда-то в одно место, откуда текст будет браться во всех частях кода. И который будет переведен лишь единожды, чтобы свести риски ошибок до минимума. Казалось бы, можно использовать DataTable, но и там кроется ряд проблем — чтобы сохранить просто названия чего-то, нам нужно создавать целые таблицы, которые будут хранить эти названия.

Поковырявшись в документации Epic Games, я обратил внимание на String Tables (далее «строковые таблицы») . Оказалось, это идеальный вариант — хранить текст в отдельной специальной для текстов таблице, которая создана именно для того, чтобы подключаться в FText — переменным. То есть, мы можем создать таблицу, которая будет хранить в себе текст. И этот текст мы можем подключать к любой переменной — будь то переменная в таблице данных, переменная в виджете, переменная в коде — все сводится к одному месту, где хранится текст.

Строковые Таблицы позволяют избегать повторения текста в проекте по нескольку раз чуть более, чем полностью, таким образом избегая ошибок.

Строковые таблицы создаются в движке, как и таблицы данных в разделе «miscellaneous»:

Локализация игр в Unreal Engine 4

Заполняются очень легко — каждая новая строка должна иметь уникальный ключ, который придется придумывать самостоятельно. А сам текст уже может быть любым. Так же, в таблице можно указать отличное название пространства текста от названия таблицы, но, по нашему опыту, это не обязательно.

После того, как строковая таблица создана, текст теперь можно подключать к FText — переменной:

Говорим Yes локализации.
Говорим Yes локализации.
Ниже в Referenced Text указывается таблица и ключ к тексту.
Ниже в Referenced Text указывается таблица и ключ к тексту.

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

Локализация.

Теперь нам остается только собрать весь текст и начать с ним работать. Для этого нам необходимо запустить Localization Dashboard и начать настройки локализации. Запустить таблицу можно через меню Window->Localization Dashboard.

И перед вами откроется примерно такое окно:

Локализация игр в Unreal Engine 4

В этом окне нужно обязательно указать цель (модуль) , из которого будет выдергиваться текст. В нашем случае, это игра — Game.

Далее, нужно указать, откуда именно будет в модуле будет выдергиваться текст. В нашем случае, это только блюпринты, так как в сурсах мы не храним текст. Поэтому нужно указать только «Gather from Packages» и указать, в каких папках и какие файлы нам необходимо рассматривать, чтобы искать тексты.

Так же нам необходимо указать, какие языки будут использоваться для перевода и какой язык будет нативным (основным) . Очень рекомендую, если вы пишите и говорите на русском языке — указывать русский язык (или любой другой ваш основной язык) . Это связано с тем, что если вы не знаете хорошо английский язык, то указав его основным, вы усложняете себе перевод на английский с «английского». Поэтому, лучше заранее указать ваш язык, как основной, и все тексты писать на вашем родном языке, чтобы потом облегчить себе и другим переводы.

Так же в UE4 есть шикарная возможность создавать переводы прямо в движке, не экспортируя тексты для сторонних программ. Для этого нужно собрать весь актуальный текст в игре, нажав на кнопку № 1. И после этого запустить редактор (кнопка № 2):

Локализация игр в Unreal Engine 4

Откроется окно редактирования перевода на нужный вам язык.

Сборка

При сборке проекта обязательно нужно указать языки, которые в эту сборку должны войти, а так же какой набор языков должен поддерживать ваш проект.

Локализация игр в Unreal Engine 4

В нашем случае, Internationalization Support установлен на All. То есть, наш проект будет поддерживать все типы языков от сложных иероглифов до простых английских букв. А вообще, есть 5 пакетов:

  • English (чистый английский) .
  • EFIGS (English, French, Italian, German, and Spanish) .
  • efigscjk (То же, что и выше + Chinese, Japanese, and Korean ).
  • CJK (Chinese, Japanese, and Korean) .
  • All (Все языки) .

Однако в случаях, когда важен каждый байт в проекте (пакет All весит 15мбайт, а EFIGS 2мбайта) , стоит более внимательно отнестись к тому, какой пакет нужно выбрать.

Настройка локализации в коде

Переключение текста происходит в Runtime, то есть вам не нужно перезагружать игру, не нужно париться на тему оптимизации переключения — все делается легко и просто через метод «SetCurrentCulture», где текстом нужно указать, на какой язык вы хотите переключиться.

!ВАЖНО! Помните, что нельзя сменить язык во время игры, если она запущена в движке. Для этого нужно запускать игру в Stand Alone режиме. Иначе вы меняете язык в движке, а не в игре =)

Локализация игр в Unreal Engine 4

И вот здесь есть некоторая такая загвоздочка. Дело в том, что разных странах есть свои ответвления языка, так, например, есть основной русский язык (ru), а есть беларуский (ru-BY), казахский (ru-KZ), молдавский (ru-MD), украинский (ru-UA) языки, которые попадают под ветку русского языка. Поэтому, при выборе какого-то языка, который не является основным, это нужно учитывать и указывать корректный язык. Если выбрать просто основной, то при переключении достаточно указать «ru».

Локализация игр в Unreal Engine 4

Добавление в текст внешних данных в Blueprint’ах.

Если в самом тексте указать фигурные скобки, а в них указать название данных, то в дальнейшем, можно использовать подстановку этих самых данных в текст. Например: «Вы желаете изучить технологию {Tech_Name}?».

И в BP можно использовать ноду «Format Text», которая будет учитывать сам текст и указанные параметры и создавать дополнительные пины для подключения этих самых данных.

Локализация игр в Unreal Engine 4

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

Локализация ассетов

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

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

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

Для этого нажмите по любому ассету в проекте ПКМ -> Asset Localization -> Create Localized Asset -> (выбрать язык) .

Локализация игр в Unreal Engine 4

После создания новой копии ассет можно найти в специализированной папке для локализации. Если лень искать — можно кликнуть ПКМ по основному объекту в проекте и через меню локализации выбрать редактирование нужной вам версии.

Локализация игр в Unreal Engine 4

Там же можно и перейти к ассету в браузере. Все очень удобно и практично.

Заключение

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

9292
24 комментария

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

4
Ответить

Переходи на анрил =) Здесь тебе и Rider и локализация =)

1
Ответить

Свой есть, но пока в Preview https://docs.unity3d.com/Packages/com.unity.localization@0.8/manual/index.html

 Детали установки:
https://forum.unity.com/threads/release-announcements-and-notes.597262/

если кратко, то добавить в manifest.json надо


а так то есть ещё в asset store локализаторы норм

1
Ответить

Комментарий недоступен

4
Ответить

Не за что =) Подписывайся на твиттер =)

Ответить

Спасибо.
У меня такой вопрос. Даже при наличии словаря терминов, когда один и тот же термин переводится одинаково, начинаются проблемы с числительными и с падежами. Например, какой-нибудь такой шаблон:

{You see %Count %ItemName}

Даже на английском с ним будут проблемы с добавлением суффикса s, а уж при переводе на русский: 

{Вы видите %Count %ItemName}

надо как-то так сделать, чтобы вместо "Вы видите 4 статуэтка" было "Вы видите 4 статуэтки". А в случае одного предмета - "Вы видите 1 статуэтку" (а не "статуэтка").

Конечно можно подбирать формулировки так, чтобы нивелировать эту проблему, но формулировки тогда получаются довольно кривыми, типа "Вы видите статуэтки в количестве 4"

Как в unreal engine с этим всем? Сталкивались?

2
Ответить

Первая же ссылка на докуметацию по запросу unreal engine localization plurals

 There {NumCats}|plural(one=is,other=are) {NumCats} {NumCats}|plural(one=cat,other=cats)"

5
Ответить