Локализация интерфейсов и текстовых блоков игр
Локализация — это не перевод строк в таблицу. Это системная работа с текстом, шрифтами, форматированием, правилами склонения и размерами UI-элементов под каждый язык. Игра, которая «переведена», но не локализована, выглядит как машинный перевод: текст вылезает за кнопки, числа отображаются без учёта локали, арабский текст идёт слева направо.
Технический пайплайн локализации в Unity
Стандарт для Unity-проектов сейчас — пакет Unity Localization (com.unity.localization). Он работает через StringTable и AssetTable: StringTable хранит текстовые строки с ключами, AssetTable — локализованные ассеты (текстуры, аудио, шрифты). Таблицы экспортируются в CSV/XLIFF для передачи переводчикам и импортируются обратно.
Ключевой принцип: в коде и в Prefab'ах должны быть только ключи, никаких хардкоженных строк. LocalizedString на компоненте TextMeshProUGUI с привязкой к StringTable — обязательная архитектура. Нарушение этого правила означает, что при добавлении нового языка придётся вручную искать все текстовые строки по сцене — это сотни объектов.
Plural Rules — отдельная боль. В русском языке три формы числительных: «1 предмет», «2 предмета», «5 предметов». В английском — две. В арабском — шесть. Unity Localization поддерживает Plural через Smart String с форматированием {count:plural:предмет|предмета|предметов}, но правила для каждого языка нужно прописывать явно через Plural Rule Provider или использовать готовые правила из CLDR (Common Locale Data Repository).
Дата и числа: 1,234.56 (EN) vs 1.234,56 (DE) vs 1 234,56 (RU). Без явного использования CultureInfo при форматировании в C# числа отображаются в формате системной локали устройства — непредсказуемо. Все числа, валюты и даты должны форматироваться через string.Format(CultureInfo.GetCultureInfo(currentLocale), ...) или через Smart String с форматом {value:C} с явной привязкой локали.
Шрифты под разные языки: самая частая недооценённая проблема
CJK (китайский/японский/корейский) шрифт для TextMeshPro — это Font Asset с десятками тысяч глифов. Полный CJK Font Asset в SDF может весить 15–30 MB только для текстурного атласа. Для мобильного проекта с бюджетом памяти это неприемлемо.
Решение: Dynamic Font Asset с Population Mode → Dynamic. Атлас заполняется только теми глифами, которые реально встречаются в тексте. При первом запуске в памяти только несколько сотен использованных иероглифов. Минус — возможен микрофриз (0.5–2 мс) при первом рендере нового глифа. Для большинства игр это приемлемо.
Для арабского и иврита обязательна поддержка RTL (right-to-left). В TextMeshPro есть встроенный RTL режим, активируется через TMP_Text.isRightToLeftText = true. Но одного флага недостаточно: элементы UI тоже должны зеркалиться (кнопка «Назад» перемещается с левого края на правый, список читается справа налево). Это требует специальной логики в Layout Manager или переключаемых Prefab'ов с зеркальным layout'ом для RTL-языков.
Кейс: кириллица и перенос слов
На проекте с поддержкой русского, английского и немецкого столкнулись с тем, что немецкие составные слова (Geschwindigkeitsbegrenzung — «ограничение скорости») не переносятся в TextMeshPro по умолчанию, а просто вылезают за границу поля или переходят на новую строку целиком. Это ломало диалоговые окна: фиксированный размер контейнера, текст уходит за нижний край.
Решение: Hyphenation через TMP_Settings → Enable Word Wrapping + подключение словаря переносов для немецкого через пользовательский TMP_HyphenationDictionary. Формат словаря совместим со стандартом LibreOffice (TeX hyphenation patterns). После подключения немецкий текст корректно переносился по правилам, контейнер диалога перестал переполняться.
Инструменты и интеграция с переводчиками
Переводчики не работают в Unity. Стандартный workflow: Unity Localization → экспорт StringTable в XLIFF 1.2 или CSV → передача в CAT-инструмент (Phrase, memoQ, SDL Trados) → получение переведённых XLIFF → импорт обратно в Unity. Этот цикл должен быть автоматизирован через Editor-скрипт, иначе ручной импорт 15 языков × 20 таблиц = несколько часов работы при каждом обновлении строк.
Строки с форматированием (Smart String с плейсхолдерами {name} или {count}) должны сопровождаться инструкцией для переводчика: что означает плейсхолдер, в какой части фразы он может быть перемещён. В немецком {count} Gegenstände gefunden — плейсхолдер в начале, что нормально. В японском порядок слов другой, плейсхолдер может быть в конце. CAT-инструменты поддерживают защиту плейсхолдеров от случайного перевода.
Переключение языка в runtime без перезапуска
Unity Localization поддерживает смену языка в реальном времени через LocalizationSettings.SelectedLocale. Все компоненты с LocalizedString автоматически обновляются. Это хорошо работает для простых текстов, но требует внимания в нескольких ситуациях.
Шрифты при смене языка. Если японский требует отдельного Font Asset, а текущий — латинский, при переключении TextMeshPro компонент должен получить новый Font Asset. Unity Localization поддерживает AssetTable для локализованных ассетов, включая шрифты. Привязка через LocalizedAsset компонент на каждом TextMeshProUGUI — стандартный подход. Не забыть про Font Asset Creator с правильными глифами для каждого языка заранее.
Числовые значения с явным форматированием в коде при смене языка не обновляются автоматически — они выводятся через SetText() или string.Format() в момент обновления данных. Поэтому при смене языка нужно явно вызвать Refresh на всех компонентах, которые выводят форматированные числа. Удобно реализовать через событие LocalizationSettings.SelectedLocaleChanged и подписку в таких компонентах.
Размер UI-элементов. Немецкий текст в среднем на 30–40% длиннее английского, финский — ещё длиннее. При смене языка в runtime ContentSizeFitter автоматически пересчитывает размеры контейнеров, но только если LayoutRebuilder не был намеренно заморожен для производительности. На экранах с фиксированными кнопками обрезание текста при смене языка — частая проблема, которую лучше поймать на этапе псевдолокализации.
Тестирование локализации
Псевдолокализация — запуск UI с тестовыми строками увеличенной длины и случайными символами. Unity Localization имеет встроенный Pseudo Locale с опцией расширения строк на 30–40% (характерно для немецкого и финского по сравнению с английским оригиналом). Запускаем псевдолокаль ещё до появления реальных переводов — проблемы с переполнением текстовых полей видны сразу.
Проверка Missing Translation: Unity Localization логирует отсутствующие ключи в Console с предупреждением, но в продакшне это должно выводить fallback-значение, а не пустую строку. Настраивается через Localization Settings → Missing Translation Behavior.
| Масштаб | Сроки (без учёта времени перевода) |
|---|---|
| Добавление одного языка в готовый пайплайн | 3–7 дней |
| Построение пайплайна локализации с нуля (1–2 языка) | 1–3 недели |
| Полная локализация проекта (5–10 языков, RTL включая) | 4–10 недель |
| Интеграция с внешними CAT-инструментами + автоматизация | 1–3 недели |
Стоимость рассчитывается индивидуально после анализа объёма строк и поддерживаемых языков.





