Переведи свою игру: девушка из ролика указывает на выбор языков в Unreal Engine 5

Статья

Локализация в Unreal Engine: текст, субтитры, озвучка и текстуры

Настраиваем русский и английский языки в UE: String Tables, перевод UMG, субтитры и локализованные ассеты. Разбираемся, когда нужен перезапуск и как проверить сборку.

1

материал

Статья

формат

Опубликован

статус

Вы нажали «Русский». Кнопки перевелись, субтитры тоже, а персонаж продолжает говорить по-английски. Надпись на стене вообще делает вид, что ничего не произошло.

С переключением языка разбираемся в моём видеоуроке. Разберёмся на небольшой сцене: переведём имя персонажа, добавим субтитры, заменим озвучку и картинку на стене. По пути выясним, что меняется сразу, когда нужен перезапуск и почему перевод иногда теряется при сборке игры.

Удобнее смотреть? Вот видео

В ролике я показываю весь процесс в Unreal Engine 5.4 — от String Tables до проверки сборки. Он длится около 20 минут. Можно смотреть и повторять за мной, а к тексту возвращаться за нужной настройкой или разбором ошибки.

ВСЁ о ЛОКАЛИЗАЦИИ игр в UNREAL ENGINE 5

Если плеер не загрузился, откройте ролик на YouTube. Статья понятна и без видео: здесь я собрал шаги, добавил пояснения из комментариев и уточнил спорные места по документации Epic.

Как выглядит результат: EN / RU

На этих кадрах показана одна тестовая сцена с выбранными en и ru. Сравните имя в двух строках интерфейса и флаг на стене.

▶ Смотреть результат в видео — 18:22

При en в обеих строках стоит Vasya, при ruВася. Меняется и изображение на стене. На русском кадре внизу виден субтитр «Привет, друг!»; на английском реплика в кадр не попала.

Это пример перевода отдельных элементов: фразы вокруг имени и кнопка «Ништяк» пока остаются русскими в обоих вариантах. Заодно здесь видно, почему имя нельзя бездумно подставлять в любое предложение: получается «Ты говоришь с Вася». В готовой игре такую фразу тоже нужно оформить с учётом грамматики. Саму озвучку можно проверить в видео — по скриншотам её не услышать.

Что понадобится и что получится

Работать будем в своём проекте. Для начала достаточно уметь открыть Widget Blueprint, добавить Text Block и кнопку, импортировать звук и запустить игру. Ролик записан на UE 5.4; в другой версии настройки могут находиться в другом месте.

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

В результате вы сможете:

  • использовать одну запись String Table в нескольких местах;
  • перевести интерфейс и встроенные субтитры;
  • подготовить языковые варианты звука и изображения;
  • проверить результат в Standalone Game и упакованной игре.

Сначала разделим текст и ассеты

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

Culture — обозначение языка и связанных с ним региональных правил. В примере используем en и ru.

Для текста, который увидит игрок, используйте тип Text (FText в C++). Он поддерживает локализацию и обновление текста при смене культуры. String тоже нужен, но для других задач: при преобразовании Text → String → Text можно потерять данные, на которых держится локализация. Text Localization.

Один Вася — одна запись в String Table

Представим, что имя героя написано в меню, карточке персонажа и диалоге. Если везде вписать его руками, при переименовании придётся искать все три места. Я хочу поменять имя один раз, чтобы оно обновилось везде.

Создадим String Table — таблицу исходных текстов. У каждой записи есть ключ: по нему виджет или переменная найдут нужный текст. В самой таблице храним исходные строки, а переводить их будем через Localization Dashboard. Столбцы «русский», «английский» и «немецкий» здесь не нужны. String Tables.

В Content Browser создайте папку Content/MyGame/Data/StringTables. В ней через Miscellaneous → String Table создайте ST_Name и добавьте записи:

KeySource String
HeroNameVasya
EnemyNameIvan

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

Редактор String Table: ассет и Namespace ST_Name, ключ EnemyName со значением Ivan и ключ HeroName со значением Vasya

▶ Смотреть создание String Table в видео — 3:03

В ST_Name две записи: EnemyName → Ivan и HeroName → Vasya. Слева — ключи, по которым обращаемся к тексту, справа — исходные значения. Переводы добавим через Localization Dashboard.

