Рано или поздно пусть даже небольшой успешный проект вам захочется показать не только своим друзьям, но и более широкой публике из других стран. Для того, чтобы всё больше и больше людей прониклись вашей «гениальной» идеей, необходимо осуществить перевод всех текстовых надписей и подписей на понятный язык его «нативных» обитателей.
В статье покажу как можно достаточно быстро написать свой менеджер локализации, параллельно сделаем несложное главное меню и меню выбора языка на Unity. У нас выбор языков будет состоять из 3-х: английский, немецкий и, конечно, русский.
Именно так будут выглядеть локализованное главное меню на 3 языках в итоговом варианте:
Для разработки будем использовать Unity3D и C#.
Базовые приготовления
Для начала создадим проект в Unity, создадим сцену, состоящую из: камеры; пустого элемента «Menu» типа «Gameobject»; текстуры типа «GUITexture» с привязанной интересной картинкой, которая будет использована в качестве фона; пустой текстуры с логотипом «unity». Жмём «Play».
Создаем файл локализации
Есть несколько вариантов организации и хранения данных локализации:
Моноязычное хранение – данные (текст, диалоги, названия ваших аудио-файлов, и т.д.) будут содержаться в каждом отдельном файле, например, русский в Russian.xml, а какой-нибудь Chinese – соответственно в Chinese.xml
Мультиязычное хранение – тут все данные хранятся в одном файле, что называется «all in one». Кто-то, возможно, скажет, что неудобно хранить в одном файле, но для проектов с малым объемом локализуемых данных, это самое «оно».
Второй вариант будет сбалансированным решением для нашей небольшой задачи, хотя первый более удобный с точки зрения организации проекта с локализацией на большое количество языков.
Для хранения текстовых данных будем использовать наиболее подходящий для этого тип – XML.
Формат данных нашего xml-файла выглядит следующим образом:
<?xml version="1.0" encoding="UTF-8" ?>
<Settings>
<meta>
<Name>Project</Name>
<version>1.0</version>
<language>Multilingual</language>
</meta>
<group id="Menu">
<string id="Play">
<text lang="en">Play</text>
<text lang="ru">Играть</text>
<text lang="de">Spielen</text>
</string>
</group>
</Settings>
Внутри элемента «meta» могут содержать общие данные вашего проекта, например, название, версию, данные для проверки оригинальности и целостности файла.
Элемент «group id» мы используем для названий главного меню, его также можно использовать для названия различных второстепенных меню, названий локаций, и т.д.
Элемент «string id», содержит те самые поля данных, которые должны быть локализованы.
Менеджер локализации
Теперь переходим непосредственно к созданию скриптов.
Создадим класс и скрипт «LangManager.cs», это и будет основной скрипт менеджера локализации.
Первое, свой тип данных. У нас, как было уже указано, будет 3 языка:
enum LangType { en = 0, ru, de };
Соответственно, переменная и свойство для хранения текущего языка, по умолчанию будет английский:
private static LangType _curLanguage = LangType.en;
public static LangType currentLanguage
{
get { return _curLanguage; }
set { _curLanguage = value; }
}
Второе, это функция подзагрузки файла:
XmlDocument root = new XmlDocument();
if (!File.Exists(LanguagesFileName))
{
Debug.Log("Lang file is not find in directory");
return;
}
root.LoadXml(File.ReadAllText(LanguagesFileName));
string language = root.SelectSingleNode("Settings/meta/language").InnerText;
if (language != "Multilingual" || grouping != "Multi")
{
Debug.Log("Lang file is wrong");
return;
}
isLoaded = true;
«LanguagesFileName» — переменная типа «string», путь к файлу локализации, например, LanguagesFileName = @"/Settings/Languages.xml"
Третье, функция получения локализованных данных, в зависимости от типа текущего языка. (Некоторые могут сказать, что не очень эффективно и следует использовать словари. Но, как говорится, «nobody cares»).
public static string Text(string levelName, string id)
{
string xPath = "localizableSettings/group[@id='" + levelName + "']/string[@id='" + id + "']/text[@lang='" + _curLanguage.ToString() + "']";
XmlNode xValue = root.SelectSingleNode(xPath);
if (xValue != null)
return xValue.InnerText;
else
return "Not been translated";
}
В случае отсутствия данных по запрашиваемому полю, будет показана надпись «not been translated».
Конечно же, каждый может добавить свои фирменные «плюшки». Итак, базовый менеджер локализации получен.
Создание и локализация меню
Первое, что делаем создаем скрипт и привязываем его к игровому объекту Menu.
В скрипте при запуске определяем загружен ли файл локализации, если ещё нет, то подгружаем.
void Start ()
{
if (!LangManager.isLoaded)
LangManager.LoadLanguageXml();
}
Рендеринг всех элементов меню осуществляется внутри функции «OnGUI».
«ScreenX» и «ScreenY» – координаты левого верхнего угла области, где будет начинаться меню;
«areaWidth» и «areaHeight» – размеры области, ширина и высота;
«currentPage» – переменная собственного типа «Page», используется для определения «в каком меню мы находимся».
void OnGUI()
{
GUILayout.BeginArea(new Rect(ScreenX, ScreenY, areaWidth, areaHeight));
switch (currentPage)
{
case Page.MainMenu:
{
MainMenu();
break;
}
case Page.Language:
{
LanguageMenu();
break;
}
}
GUILayout.EndArea();
}
Непосредственно функция создания самих кнопок в главном меню. Внутри можно дописать свои собственные обработчики нажатий, например, загрузка уровня или нового меню.
void MainMenu()
{
if (GUILayout.Button(LangManager.Text("Menu", "Play")))
{
//обработка нажатия
}
if (GUILayout.Button(LangManager.Text("Menu", "Options")))
{
//обработка нажатия
}
if (GUILayout.Button(LangManager.Text("Menu", "Language"))
{
currentPage = Page.Language;
}
if (GUILayout.Button(LangManager.Text("Menu", "Credits")))
{
//обработка нажатия
}
if (GUILayout.Button(LangManager.Text("Menu", "Quit")
{
//обработка нажатия
}
}
Для каждого языка будет свой собственный шрифт, поэтому объявляем соотвествующие переменные:
public Font en_font;
public Font ru_font;
public Font de_font;
Назначаем каждой переменной желаемый шрифт:
Меню выбора языка:
void LanguageMenu()
{
if (GUILayout.Button("English"))
{
LangManager.currentLanguage = LangManager.LangType.en;
menuManager.menuSkin.font = en_font;
}
if (GUILayout.Button("Русский"))
{
LangManager.currentLanguage = LangManager.LangType.ru;
menuManager.menuSkin.font = ru_font;
}
if (GUILayout.Button("Deutsch"))
{
LangManager.currentLanguage = LangManager.LangType.de;
menuManager.menuSkin.font = de_font;
}
if (GUILayout.Button(LangManager.Text("Menu", "Back")))
{
currentPage = Page.MainMenu;
}
}
Сохраняем, жмём «Play».
У меня получилось такое главное меню и меню выбора языка (русский вариант):
В конечном итоге, получаем привлекательную картинку, которую при желании можно распечатать и повесить на стену:
Альтернативы
В Unity Asset Store есть вполне пригодные для использования наработки (в виде расширения для Unity3D). И даже со специальным разделом Editor
Extension/Language.
Бесплатный вариант – Language Manager.
Если, покупать официально, то можно взглянуть на:
- Smart Localization – за 20$.
- Language Localization – за 10$.
- Language Internationalization – за 2$.
- Localization System – за 2$.
- Localising – за 25$.
Заключение
Желание, немножко терпения и всё готово!
UPD: Устранены недоработки, учтены пожелания хабрапользователей
1) удален индуссо-код;
2) добавлены новые шрифты, в том числе для кириллицы.
Всем участвующим в дисскусии, а также HomoLuden, Gafs, — спасибо за ваши вполне обоснованные замечания и предложения!
Автор: LeoMan