Данная статья предназначена для тех, кто хотел бы сделать свой сервер, либо отдельный плагин мультиязычным. Для этого существуют словари - файлы, содержащие в себе набор переменных, каждой из которых присвоено своё значение (слово или фраза на одном или нескольких языках). Эта статья как раз и посвящена словарям, точнее, работе с ними. Не будем углубляться в теорию, тем более, что, в данном случае, её почти и нет, разберём всё подробно на практике...
Практическая часть:
Для начала нам необходимо зарегистрировать наш файл словаря:
#include <amxmodx>
#pragma semicolon 1
public plugin_init()
{
register_plugin("Test Dictionary", "0.1a", "[onserver.org] #dev.tm");
register_dictionary("test_dictionary.txt"); // регистрация нового файла словаря с именем 'test_dictionary.txt'
}
По умолчанию файл должен находиться в директории ./cstrike/addons/amxmodx/data/lang. В файле словаря (test_dictionary.txt) пишем текст следующего содержания:
[en]
TD_HELLO = Hello, world!
[ru]
TD_HELLO = Привет, мир!
TD_HELLO = Hello, world!
[ru]
TD_HELLO = Привет, мир!
Сохраняем файл в кодировке UTF-8 без BOM. Рассмотрим, что же мы написали. Мы создали файл словаря, который поддерживает перевод на два языка: английский и русский. en и ru - это значения ключа lang (setinfo "lang" "en"). TD_HELLO - это переменная, Hello, world! и Привет, мир! - её значения для английского и русского языков, соответственно. Переменные, расположенные ниже строки [en], относятся к переводу на английский язык. Соответственно, переменные, расположенные ниже строки [ru], относятся к переводу на русский язык. Теперь зарегистрируем команду, при выполнении которой всем игрокам в чат будет выводиться наше сообщение:
#include <amxmodx>
#pragma semicolon 1
public plugin_init()
{
register_plugin("Test Dictionary", "0.1a", "[onserver.org] #dev.tm");
register_dictionary("test_dictionary.txt");
register_clcmd("say /hello", "CmdHello"); // регистрация команды /hello для отправки сообщения всем игрокам (общий чат)
register_clcmd("say_team /hello", "CmdHello"); // регистрация команды /hello для отправки сообщения всем игрокам (командный чат)
}
Добавим функцию обработки команды /hello (вывода сообщения):
#include <amxmodx>
#pragma semicolon 1
public plugin_init()
{
register_plugin("Test Dictionary", "0.1a", "[onserver.org] #dev.tm");
register_dictionary("test_dictionary.txt");
register_clcmd("say /hello", "CmdHello");
register_clcmd("say_team /hello", "CmdHello");
}
public CmdHello()
{
client_print(0, print_chat, "%L", LANG_PLAYER, "TD_HELLO"); // отправка нашего сообщения всем игрокам
return PLUGIN_HANDLED; // блокировка отправки команды /hello
}
Мы получили простейшую функцию вывода сообщения 'Hello, world!' или 'Привет, мир!' (в зависимости от языковых настроек игрока-получателя сообщения) по команде /hello. Как вы, наверное, уже поняли, символы %L в сообщении заменяются на то значение, которое соответствует переменной TD_HELLO. Добавим в сообщение никнейм игрока, который вызывает эту функцию (выполняет команду /hello):
#include <amxmodx>
#pragma semicolon 1
public plugin_init()
{
register_plugin("Test Dictionary", "0.1a", "[onserver.org] #dev.tm");
register_dictionary("test_dictionary.txt");
register_clcmd("say /hello", "CmdHello");
register_clcmd("say_team /hello", "CmdHello");
}
public CmdHello(const id)
{
new szName[32]; // объявление нового массива szName
get_user_name(id, szName, charsmax(szName)); // получение никнейма игрока, который выполнил команду /hello, в массив szName
client_print(0, print_chat, "%s: %L", szName, LANG_PLAYER, "TD_HELLO");
return PLUGIN_HANDLED;
}
Теперь наше сообщение имеет вид: 'Player: Hello, world!' или 'Player: Привет, мир!'. В данном случае мы использовали константу LANG_PLAYER (также можно использовать константу LANG_SERVER, либо индекс получателя, но об этом чуть позже). Обратите внимание, что константа LANG_PLAYER располагается всегда перед переменной TD_HELLO и между ними не должно быть никаких иных аргументов. То есть, подобные варианты:
client_print(0, print_chat, "%s: %L", LANG_PLAYER, szName, "TD_HELLO");
client_print(0, print_chat, "%s: %L", szName, "TD_HELLO", LANG_PLAYER);
ошибочны и, либо не будут работать вовсе, либо будут работать некорректно. Также для каждой переменной должна быть объявлена своя константа. Рассмотрим на конкретном примере. Добавим в файл словаря ещё одну переменную:
[en]
TD_HELLO = Hello, world!
TD_SAID = said
[ru]
TD_HELLO = Привет, мир!
TD_SAID = сказал
TD_HELLO = Hello, world!
TD_SAID = said
[ru]
TD_HELLO = Привет, мир!
TD_SAID = сказал
Добавим новую переменную в наше сообщение:
#include <amxmodx>
#pragma semicolon 1
public plugin_init()
{
register_plugin("Test Dictionary", "0.1a", "[onserver.org] #dev.tm");
register_dictionary("test_dictionary.txt");
register_clcmd("say /hello", "CmdHello");
register_clcmd("say_team /hello", "CmdHello");
}
public CmdHello(const id)
{
new szName[32];
get_user_name(id, szName, charsmax(szName));
client_print(0, print_chat, "%L (%L %s)", LANG_PLAYER, "TD_HELLO", LANG_PLAYER, "TD_SAID", szName);
return PLUGIN_HANDLED;
}
Теперь сообщение приняло следующий вид: 'Hello, world! (said Player)' или 'Привет, мир! (сказал Player)'. С основной частью разобрались, переходим к деталям. Разберём, в каких случаях необходимо использовать константы LANG_PLAYER, LANG_SERVER и индекс получателя.
LANG_PLAYER необходимо использовать в тех случаях, когда индекс получателя заранее неизвестен. Например, при отправке сообщения всем игрокам, что мы и делали выше. Во всех остальных случаях желательно использовать индекс получателя. Рассмотрим пример. Добавим в словарь ещё одну переменную:
[en]
TD_HELLO = Hello, world!
TD_SAID = said
TD_HEALTH = Your health
[ru]
TD_HELLO = Привет, мир!
TD_SAID = сказал
TD_HEALTH = Ваше здоровье
TD_HELLO = Hello, world!
TD_SAID = said
TD_HEALTH = Your health
[ru]
TD_HELLO = Привет, мир!
TD_SAID = сказал
TD_HEALTH = Ваше здоровье
Немного изменим наш код:
#include <amxmodx>
#pragma semicolon 1
public plugin_init()
{
register_plugin("Test Dictionary", "0.1a", "[onserver.org] #dev.tm");
register_dictionary("test_dictionary.txt");
register_clcmd("say /health", "CmdHealth"); // замена команды /hello на /health (общий чат)
register_clcmd("say_team /health", "CmdHealth"); // замена команды /hello на /health (командный чат)
}
public CmdHealth(const id)
{
client_print(id, print_chat, "%L: %d", id, "TD_HEALTH", get_user_health(id)); // отправка сообщения игроку, выполнившему команду /health
return PLUGIN_HANDLED;
}
Теперь наше сообщение имеет вид: 'Your health: 100' или 'Ваше здоровье: 100'. Как видите, вместо константы LANG_PLAYER перед переменной TD_HEALTH расположен индекс получателя, id, на языковые настройки которого и будет сориентирована система при отправке сообщения.
LANG_SERVER необходимо использовать в тех случаях, когда вы хотите, чтобы при отправке сообщения или его форматировании система была сориентирована на языковые настройки сервера. Также эту константу можно использовать в тех же случаях, что и LANG_PLAYER (то есть, если индекс получателя заранее неизвестен). На практике используется достаточно редко, но, иногда, бывает весьма полезной для решения нестандартных задач.
Важные детали:
Ну и последние детали, на которые следует обратить внимание. Как при составлении файла словаря правильно называть переменные. Я не случайно в начале каждой переменной указал префикс TD_ (первые буквы от названия плагина, 'Test Dictionary'). Переменные с одинаковыми именами могут "пересекаться" между собой, в результате чего мы можем наблюдать в сообщениях плагина совсем не тот текст, который указан в нашем файле словаря. Чтобы этого не случалось, нужно просто не допускать появления переменных с одинаковыми именами в разных файлах словаря.
И ещё один небольшой, но не менее важный нюанс, о котором следует знать и помнить: имена переменных чувствительны к регистру символов, то есть, TD_HEALTH и TD_health - это две разные переменные и при подобных несовпадениях мы получим ошибку типа ML_NOTFOUND: TD_HEALTH, которая означает, что переменная TD_HEALTH не найдена в файле словаря.
Источник: onserver.org