Теперь откройте тестовый виджет. У свойства Text первого текстового поля нажмите значок локализации возле значения, выберите ST_Name и ключ HeroName. Сделайте то же для второго поля. Скомпилируйте и сохраните виджет.

В обоих полях появится Vasya. Проверьте, что вы именно выбрали запись из таблицы. Если просто вписать имя руками, связи с таблицей не будет.

В Widget Blueprint выбран TextBlock_Name; стрелка ведёт от него к значку локализации свойства Text и раскрытым полям String Table ST_Name и ключа HeroName

▶ Смотреть привязку Text к таблице в видео — 6:14

Выберите нужный Text Block — на кадре это TextBlock_Name. В свойстве Text нажмите значок флага, затем укажите String Table ST_Name и ключ HeroName. После этого поле хранит ссылку на запись таблицы, а не отдельно набранное имя.

Так же можно задать значение переменной типа Text. Чтобы вставить имя в предложение, используйте Format Text: вся фраза будет переводимым шаблоном, а имя — его аргументом. Не склеивайте предложение из отдельно переведённых кусочков: в другом языке слова могут идти в другом порядке. Форматирование локализуемого текста.

Проверка: поменяйте исходное имя в ST_Name и убедитесь, что оба поля используют обновлённое значение. После этого верните Vasya.

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

Настраиваем Localization Dashboard

Откройте Tools → Localization Dashboard и выберите игровой Target — набор настроек и данных локализации. Для нашего примера хватит одного. Если создаёте новый, проверьте Loading Policy: Game, иначе его данные не будут загружаться в игре. Localization Tools.

