|
OKStyle
| Дата: Понедельник, 22.12.2014, 11:07 | Сообщение # 1 |
 Архивариус
Группа: Администраторы
Зарегистрирован: 19.02.2011
Сообщений: 125
Репутация: 8
Статус: Offline
| Многие задавались вопросом, как же реализовать на сервере поддержку мультиязычного интерфейса. Мной были перепробованы различные варианты, некоторые из которых я сегодня покажу.
Начнём с самого быстрого, действенного и не требующего дополнительных файлов, но требующего перекомпиляцию мода при внесении исправлений в текст - Массив.
Код new Language[2][2][144] = { // 2 - кол-во языков, 2 - кол-во строк текста, 144 - максимальная длина текста { {" Text 1 Text 1 Text 1 "}, {" Text 2 %s 2 Text 2 "} }, { {" Текст 1 Текст 1 Текст 1 "}, {" Текст 2 %s 2 Текст 2 "} } };
При входе устанавливайте игроку язык интерфейса (в зависимости от национальности целевой аудитории... представим, что у нас она - русскоязычная): Код SetPVarInt(playerid, "Language", 1); // 0 - пусть будет по-умолчанию английский, а 1 - русский
Используется так: Код if(strcmp(cmdtext, "/rus1", true) == 0) { SetPVarInt(playerid, "Language", 1); // для тестирования, у вас установка переменной должна быть в аккаунте игрока (при реге или с возможностью изменения) SendClientMessage(playerid, 0xFDE39DFF, Language[GetPVarInt(playerid, "Language")][0]); new string[128], PlayerName[MAX_PLAYER_NAME]; GetPlayerName(playerid, PlayerName, sizeof(PlayerName)); format(string, sizeof(string), Language[GetPVarInt(playerid, "Language")][1], PlayerName); SendClientMessage(playerid, 0xFDE39DFF, string); return 1; } if(strcmp(cmdtext, "/eng1", true) == 0) { SetPVarInt(playerid, "Language", 0); SendClientMessage(playerid, 0xFDE39DFF, Language[GetPVarInt(playerid, "Language")][0]); new string[128], PlayerName[MAX_PLAYER_NAME]; GetPlayerName(playerid, PlayerName, sizeof(PlayerName)); format(string, sizeof(string), Language[GetPVarInt(playerid, "Language")][1], PlayerName); SendClientMessage(playerid, 0xFDE39DFF, string); return 1; }
Второй вариант мультиязычность - это Дефайны. В этом случае мы присваиваем константам определённый текст для каждого языка.
Самый сложный пример: Код #define RUS_TEXT_ONE "Текст текст текст" #define RUS_TEXT_TWO "Текст %s текст" #define ENG_TEXT_ONE "Text text text" #define ENG_TEXT_TWO "Text %s text"
Опять введём переменную, отвечающую за язык и посмотрим пример использования: Код SetPVarInt(playerid, "Language", 0);
Самый простой вариант: Код if(GetPVarInt(playerid, "Language") == 1) return SendClientMessage(playerid, 0xFDE39DFF, RUS_TEXT_ONE); else SendClientMessage(playerid, 0xFDE39DFF, ENG_TEXT_ONE);
Сложный вариант (с внутренним форматированием): Код if(strcmp(cmdtext, "/rus2", true) == 0) { SetPVarInt(playerid, "Language", 1); if(GetPVarInt(playerid, "Language") == 1) { SendClientMessage(playerid, 0xFDE39DFF, RUS_TEXT_ONE); new string[128], PlayerName[MAX_PLAYER_NAME]; GetPlayerName(playerid, PlayerName, sizeof(PlayerName)); format(string, sizeof(string), RUS_TEXT_TWO, PlayerName); SendClientMessage(playerid, 0xFDE39DFF, string); } else { SendClientMessage(playerid, 0xFDE39DFF, ENG_TEXT_ONE); new string[128], PlayerName[MAX_PLAYER_NAME]; GetPlayerName(playerid, PlayerName, sizeof(PlayerName)); format(string, sizeof(string), ENG_TEXT_TWO, PlayerName); SendClientMessage(playerid, 0xFDE39DFF, string); } return 1; } if(strcmp(cmdtext, "/eng2", true) == 0) { SetPVarInt(playerid, "Language", 0); if(GetPVarInt(playerid, "Language") == 1) { SendClientMessage(playerid, 0xFDE39DFF, RUS_TEXT_ONE); new string[128], PlayerName[MAX_PLAYER_NAME]; GetPlayerName(playerid, PlayerName, sizeof(PlayerName)); format(string, sizeof(string), RUS_TEXT_TWO, PlayerName); SendClientMessage(playerid, 0xFDE39DFF, string); } else { SendClientMessage(playerid, 0xFDE39DFF, ENG_TEXT_ONE); new string[128], PlayerName[MAX_PLAYER_NAME]; GetPlayerName(playerid, PlayerName, sizeof(PlayerName)); format(string, sizeof(string), ENG_TEXT_TWO, PlayerName); SendClientMessage(playerid, 0xFDE39DFF, string); } return 1; }
Как вы понимаете, нерентабельно для каждого вывода текста ставить условие по языку. В вдруг их не 2, а 10? Код будет заспамлен условиями. Поэтому есть вариант попроще (с дополнительными функциями): http://pawno-info.ru/showthread.php?t=193903 (не мешало бы объединить темы).
Однако есть и более простой и действенный способ, который был реализован [RSAH]SeriouS в его моде Premium A/D - Файлы. Поскольку исходников мода не выкладывалось, реализацию я сделал собственную. Не могу утверждать, что она лучше оригинала (в моде), но попробуйте.
Для начала тоже установим игроку переменную языка, но в этом случае я рекомендую использовать сразу название файла с текстом, либо ввести массив соответствия языков файлам.
Код SetPVarString(playerid, "Language", "russian.lng");
Далее в нужный момент времени надо показать игроку необходимый текст. На mxINI это будет выглядеть так: Код new string[128], string2[128], languagefile[32]; GetPVarString(playerid, "Language", languagefile, sizeof(languagefile)); new iniFile = ini_openFile(languagefile); if(iniFile < 0) return printf("Не удалось найти файл с переводом для данного языка %s.", languagefile); ini_getString(iniFile, "Text_0001", string, sizeof(string)); ini_getString(iniFile, "Text_0002", string2, sizeof(string2)); ini_closeFile(iniFile); SendClientMessage(playerid, 0xFDE39DFF, string); new PlayerName[MAX_PLAYER_NAME]; GetPlayerName(playerid, PlayerName, sizeof(PlayerName)); format(string2, sizeof(string2), string2, PlayerName); // поскольку текст содержит маркер форматирования %s, вставляем туда имя игрока SendClientMessage(playerid, 0xFDE39DFF, string2);
Пример подобран для показа способов форматирования получаемого текста. Тот же код на Dini: Код new string[128], languagefile[32]; GetPVarString(playerid, "Language", languagefile, sizeof(languagefile)); SendClientMessage(playerid, 0xFDE39DFF, dini_Get(languagefile, "Text_0001")); new PlayerName[MAX_PLAYER_NAME]; GetPlayerName(playerid, PlayerName, sizeof(PlayerName)); format(string, sizeof(string), dini_Get(languagefile, "Text_0002"), PlayerName); SendClientMessage(playerid, 0xFDE39DFF, string);
Содержимое файла russian.lng: Код Text_0001 = (ИНФО) Добро пожаловать на наш сервер! Text_0002 = (ИНФО) Общие настройки в профиле "%s" были загружены.
Содержимое файла english.lng: Код Text_0001= (INFO) Welcome to our server! Text_0002= (INFO) General settings from profile "%s" have been loaded.
Урок написан с надеждой на то, что те, кто будет его читать, уже работали с mxINI или Dini. В принципе, ничего сложного в них нет.
Полный листинг кода скрипта с тестом скорости представлен в приложенном к сообщению *.pwn-файле.
Тесты скорости для одной форматируемой строки:
Для 2-х строк (одна неформатируемая, другая форматируемая):
Разница между Dini и mxINI в том, что у первого открытие файла и чтение ключа происходит в самой функции получения информации, а у mxINI надо всё делать самому. Но во втором случае можно прочитать сразу все строки и записать их в переменные. Если текст на сервере относится совершенно к разным моментам игры, то я посоветую использовать первый вариант (Dini). И хочу спасибо сказать Stepashka за наводку на принцип форматирования скрытого маркера.
Автор: OKStyle
|
| |
| |