На странице

Статья
Локализация в Unreal Engine: текст, субтитры, озвучка и текстуры
Настраиваем русский и английский языки в UE: String Tables, перевод UMG, субтитры и локализованные ассеты. Разбираемся, когда нужен перезапуск и как проверить сборку.
1
материал
Статья
формат
Опубликован
статус
Вы нажали «Русский». Кнопки перевелись, субтитры тоже, а персонаж продолжает говорить по-английски. Надпись на стене вообще делает вид, что ничего не произошло.
С переключением языка разбираемся в моём видеоуроке. Разберёмся на небольшой сцене: переведём имя персонажа, добавим субтитры, заменим озвучку и картинку на стене. По пути выясним, что меняется сразу, когда нужен перезапуск и почему перевод иногда теряется при сборке игры.
Удобнее смотреть? Вот видео
В ролике я показываю весь процесс в Unreal Engine 5.4 — от String Tables до проверки сборки. Он длится около 20 минут. Можно смотреть и повторять за мной, а к тексту возвращаться за нужной настройкой или разбором ошибки.
Если плеер не загрузился, откройте ролик на 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 и добавьте записи:
| Key | Source String |
|---|---|
| HeroName | Vasya |
| EnemyName | Ivan |
Сохраните таблицу. В нашем примере английский будет использоваться как язык игры по умолчанию, поэтому значения здесь тоже на английском.
▶ Смотреть создание String Table в видео — 3:03
В ST_Name две записи: EnemyName → Ivan и HeroName → Vasya. Слева — ключи, по которым обращаемся к тексту, справа — исходные значения. Переводы добавим через Localization Dashboard.
Теперь откройте тестовый виджет. У свойства Text первого текстового поля нажмите значок локализации возле значения, выберите ST_Name и ключ HeroName. Сделайте то же для второго поля. Скомпилируйте и сохраните виджет.
В обоих полях появится Vasya. Проверьте, что вы именно выбрали запись из таблицы. Если просто вписать имя руками, связи с таблицей не будет.
▶ Смотреть привязку 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/*; если у вас другая структура, укажите свой путь.
▶ Настройки сбора в видео — 1:10
Через Add New Culture добавьте English (en) и Russian (ru). Выберите английский как Native Culture, сохраните настройки и нажмите Gather Text.
▶ Языки и сбор текста в видео — 1:10
Native Culture — язык исходного текста. В вашем проекте он вполне может быть русским. Лучше определиться с ним в начале. Когда проект будет уже наполнен текстами и переводами, смену Native нужно готовить как отдельную миграцию. Localization Overview.
В строке Russian нажмите первую кнопку в столбце Actions. Подсказка Edit translations for this culture поможет найти её среди похожих значков.
▶ Открываем перевод в видео — 4:25
В Translation Editor переведите Vasya → Вася и Ivan → Иван. Нажмите 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.
▶ Смотреть переключение культуры в видео — 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, чтобы убрать принудительный предпросмотр.
На кадре меню стоит в положении None. Само переключение языка здесь не показано. Этот способ проверки я добавил в закреплённом комментарии к ролику; в видео его нет.
Если вместо букв видны квадраты, проверьте шрифт. Composite Font позволяет задать основное семейство и дополнительные Sub-Font Family для отдельных диапазонов символов. Например, оставить основной шрифт для латиницы, а кириллицу взять из другого. В выбранном Font Face должны быть нужные буквы. Font Asset and Editor.
Буквы появились — теперь проверьте длину строк. Перевод должен помещаться в кнопку, а при уменьшении окна не перекрывать соседние элементы. Предпросмотр помогает проверить вёрстку; работу выбора языка и его сохранение всё равно проверяйте в игре.
Храните изменённый шрифтовой ассет в проекте, чтобы его получили остальные участники команды. Изменения ресурса в папке установленного движка сами по себе в репозиторий игры не попадут. Это относится и к настройке шрифта встроенных субтитров: важно, какой файл вы меняете и где он хранится.
Добавляем субтитры к реплике
В этом примере субтитры выводит сам Unreal. Отдельный виджет для них делать не будем.
- Создайте в той же папке
ST_Subtitle. - Добавьте ключ
Helloс исходным текстомHello, friend!. - Откройте Sound Wave с репликой, найдите раздел Subtitles и добавьте элемент.
- Укажите время появления текста относительно начала записи. Для приветствия, звучащего сразу, начните с
0и проверьте синхронизацию. - В поле текста выберите ссылку на
ST_Subtitle, ключHello. - Сохраните ассеты, выполните Gather Text, добавьте перевод
Привет, други выполните Compile Text.
▶ Смотреть настройку субтитра в видео — 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.
▶ Создание локализованного звука в видео — 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.
▶ Папка локализованных звуков в видео — 15:06
3. Замените запись. Убедитесь, что работаете с копией в L10N/ru. В её контекстном меню выберите 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.
▶ Смотреть локализацию текстуры в видео — 17:27
Откройте созданную копию внутри L10N/ru и замените изображение через Reimport With New File, как мы уже сделали со звуком. Сохраните ассет и проверьте оба языка отдельными запусками игры. Загруженная текстура не обязана обновляться сразу при переключении культуры.
На кадре в сцене виден российский флаг. Английский и русский результаты можно сравнить в галерее в начале статьи; при проверке локализованной текстуры полностью перезапускайте игру после смены культуры.
Так можно заменить не любой ассет: Blueprint и другие ассеты с байткодом через Asset Localization не локализуются. Перевести текст внутри Blueprint можно; заменить этим способом весь Blueprint — нет. Ограничения типов ассетов.
Перевод должен попасть в сборку
В Project Settings → Packaging найдите Localizations to Package и отметьте en и ru.
▶ Смотреть настройку языков сборки в видео — 9:08
Кадр показывает, где находится список Localizations to Package. В видимой части отмечен English. Найдите в списке также Russian и выберите обе локализации. Состав готовой сборки проверим отдельным запуском.
Дополнение по документации Epic: в Project Settings → Packaging → Advanced проверьте Internationalization Support. Эта настройка определяет, какие данные ICU попадут в сборку. Для проекта с русским языком выберите All. В ролике этот параметр не показан. Packaging Localization Data.
После этого соберите игру и проверьте оба языка уже в готовом билде.
Перед упаковкой ещё раз пройдите Gather → проверка переводов → Compile.
▶ Смотреть 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;
- более длинный текст не ломает компоновку.
Теперь поменяйте исходный текст подсказки на предложение с другим смыслом. Должна ли вместе с ним измениться кнопка? Если нет, разделите ключи. Общая запись нужна там, где действительно нужен один и тот же текст.
Если что-то не работает, пройдите по цепочке: источник → сбор → перевод → компиляция → культура → отображение. Для звука и изображения проверьте ещё локализованный ассет и момент его загрузки. Так будет проще найти пропущенный шаг, чем менять настройки наугад.