Включите Gather from Packages — сбор текста из ассетов. В Include Path Wildcards укажите папку с таблицами. В примере это Content/MyGame/Data/StringTables/*; если у вас другая структура, укажите свой путь.

Target Game: Loading Policy Game, включён Gather from Packages, задан путь Content/MyGame/Data/StringTables/*

▶ Настройки сбора в видео — 1:10

Через Add New Culture добавьте English (en) и Russian (ru). Выберите английский как Native Culture, сохраните настройки и нажмите Gather Text.

В Target Game добавлены English и Russian; английский выбран как Native, выделены Add New Culture и Gather Text

▶ Языки и сбор текста в видео — 1:10

Native Culture — язык исходного текста. В вашем проекте он вполне может быть русским. Лучше определиться с ним в начале. Когда проект будет уже наполнен текстами и переводами, смену Native нужно готовить как отдельную миграцию. Localization Overview.

В строке Russian нажмите первую кнопку в столбце Actions. Подсказка Edit translations for this culture поможет найти её среди похожих значков.

Стрелка указывает на Edit Translations в строке Russian в Localization Dashboard

▶ Открываем перевод в видео — 4:25

В Translation Editor переведите VasyaВася и IvanИван. Нажмите Save.

В Translation Editor исходные Ivan и Vasya переведены как Иван и Вася; сверху видна кнопка Save

▶ Перевод и компиляция в видео — 4:25

Вернитесь в Localization Dashboard и нажмите Compile Text. Дальше повторяйте эту последовательность после изменений:

Изменили исходный текст
→ Gather Text
→ Добавили или проверили перевод
→ Сохранили
→ Compile Text
→ Проверили в игре

Gather находит строки, а Compile Text создаёт файлы .locres — Localization Resource. Это готовые двоичные ресурсы с переводами для конкретного языка: во время игры движок читает перевод из них. Сохранить правки в Translation Editor недостаточно — после этого нужно выполнить Compile Text. При следующей компиляции ресурсы обновятся. Самим создавать или редактировать .locres не нужно. Как устроены файлы локализации.

Не путайте компиляцию переводов с компиляцией Blueprint или сборкой игры. Здесь мы только подготавливаем текстовые данные. Звуковые записи и текстуры в .locres не хранятся.

Если после сбора новые строки не появились в уже открытом Translation Editor, закройте и откройте его заново — в демонстрации этого было достаточно. Если строк всё ещё нет, проверьте путь сбора и сохранены ли ассеты.

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

Переключаем язык и проверяем интерфейс

В обработчике On Clicked кнопки русского языка вызовите Set Current Culture со значением ru. Для английского — en. Включите Save to Config, если игра должна запоминать выбор после закрытия. Если язык не меняется, проверьте результат вызова — Return Value.

Blueprint переключения языка: Button_Rus вызывает Set Current Culture с ru, Button_Eng — с en; у обеих нод включён Save to Config

▶ Смотреть переключение культуры в видео — 8:58

Здесь две кнопки работают одинаково: событие On Clicked передаёт выполнение в Set Current Culture, меняется только код культуры — ru или en. Флажок Save to Config включён в обеих нодах, поэтому выбранный язык сохранится после закрытия игры. Выход Return Value позволяет проверить, удалось ли переключение.

В примере мы переключаем всё вместе. Если позже захотите дать игроку отдельный выбор языка озвучки, учтите: Set Current Culture меняет общую культуру, включая настройки групп ассетов. Для раздельного выбора понадобятся отдельные операции. Managing the Active Culture at Runtime.

Запустите Standalone Game. Нажмите кнопку русского языка: оба поля с именем должны показывать Вася. Верните английский: оба должны показывать Vasya. Затем выберите русский, закройте игру и запустите заново — при сохранённом выборе она должна вернуться к русскому.

Для быстрой проверки вёрстки можно остаться в редакторе: откройте Editor Preferences → Region & Language → Preview Game Language или выберите язык предпросмотра в UMG. Но результат может отличаться от работающей игры, поэтому окончательно проверяйте локализацию в Standalone и сборке. Localization Preview.

Чтобы перевод можно было прочитать

Проверить имя и вёрстку можно прямо в виджете. В UMG Designer откройте меню с глобусом над холстом, выберите культуру и сравните Vasya и Вася. Посмотрите, помещается ли текст в свои поля. Затем верните None, чтобы убрать принудительный предпросмотр.

UMG Designer с русским текстом в виджете; стрелка указывает на меню предпросмотра культуры с текущим значением None

На кадре меню стоит в положении None. Само переключение языка здесь не показано. Этот способ проверки я добавил в закреплённом комментарии к ролику; в видео его нет.

Если вместо букв видны квадраты, проверьте шрифт. Composite Font позволяет задать основное семейство и дополнительные Sub-Font Family для отдельных диапазонов символов. Например, оставить основной шрифт для латиницы, а кириллицу взять из другого. В выбранном Font Face должны быть нужные буквы. Font Asset and Editor.

Буквы появились — теперь проверьте длину строк. Перевод должен помещаться в кнопку, а при уменьшении окна не перекрывать соседние элементы. Предпросмотр помогает проверить вёрстку; работу выбора языка и его сохранение всё равно проверяйте в игре.

Храните изменённый шрифтовой ассет в проекте, чтобы его получили остальные участники команды. Изменения ресурса в папке установленного движка сами по себе в репозиторий игры не попадут. Это относится и к настройке шрифта встроенных субтитров: важно, какой файл вы меняете и где он хранится.

Добавляем субтитры к реплике

В этом примере субтитры выводит сам Unreal. Отдельный виджет для них делать не будем.

  1. Создайте в той же папке ST_Subtitle.
  2. Добавьте ключ Hello с исходным текстом Hello, friend!.
  3. Откройте Sound Wave с репликой, найдите раздел Subtitles и добавьте элемент.
  4. Укажите время появления текста относительно начала записи. Для приветствия, звучащего сразу, начните с 0 и проверьте синхронизацию.
  5. В поле текста выберите ссылку на ST_Subtitle, ключ Hello.
  6. Сохраните ассеты, выполните Gather Text, добавьте перевод Привет, друг и выполните Compile Text.
Sound Wave A_Privet: в массиве Subtitles задано время 0.0, а текст Hello, friend! связан с ключом Hello таблицы ST_Subtitle

▶ Смотреть настройку субтитра в видео — 10:13

В Sound Wave A_Privet раскрыт первый элемент массива Subtitles. Значение Time: 0.0 выводит строку с начала записи, а поле Text ссылается на ключ Hello таблицы ST_Subtitle. Благодаря этой ссылке движок берёт перевод для активной культуры вместо жёстко вписанной фразы.

Запустите Standalone и проиграйте реплику. Смените язык и запустите её ещё раз: субтитр должен перевестись. Если голос остался прежним, на этом этапе всё нормально — до озвучки мы ещё не дошли.

Если надпись не появилась, сначала убедитесь, что проигрывается именно настроенный Sound Wave и включён показ субтитров. Затем проверяйте время строки, ссылку на таблицу и скомпилированный перевод.

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

Локализуем озвучку

Подготовим английскую и русскую записи одной реплики. Перед работой выполните Compile Text в Localization Dashboard: меню Asset Localization использует наличие .locres для выбранной культуры. Это те самые ресурсы перевода, которые мы собрали выше. Они нужны для работы с культурами, но русскую аудиозапись мы добавим отдельно. Asset Localization.

1. Создайте локализованную копию. В исходном Sound Wave A_Privet оставьте английскую запись. Найдите его в MyGame/Sounds, щёлкните правой кнопкой и выберите Asset Localization → Create Localized Asset → Russian.

Для исходного Sound Wave открыто Asset Localization → Create Localized Asset → Russian

▶ Создание локализованного звука в видео — 15:06

2. Найдите русскую копию. В настройках Content Browser включите Show Localized Content. Движок сохраняет структуру исходных папок внутри L10N/ru:

Исходный Sound Wave: /Game/MyGame/Sounds/A_Privet
Русская копия:       /Game/L10N/ru/MyGame/Sounds/A_Privet

На следующем кадре показана нужная папка. Выделенный в ней A_Privet_Cue — Sound Cue; для замены самой записи найдите локализованный Sound Wave A_Privet.

Content Browser: папка Content/L10N/ru/MyGame/Sounds; в ней показан локализованный Sound Cue A_Privet_Cue

▶ Папка локализованных звуков в видео — 15:06

3. Замените запись. Убедитесь, что работаете с копией в L10N/ru. В её контекстном меню выберите Reimport With New File, укажите русскую запись и сохраните ассет.

В контекстном меню локализованного Sound Wave выбрана команда Reimport With New File

▶ Замена записи: раздел видео с 15:06

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

В ролике я показываю и Sound Cue, который случайно выбирает одну из нескольких реплик. Если набор реплик одинаков на обоих языках, удобно заменить отдельные Sound Wave. А если для русского готова только часть записей, можно локализовать сам Sound Cue и оставить в нём доступные варианты. Здесь выбор зависит от того, что именно нужно изменить: запись или весь набор реплик.

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

Почему текст уже русский, а голос ещё английский

Когда игре нужен звук или изображение, ассет загружается в память. Дальше компоненты используют уже загруженный объект. Смена культуры сама по себе не освобождает его и не подменяет все ссылки на другую языковую версию: автоматической перезагрузки локализованных ассетов во время игры нет. Ограничение Asset Localization.

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

Для надёжной проверки нашего примера сохраните язык, полностью закройте игру и запустите её заново. Культура должна быть выбрана до загрузки проверяемых ассетов. Перезагрузка одной карты не даёт той же гарантии: объекты могут оставаться в памяти через другие ссылки. Сначала проверьте русский запуск, затем так же английский.

Если текст, озвучка и картинки должны переключаться отдельно

Это уже отдельная задача для настроек игры. Set Current Culture меняет общий язык, региональные правила и сбрасывает переопределения культуры групп ассетов. Для независимого выбора используются Set Current Language для текста и Set Current Asset Group Culture для заранее настроенных групп классов ассетов. Например, в отдельную группу можно отнести звуковые ассеты. Управление языком и группами ассетов.

Но выбор культуры группы не решает вопрос памяти. Для переключения без перезапуска нужна логика, которая прекращает использование старого контента, управляет его загрузкой и обновляет ссылки у потребителей. Другой вариант — явно выбирать подготовленные звуки и текстуры своей системой настроек. Это требует отдельной реализации и проверки; одним повторным вызовом Set Current Culture такую систему не заменить.

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

Текстуры и материалы: выбираем уровень замены

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

В исходной текстуре оставьте базовое изображение. Найдите её в MyGame/Materials/Textures, откройте Asset Localization → Create Localized Asset и выберите Russian.

Для текстуры из папки MyGame/Materials/Textures открыто меню Asset Localization → Create Localized Asset → Russian; в сцене на стене виден российский флаг

▶ Смотреть локализацию текстуры в видео — 17:27

Откройте созданную копию внутри L10N/ru и замените изображение через Reimport With New File, как мы уже сделали со звуком. Сохраните ассет и проверьте оба языка отдельными запусками игры. Загруженная текстура не обязана обновляться сразу при переключении культуры.

На кадре в сцене виден российский флаг. Английский и русский результаты можно сравнить в галерее в начале статьи; при проверке локализованной текстуры полностью перезапускайте игру после смены культуры.

Так можно заменить не любой ассет: Blueprint и другие ассеты с байткодом через Asset Localization не локализуются. Перевести текст внутри Blueprint можно; заменить этим способом весь Blueprint — нет. Ограничения типов ассетов.

Перевод должен попасть в сборку

В Project Settings → Packaging найдите Localizations to Package и отметьте en и ru.

Project Settings → Packaging → Advanced: открыт список Localizations to Package, в видимой части отмечен English

▶ Смотреть настройку языков сборки в видео — 9:08

Кадр показывает, где находится список Localizations to Package. В видимой части отмечен English. Найдите в списке также Russian и выберите обе локализации. Состав готовой сборки проверим отдельным запуском.

Дополнение по документации Epic: в Project Settings → Packaging → Advanced проверьте Internationalization Support. Эта настройка определяет, какие данные ICU попадут в сборку. Для проекта с русским языком выберите All. В ролике этот параметр не показан. Packaging Localization Data.

После этого соберите игру и проверьте оба языка уже в готовом билде.

Перед упаковкой ещё раз пройдите Gather → проверка переводов → Compile.

Финальная проверка в Localization Dashboard: 1 — открыть Dashboard, 2 — Gather Text, 3 — открыть переводы нужной культуры, 4 — Compile Text

▶ Смотреть Gather Text в видео — 18:58 · ▶ Смотреть проверку перевода и Compile Text — 4:25

Цифры на кадре задают порядок: откройте Localization Dashboard и Target Game, выполните Gather Text, откройте перевод нужной культуры через кнопку в столбце Actions, проверьте и сохраните изменения, затем нажмите Compile Text. После этого запускайте саму сборку: успешная проверка в редакторе её не заменяет.

СценарийОжидаемый результат
Запуск с английскимАнглийские имя, субтитры, голос и изображение
Переключение на русскийТекст обновляется; уже загруженные ассеты могут остаться прежними
Закрытие и повторный запуск с сохранённым русскимРусские имя, субтитры, голос и изображение
Возврат к английскому и повторный запускВсе проверяемые элементы снова английские
Проверка меньшего окнаТекст не обрезан, кнопки доступны, субтитры читаются

Процент в Dashboard показывает, как обстоят дела с переводом строк. Даже если там всё переведено, озвучку, вёрстку и содержимое билда нужно проверить отдельно.

Если что-то пошло не так

СимптомЧто проверить сначала
Новая строка не найденаСохранение таблицы, путь Gather, повторный сбор
Перевод сохранён, но не появилсяCompile Text, активную культуру, ссылку поля на нужный ключ
Одно поле перевелось, другое нетНе осталось ли во втором поле независимо введённого текста
После изменения исходника перевод требует проверкиРаздел Needs Review: старый перевод может уже не соответствовать новому тексту
Буквы заменены квадратикамиНаличие глифов в шрифте и диапазоны Sub-Font Family
Текст русский, голос английскийЛокализованный ассет, выбранную культуру при загрузке и повторный запуск
В Standalone работает, в билде нетLocalizations to Package, Internationalization Support и актуальность собранных данных

А если у меня есть только готовая игра?

Об этом спрашивали в комментариях. Здесь мы работаем с исходным проектом: можем менять ассеты, настройки и собирать игру. Если у вас только чужой packaged build, извлекать перевод и делать патч придётся иначе. Способ зависит от конкретной игры и её упаковки; в этом уроке он не проверялся.

Практика: добавьте второй случай сами

Добавьте в виджет кнопку «Продолжить» и отдельную подсказку с тем же действием. Создайте для них одну запись в новой таблице ST_UI, переведите её и подключите к обоим элементам. Новую реплику персонажа добавьте в ST_Subtitle.

Задача выполнена, если:

  • кнопка и подсказка используют одну запись и переключаются вместе;
  • новая реплика появляется на обоих языках;
  • выбор языка сохраняется после закрытия игры;
  • проверка проходит в packaged build;
  • более длинный текст не ломает компоновку.

Теперь поменяйте исходный текст подсказки на предложение с другим смыслом. Должна ли вместе с ним измениться кнопка? Если нет, разделите ключи. Общая запись нужна там, где действительно нужен один и тот же текст.

Если что-то не работает, пройдите по цепочке: источник → сбор → перевод → компиляция → культура → отображение. Для звука и изображения проверьте ещё локализованный ассет и момент его загрузки. Так будет проще найти пропущенный шаг, чем менять настройки наугад.