0
};
int i = 0;
while (flowers[i]) {
comboBox->insertItem(tr(flowers[i]));
++i;
}
}
Макрос QT_TR_NOOP() фактически ничего не делает, но он служит маркером дляlupdate. Строки, передаваемые этому макросу попадут в файл перевода и затем tr()переведет содержимое переменной обычным образом. Как видите, даже не смотря на то, что функции tr() передается не текст, а переменная, перевод будет выполнен корректно.
Есть еще один макрос -- QT_TRANSLATE_NOOP(), который похож на QT_TR_NOOP(), только в отличие от последнего, ему можно задать контекст перевода. Этот макрос найдет применение, когда необходимо инициализировать переменные за пределами класса:
static const char * const flowers[] = {
QT_TRANSLATE_NOOP("OrderForm", "Medium Stem Pink Roses"),
QT_TRANSLATE_NOOP("OrderForm", "One Dozen Boxed Roses"),
QT_TRANSLATE_NOOP("OrderForm", "Calypso Orchid"),
QT_TRANSLATE_NOOP("OrderForm", "Dried Red Rose Bouquet"),
QT_TRANSLATE_NOOP("OrderForm", "Mixed Peonies Bouquet"),
0
};
причем контекст должен совпадать с контекстом вызова функции tr(), которая будет выполнять перевод этих строк.
При использовании tr() в приложении не так уж и сложно забыть заключить какие нибудь строки в вызов этой функции, особенно если вы еще новичок. Эти досадные промахи будут проявляться в локализованных приложениях в виде непереведенных сообщений или надписей, вызывая чувство недовольства у пользователя. Чтобы избежать этой проблемы, мы можем запретить неявное преобразование из const char * в QString, определив символ препроцессора QT_NO_CAST_ASCII, перед директивой подключения заголовочного файла <qstring. h>. Самый простой способ определить этот символ -- поместить в файл .pro следующую строку:
DEFINES += QT_NO_CAST_ASCII
В результате, каждая строка, которая не пропускается через вызов tr() или QString:: fromAscii() (в зависимости от того, должна строка подвергаться переводу или нет), будет вызывать ошибку времени компиляции.
После того, как все строки будут "завернуты" в вызовы tr(), остается соблюсти еще одно важное условие -- загрузить на запуске файл с переводом. Обычно это делается в функции main(). Например, следующий код загрузит файл с переводом, с учетом региональных настроек пользователя:
int main(int argc, char *argv[])
{
QApplication app(argc, argv);
QTranslator appTranslator;
appTranslator. load(QString("app_") + QTextCodec::locale(),
qApp->applicationDirPath());
app. installTranslator(&appTranslator);
...
return app. exec();
}
Функция QTextCodec::locale() возвращает строку -- имя локали пользователя, запустившего приложение. Локаль может быть определена более или менее точно, например, ru определяет русскую локаль, ru_RU -- русскую локаль для России, ru_RU. KOI8-R -- русскую локаль для России, с кодировкой символов KOI8-R.
Предположим, что приложение получило строку с именем локали -- ru_RU. KOI8-R, тогда load() попытается сначала загрузить файл app_ru_RU. KOI8-R. qm. Если этот файл отсутствует, то load() попытается загрузить файл app_ru_RU. qm, затемapp_ru. qm и наконец app. qm. Обычно, в таких случаях достаточно создать один файл, с именем app_ru. qm. Однако, если перевод предполагает более точный учет региональных настроек, как например в случае fr_FR (французский язык для Франции) и fr_CA (французский язык для Канады), то может потребоваться создать отдельные файлы с переводом для каждого из регионов.
Второй аргумент функции load() -- это каталог, где находится файл с переводом. Компания Trolltech предоставляет файлы с французским и немецким переводами Qt в каталоге translations. (Переводы на некоторые другие языки так же могут поставляться вместе с библиотекой, но все они выполняются командами добровольцев и официально не поддерживаются.) Так же должен подгружаться библиотечный файл с переводом:
QTranslator qtTranslator;
qtTranslator. load(QString("qt_") + QTextCodec::locale(),
qApp->applicationDirPath());
app. installTranslator(&qtTranslator);
Экземпляр класса QTranslator может хранить только один файл с переводом, поэтому следует использовать различные QTranslator. Но это не является большой проблемой, так как мы можем создать столько экземпляров класса QTranslator, сколько потребуется. Все они будут использоваться приложением при поиске перевода.
В некоторых языках, таких как арабский и иврит, строки пишутся справа-налево. В этих случаях приложению необходимо сообщить о порядке вывода строк вызовомQApplication::setReverseLayout(true). Для таких языков, файл перевода должен содержать специальный маркер -- "LTR", который обеспечивает корректный вывод переведенных строк.
Для пользователей программы может оказаться более удобным вариант, когда файлы перевода внедряются в тело исполняемого файла программы. Мало того, что этот прием уменьшает количество файлов, которые придется распространять вместе сприложением, но это так же сведет к минимуму риск случайной потери файлов с переводами. Для реализации этой возможности, в составе Qt распространяется утилита qembed, которая преобразует файлы с переводами в массивы C++, которые могут передаваться функции QTranslator::load().
Мы описали все, что необходимо сделать, чтобы подготовить приложение к интернационализации. Но язык и направление письма это еще не все, что отличает страны и культуры. Интернационализированная программа должна принимать во внимание формат представления даты, времени, национальной валюты, чисел и порядок сортировки строк. Для этого в Qt 3.2 не существует никаких специальных функций, но мы можем использовать стандартные функции setlocale() иlocaleconv(). [8]
Некоторые функции и классы Qt адаптируют свое поведение под настройки локали:
· Функция QString::localeAwareCompare() выполняет сравнение строк в зависимости от настроек локали. Она используется классами QIconView иQListView для выполнения сортировки своих элементов.
· Функция toString() используется классами QDate, QTime и QDateTime, возвращающими локализованное представление даты и времени, когда вызываются с аргументом Qt::LocalDate.
· По-умолчанию QDateEdit, QTimeEdit и QDateTimeEdit представляют дату и время в локализованном виде.
Наконец, вместе с переводом, приложение может использовать разные наборы иконок для разных языков. Например, для языков, в которых письмо осуществляется справа-налево, в web-браузере логичнее было бы поменять местами кнопки "Назад" и "Вперед". Сделать это можно следующим образом:
if (QApplication::reverseLayout()) {
backAct->setIconSet(forwardIcon);
forwardAct->setIconSet(backIcon);
} else {
backAct->setIconSet(backIcon);
forwardAct->setIconSet(forwardIcon);
}
Иконки, изображение на которых соответствует алфавитным символам, очень часто должны быть адаптированы, в соответствии с конкретными языковыми настройками. Например, в текстовых процессорах, иконка с изображением символа "I" (что означает "Italic" -- Курсив) должна быть заменена на "C" для Испании (Cursivo) или на "K" -- для России (Курсив). Самый простой способ:
if (tr("Italic")[0] == 'C') {
italicAct->setIconSet(iconC);
} else if (tr("Italic")[0] == 'K') {
italicAct->setIconSet(iconK);
} else {
italicAct->setIconSet(iconI);
}
15.3. Динамическое переключение языков.
В большинстве приложений, определение предпочитаемого пользователем языка производится в функции main() и затем выполняется загрузка соответствующего файла с переводом. Чаще всего этого бывает достаточно, но иногда возникают ситуации, когда нужно быстро переключить интерфейс приложения на другой язык, без перезапуска приложения. В качестве примера можно привести приложения для операторов международных телефонных центров, для переводчиков, выполняющих синхронный перевод или для операторов отделений банков, когда становится насущной необходимость в быстром переключении между языками.
Чтобы приложение позволяло выполнять быстрый переход от языка к языку, нужно сделать немного больше, чем просто загрузить единственный файл с переводом, но это не так сложно, как может показаться на первый взгляд. Чтобы реализовать возможность выбора языка во время исполнения приложения, нужно:
· Обеспечить пользователя средствами выбора языка.
· Для каждого виджета или диалога, все строки, подвергающиеся переводу, необходимо разместить в отдельной функции (которую часто называют какretranslateStrings()) и вызывать ее при смене языка.
Рассмотрим отдельные части исходного кода приложения, которое поддерживает возможность быстрой смены языка интерфейса. Язык по-умолчанию -- Английский.
|
Из за большого объема этот материал размещен на нескольких страницах:
1 2 3 4 5 |


