Главная | Комментарии | О проекте
Чтение RSS
Суперсайт
Главная Контакты Карта сайта Добавить в избранное
  • Кто OnLine

    Всего на сайте: 5
    Гостей: 3
    Пользователи: - отсутствуют
    Роботы: robot Bot, crawl Bot

    Опрос пользователей

    Для какого мода Вы пишите плагины?

    • Популярное

    Рекомендуем

    • AMX Mod X
    • up.org.ua

    Наши друзья


  • Автор: Subb98 Дата: 19-02-2014, 21:11 Просмотров: 4302

    Урок 25. Работа со словарями

    Введение:
    Данная статья предназначена для тех, кто хотел бы сделать свой сервер, либо отдельный плагин мультиязычным. Для этого существуют словари - файлы, содержащие в себе набор переменных, каждой из которых присвоено своё значение (слово или фраза на одном или нескольких языках). Эта статья как раз и посвящена словарям, точнее, работе с ними. Не будем углубляться в теорию, тем более, что, в данном случае, её почти и нет, разберём всё подробно на практике...

    Практическая часть:
    Для начала нам необходимо зарегистрировать наш файл словаря:
    #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 = Привет, мир!

    Сохраняем файл в кодировке 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 = сказал

    Добавим новую переменную в наше сообщение:
    #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 = Ваше здоровье

    Немного изменим наш код:
    #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
    Уважаемый посетитель, Вы зашли на сайт как незарегистрированный пользователь.
    Мы рекомендуем Вам зарегистрироваться либо войти на сайт под своим именем.
    Урок 25. Работа со словарями
    Diablo

    --
    ICQ: --
    Публикаций: 0
    Комментариев: 0
    Репутация: -  0  +

    Благодарю!)
    Leyb

    --
    ICQ: --
    Публикаций: 0
    Комментариев: 0
    Репутация: -  0  +

    wink норм bully
    kostya06051995

    --
    ICQ: --
    Публикаций: 0
    Комментариев: 0
    Репутация: -  0  +

    Отлично!
    Я очень внимательно прочитал, но не понял одного:
    откуда вы узнали про ключ lang и какие еще есть стандартные ключи?
    gavrilyuc

    --
    ICQ: --
    Публикаций: 0
    Комментариев: 0
    Репутация: -  0  +

    kostya06051995, Ключ который ты указываешь как %L это те ключи которые ты как бы указал в *.txt файле.
    то есть:
    [Key] = [Value]

    Например: в *.txt.
    ЛюбоеСмысловое_и_Уникальное_Название = Добро пожаловать! Дорогой Пользователь.

    в исходе:
    client_print(id, print_chat, "%L", id, "ЛюбоеСмысловое_и_Уникальное_Название");



    Такой подход очень часто используется для каких-то "Своих" кваров, как у ZP в файле zombieplague.ini

    более подробно вот здесь:
    https://wiki.alliedmods.net/Advanced_Scripting_(AMX_Mod_X)#Multi-Lingual_Support
    Maksovich

    --
    ICQ: --
    Публикаций: 0
    Комментариев: 0
    Репутация: -  0  +

    Для чего нужно #pragma semicolon 1? Я так понял это для обработки точки с запятой в конце строк чтобы показать компилятору где точно строка кончается. Опишите подробнее. Или где можно подробнее, желательно на русском, почитать про #if, #include, #pragma, #define и.т.п.
    gavrilyuc

    --
    ICQ: --
    Публикаций: 0
    Комментариев: 0
    Репутация: -  0  +

    Maksovich,
    команды начинающие на # это команды компилятору.
    Я вроде ещё не находил что бы спец. для павна на русском...
    но вот в статьях про плюсы, 100% есть русское описание...
    Safety1st

    5.08.2014
    ICQ: --
    Публикаций: 8
    Комментариев: 42
    Репутация: -  9  +

    Maksovich, #pragma semicolon 1 нужно, если хочется, чтобы компилятор обращал внимание на все строки, не завершённые точкой с запятой. В pawn'е такого требования нет, а вот в C++, Например, они обязательны.
    --------------------

    Информация

    Посетители, находящиеся в группе Гости, не могут оставлять комментарии к данной публикации.
Наверх

Реклама