Локализация
IcyUI показывает текст на языке игрока: разметка запрашивает строку по ключу через {Localize}, локализатор находит её
на текущем языке, а смена языка сразу обновляет все локализованные тексты.
Настройка
Выберите, где хранятся переводы, и передайте конфигурации локализатор. С файлами gettext .po, по одному на язык, в
папке Localization рядом с игрой:
Game.UseIcyUI(ui => ui
.ConfigureAssets()
.UsePoLocalization("Localization", CultureInfo.GetCultureInfo("en"))); // Localization/en.po, ru.po, ...
| Локализатор | Откуда строки | Подходит для |
|---|---|---|
| PoLocalizer | Файлы gettext .po, по одному на язык (en.po, ru.po, pt_BR.po). |
Большинства игр: переводчики работают в Poedit, Weblate или Crowdin, а игроки могут добавить язык без новой сборки. |
| ResourceManagerLocalizer | Ресурсы .resx, скомпилированные в игру. |
Проектов, которые уже используют ресурсы .NET. |
| DictionaryLocalizer | Строки, добавленные из кода. | Прототипов, тестов, нескольких встроенных строк. |
| CompositeLocalizer | Несколько локализаторов, опрашиваемых по порядку. | Переводов модов поверх перевода игры или запасного варианта. |
Подойдёт и любой другой источник: реализуйте ILocalizer — один метод, возвращающий строку для
ключа и культуры или null.
Культура откатывается к родительской, а затем к языку по умолчанию: для ru-RU — ru-RU.po, затем ru.po, затем
en.po. Ключ, не найденный нигде, показывается как есть, а IcyUI один раз пишет в журнал предупреждение (событие 4001).
Файл .po с ошибкой пропускается, как будто его нет, с предупреждением (событие 4002): опечатка в переводе от игрока
никогда не остановит игру.
В разметке
<!-- {Localize} shows the string for a key in the configuration's culture, and follows it when it changes. -->
<StackPanel Orientation="Vertical">
<TextBlock Text="{Localize Menu.Title}" />
<Button Content="{Localize Menu.Play}" />
</StackPanel>
{Localize Menu.Play}работает с любым свойством, принимающим текст. УContentстрока становитсяTextBlock, как и обычный текст.Context=различает два ключа с одинаковым текстом (msgctxtв gettext):{Localize Open, Context=Verb}.
Смена языка
Язык — это Culture конфигурации, та же настройка, в которой показываются числа:
configuration.Culture = CultureInfo.GetCultureInfo("ru"); // every {Localize} changes now
Каждый текст {Localize} меняется сразу. Привязка покажет числа в новом формате при следующем обновлении. По умолчанию
Culture следует языку интерфейса системы; задайте её, если у игры своя настройка языка.
Интерфейс, построенный в коде
score.Localize(nameof(TextBlock.Text), "Hud.Score");
Такой текст меняется вместе с языком, как {Localize}, а элемент, которого ещё нет на Canvas, получает текст при
добавлении. Configuration.Localize("Hud.Score") возвращает строку для кода, который сам форматирует текст.
Моды и слои
var mods = new PoLocalizer(configuration.Assets, "Mods/Localization"); // no default: only the player's language
var game = new PoLocalizer(configuration.Assets, "Localization", CultureInfo.GetCultureInfo("en"));
configuration.Assets.Localizer = new CompositeLocalizer(mods, game);
Язык по умолчанию задавайте только последнему локализатору. Слой мода с языком по умолчанию отвечал бы на любом языке строками этого языка, и перевод самой игры на язык игрока никогда бы не запрашивался.
Производительность
Локализованный текст стоит одного поиска при загрузке и одной небольшой записи, чтобы он мог сменить язык. Каждый файл
.po читается один раз — когда его язык понадобился впервые. Смена языка обновляет каждый локализованный текст один раз;
между сменами ничего не выполняется.
Типичные ошибки
- Собственный текст навсегда заменяет локализованный. Если вы сами задаёте локализованное свойство (счёт, имя игрока), оно перестаёт меняться вместе с языком.
- Стили не переключаются.
{Localize}в установщике стиля читается один раз, при загрузке стиля. Ставьте его у элементов или в шаблоне. - Недостающие символы. Шрифт без кириллицы или CJK не покажет эти языки; выберите шрифт, который покрывает ваши языки.
- Аргументы.
"Score: {0}"пока не заполняется автоматически: форматируйте его в коде черезConfiguration.Localize.
См. также
- Привязка данных — числа в текущей культуре.
- Конфигурация.