суббота, 19 апреля 2008 г.

Поддержка нескольких языков приложением

При разработке коммерческих приложений рано или поздно придется столкнуться с проблемой локализации. Как правило, если сразу этот вопрос не был рассмотрен, то появляется множество проблем при попытке перевести свой программный продукт на другие языкы. Большниство новичков даже не знают, что из себя представляет Unicode и как с ним работать. На dtf.ru недавно появилась небольшая статья, которая показывает в каком направлении надо двигаться.

Мы живем в таком замечательном мире, в котором игра, сделанная в одной стране, легко может продаваться в другой. Впрочем, не всегда так "легко", как хотелось бы. Потому что кроме географического барьера вашей игре придется преодолеть барьер языковой.

На Земле насчитывается более 5000 языков. А финальный вариант стандарта ISO 639-3 (трехбуквенные языковые коды), учитывающий даже диалекты мертвых языков, содержит целых 7589 записей.
Очевидно, что языковое разнообразие вашей игры будет описываться значительно более скромными цифрами; не менее очевиден ваш интерес в том, чтобы какое-то разнообразие было. Однако никто не любит долго заниматься локализацией, поэтому ее неизбежность должна заставлять задуматься над правильной организацией процесса.

По моим подсчетам, на тему локализации на различных КРИ было прочитано 5 докладов, что указывает на определенный интерес коллег к этой теме. Особое внимание заслуживает доклад "Бумеранг, написание локализуемой игры", сделанный в 2003 году Юрием Блажевичем и Василием Подобедом. Доклад содержит в себе ряд правил, следование которым поможет быстро достичь счастья всем участникам процесса локализации. Полное содержание доклада вы можете получить с сайта КРИ, я же позволю себе уточнить и раскрыть некоторые аспекты.

Мы, как и многие другие разработчики, когда-то столкнулись с необходимостью локализации своих игр. В этой статье я опишу, как мы реализовали перевод одного из игровых ресурсов - текстовых данных, и предложу наш инструмент для упрощения и улучшения такого перевода.

Олег Смирнов

Продолжение...

Object Iterators

Методы end() и begin() возвращают luabind::iterator, который можно использовать для перебора всех элементов в таблице luabind::object. Так же есть другой тип итератора — luabind::functor, который позволяет перебрать все функции в таблице (более подробно можно прочитать в документации к luabind).

Метод is_valid и оператор bool

Метод is_valid и оператор bool позволяют проверить является ли полученный luabind::object рабочим:


//получаем глобальную табилцу lua объекту luabind::object
luabind::object MyObject = get_globals(pLua);

//проверяем действителен ли объект
if (MyObject.is_valid())
{
DoSomething(MyObject[key]);
}


Так же возможен такой вариант:


if (MyObject)
{
DoSomething(MyObject[key]);
}



is_valid
действителен, когда был использован конструктор по-умолчанию и не было присвоено значение.

четверг, 17 апреля 2008 г.

Команды at() и [] для luabind::object

Как только lua тип назначен для luabind::object вы можете использовать оператор [] или методм at() для доступа к данным. at() обеспечивает read-only доступ, а [] - read-write доступ. Параметр, передаваемый в [] или at(), должен быть lua типом доступным в глобальном пространстве имен (помните, что все переменные lua объявлены в глобальной области видимости, если явно не указано ключевое слово local перед первым объявлением переменной в скрипте lua). Для преобразования типа luabind::object в C++ тип необходимо использовать luabind::object_cast.

Например давайте объявим такие переменные в lua скрипте:


Mat = 37
Sharon = 15
Scooter = 1.5


Теперь мы должны связать luabind::object с глобальной таблицей lua. Для этого необходимо использовать функцию get_globals:


luabind::object global_table = get_globals(pLua);


После этого можно получить доступ до объявленных переменных:


float scooter = luabind::object_cast<float>(global_table.at("Scooter"));


Или поменять значение переменных:


global_table["Mat"] = 10;


Одной из важных особенностей luabind::object является возможность вызывать функции, определенные в lua. Вы можете даже включать luabind::object в поля класса C++, позволяя расширить функциональные возможности класса. В следующих статьях я покажу, как это сделать.

luabind::object

Чтобы упростить привязку lua типов к вашим C++ функция и объектам, luabind содержит класс object. Этот класс может представлять любой тип lua. Интерфейс класса object скопирован с документации luabind:


class object
{
public:
class iterator;
class raw_iterator;
class array_iterator;

template<class T>
object(lua_State*, const T& value);
object(const object&);
object(lua_State*);
object();

-object();

iterator begin() const;
iterator end() const;
raw_iterator raw_begin() const;
raw_iterator raw_end() const;
array_iterator abegin() const;
array_iterator aend() const;

void set();
lua_State* lua_state() const;
void pushvalue() const;
bool is_valid() const;
operator bool() const;

template<class Key>
<implementation-defined> operator[](const Key&);

template<class Key>
object at(const Key&) const;

template<class Key>
object raw_at(const Key&) const;

template<class T>
object& operator=(const T&);
object& operator=(const object&);

template<class T>
bool operator==(const T&) const;
bool operator==(const object&) const;
bool operator<(const object&) const;
bool operator<=(const object&) const;
bool operator>(const object&) const;
bool operator>=(const object&) const;
bool operator!=(const object&) const;

void swap(object&);
int type() const;

<implementation-defined> operator()();

template<class A0>
<implementation-defined> operator()(const A0& a0);

template<class A0, class A1>
<implementation-defined> operator()(const A0& a0, const A1& a1);

/* ... */
};