[Следующая: Написание исходного кода для перевода] Интернационализация с Qt
|
QInputContext | Абстрактный метод ввода, зависящий от данных и состояния |
---|---|
QLocale | Конвертирует числа в их строковые представления на различных языках |
QSystemLocale | Может быть использовать в регулировании локализаций системных выражений |
QTextCodec | Преобразования текста в различные кодировки |
QTextDecoder | Декодер, поддерживающий различные состояния |
QTextEncoder | Кодировщик, поддерживающий различные состояния |
QTranslator | Поддержка интернационализации выводимого текста |
Правила перевода множественного числа | Сводка правил перевода множественного числа, производимого инструментами интернационализации Qt. |
Написание исходного кода для перевода | Как записать исходный код способом, который делает возможным перевод текста, видимого пользователем. |
В некоторых случаях интернационализация это просто, например, перевод приложения написанного в США для пользователей Англии или Австралии требует чуть больше чем несколько поправок орфографии. Но чтобы сделать приложение написанное в США полезным для пользователей в Японии или корейское приложение для немецких пользователей, потребуется не только чтобы приложение работало на другом языке, но и использовало другие техники ввода, кодирования символов и соглашения о представлении.
Qt пытается сделать интернационализацию на столько безболезненной, для разработчиков, насколько это возможно. Все виджеты ввода и методы отрисовки текста в Qt предлагают встроенную поддержку для всех поддерживаемых языков. Встроенный механизм шрифтов в состоянии корректно и привлекательно отрисовывать текст, который содержит символы из множества разнообразных систем письменности в одно и то же время.
Qt поддерживает большинство языков, используемых сегодня, в частности:
В Windows, Unix/X11 с FontConfig (поддержка шрифтов с клиентской стороны) и в Qt для встраиваемых Linux-систем также поддерживаются следующие языки:
Многие из этих систем письменности имеют особые свойства:
Qt пытается позаботится о всех специальных особенностях, перечисленных выше. Обычно не приходится беспокоиться об этих особенностях пока вы используете виджеты ввода Qt (например, QLineEdit, QTextEdit и наследуемые классы) и виджеты отображения Qt (например, QLabel).
Поддержка для этих систем письменности прозрачна для программиста и полностью инкапсулирована в текстовый механизм Qt. Это значит что вам не требуется иметь каких-либо знаний о системе письменности, используемой в конкретном языке, кроме следующих небольших замечаний:
Следующая секция дает некоторую информацию о статусе поддержки интернационализации (i18n) в Qt. Смотрите также: Руководство по Qt Linguist.
Написание кросс-платформенных интернациональных программ с Qt это мягкий, последовательный процесс. Ваше программное обеспечение может стать международным в следующих стадиях:
С тех пор как QString использует внутри кодирование в Unicode 5.1, любой язык в мире может быть обработан прозрачно используя общие операции обработки текста. Также, с тех пор как все функции Qt, которые представляют текст пользователю, принимают QString в качестве параметра, больше нет дополнительных преобразований char * в QString.
Строки, которые в "пространстве программиста" (такие как имена QObject и тексты форматов файлов), не требуют использования QString; традиционный char * или класс QByteArray будут достаточны.
Вы скорее всего не заметили что используете Unicode; QString, и QChar просто упрощенные версии необработанных const char * и char из традиционного C.
Где бы ваша программа не использовала "текст в кавычках" для текста, который будет отображен пользователю, убедитесь что он обрабатывается функцией QCoreApplication::translate(). Все что для этого необходимо - использовать QObject::tr(). Например, предположим что LoginWidget это подкласс QWidget:
LoginWidget::LoginWidget() { QLabel *label = new QLabel(tr("Password:")); ... }
Это справедливо для 99% строк видимых пользователю которые вы захотите написать.
Если текст в кавычках не находится в функции-члене подкласса QObject, используйте функцию tr() подходящего класса или функцию QCoreApplication::translate() напрямую:
void some_global_function(LoginWidget *logwid) { QLabel *label = new QLabel( LoginWidget::tr("Password:"), logwid); } void same_global_function(LoginWidget *logwid) { QLabel *label = new QLabel( qApp->translate("LoginWidget", "Password:"), logwid); }
Если вам потребуется перевести текст, который находится полностью вне функции, есть два макроса для помощи: QT_TR_NOOP() и QT_TRANSLATE_NOOP(). Они незаметно помечают текст для извлечения утилитой lupdate, описанной ниже. Макрос распространяется только на текст (без контекста).
Пример QT_TR_NOOP():
QString FriendlyConversation::greeting(int type) { static const char *greeting_strings[] = { QT_TR_NOOP("Hello"), QT_TR_NOOP("Goodbye") }; return tr(greeting_strings[type]); }
Пример QT_TRANSLATE_NOOP():
static const char *greeting_strings[] = { QT_TRANSLATE_NOOP("FriendlyConversation", "Hello"), QT_TRANSLATE_NOOP("FriendlyConversation", "Goodbye") }; QString FriendlyConversation::greeting(int type) { return tr(greeting_strings[type]); } QString global_greeting(int type) { return qApp->translate("FriendlyConversation", greeting_strings[type]); }
Если вы отключите автоматическое преобразование из const char * в QString путем компиляции вашей программы с определенным макросом QT_NO_CAST_FROM_ASCII, вы скорее всего найдете все строки, которые пропустили. Для получения более подробной информации смотрите QString::fromLatin1(). Отключение преобразования может сделать программирование слегка затруднительнее.
Если ваш исходный язык использует символы вне таблицы символов Latin1, вы можете найти QObject::trUtf8() более удобным чем QObject::tr(), так как tr() зависит от QTextCodec::codecForTr(), что делает его более "хрупким" чем QObject::trUtf8().
Горячие клавиши, такие как Ctrl+Q или Alt+F, должны быть также переведены. Если вы жестко зададите Qt::CTRL + Qt::Key_Q для "выхода" в кашей программе, переводчики не смогут переназначить его. Правильный подход это
exitAct = new QAction(tr("E&xit"), this); exitAct->setShortcuts(QKeySequence::Quit);
Функции QString::arg() предлагают простое толкование для подстановочных аргументов:
void FileCopier::showProgress(int done, int total, const QString ¤tFile) { label.setText(tr("%1 of %2 files copied.\nCopying: %3") .arg(done) .arg(total) .arg(currentFile)); }
В некоторых языках может потребоваться изменить порядок аргументов, и это может быть легко достигнуто изменением порядка переменных с %. Например:
QString s1 = "%1 of %2 files copied. Copying: %3"; QString s2 = "Kopierer nu %3. Av totalt %2 filer er %1 kopiert."; qDebug() << s1.arg(5).arg(10).arg("somefile.txt"); qDebug() << s2.arg(5).arg(10).arg("somefile.txt");
производит корректный вывод текста на английском и норвежском:
5 of 10 files copied. Copying: somefile.txt Kopierer nu somefile.txt. Av totalt 10 filer er 5 kopiert.
После того как вы использовали tr() по всему приложению, вы можете создавать перевод текста видимого пользователю вашей программы.
Справочное руководство Qt Linguist предоставляет дополнительную информацию об инструментах перевода Qt, Qt Linguist, lupdate и lrelease.
Перевод приложения Qt содержит 3 шага:
Обычно вы будете повторять эти шаги для каждого выпуска приложения. Утилита lupdate делает все возможное по повторному использованию переводов от предыдущих релизов.
Перед запуском lupdate, вам потребуется подготовить файл проектов. Вот небольшой пример файла проекта (файл .pro):
HEADERS = funnydialog.h \ wackywidget.h SOURCES = funnydialog.cpp \ main.cpp \ wackywidget.cpp FORMS = fancybox.ui TRANSLATIONS = superapp_dk.ts \ superapp_fi.ts \ superapp_no.ts \ superapp_se.ts
Когда вы запускаете lupdate или lrelease, вы должны предоставить имя файла проекта в качестве аргумента командной строки.
В данном примере поддерживаются четыре экзотических языка: датский, финский, норвежский и шведский. Если вы используете qmake, вам обычно не нужен дополнительный файл проекта для lupdate; ваш файл проекта qmake будет прекрасно работать после того как вы добавите запись TRANSLATIONS.
В вашем приложении вы должны загрузить QTranslator::load() файлы используя QCoreApplication::installTranslator().
linguist, lupdate и lrelease установлены в поддиректории bin базовой директории, в которой установлен Qt. Щелкните на Help|Manual в Qt Linguist для доступа к руководству пользователя; он содержит учебное пособие для начала работы.
Qt содержит внутри около 400 строк, которые так же должны быть переведены на языки которые вам необходимы. Вы найдете файлы переводов для французского, немецкого и упрощенного китайского в директории $QTDIR/translations, так же как и шаблоны для перевода на другие языки. (Эта директория так же содержит некоторые дополнительные неподдерживаемые переводы, которые могут быть полезны).
Обычно, функция main() вашего приложения будет выглядеть примерно так:
int main(int argc, char *argv[]) { QApplication app(argc, argv); QTranslator qtTranslator; qtTranslator.load("qt_" + QLocale::system().name(), QLibraryInfo::location(QLibraryInfo::TranslationsPath)); app.installTranslator(&qtTranslator); QTranslator myappTranslator; myappTranslator.load("myapp_" + QLocale::system().name()); app.installTranslator(&myappTranslator); ... return app.exec(); }
Обратите внимание на использование QLibraryInfo::location() для обнаружения переводов Qt. Разработчик должен запросить путь к переводам во время выполнения обрабатывая QLibraryInfo::TranslationsPath для этой функции вместо использования переменной среды QTDIR в своих приложениях.
Класс QTextCodec и его возможности в QTextStream делают поддержку множества входных и выходных кодировок пользовательских данных легкой. Когда приложение запущено, локаль машины определит 8-ми битную кодировку используемую для работы с 8-ми битными данными: например, для выбора шрифта, отображения текста, ввода-вывода 8-ми битного текста и ввода символов.
Приложению может внезапно потребоваться кодировка, отличная от 8-ми битной локальной кодировки по умолчанию. Например, приложение в кириллической локали KOI8-R (стандартная де-факто локаль в России) может потребовать вывод кириллицы в кодировке ISO 8859-5. Код может быть следующим:
QString string = ...; // некоторый текст в Unicode QTextCodec *codec = QTextCodec::codecForName("ISO 8859-5"); QByteArray encodedString = codec->fromUnicode(string);
Для преобразования из Unicode в локальную 8-ми битную кодировку, доступен короткий путь: функция QString::toLocal8Bit() возвращает такие 8-ми битные данные. Другой полезный короткий путь это QString::toUtf8(), который возвращает текст из 8-ми битной кодировки в UTF-8: она идеально сохраняет информацию в Unicode и в то же время выглядит как простой текст в ASCII если весь текст полностью в ASCII.
Для преобразования в другую сторону есть QString::fromUtf8() и QString::fromLocal8Bit() вспомогательные функции, или основной код, продемонстрированный конвертацией из ISO 8859-5 в Unicode:
QByteArray encodedString = ...; // некоторый текст в кодировке ISO 8859-5 QTextCodec *codec = QTextCodec::codecForName("ISO 8859-5"); QString string = codec->toUnicode(encodedString);
В идеале должен быть использован ввод-вывод Unicode, так как это увеличивает переносимость документов между пользователями по всему миру, но в реальности удобно поддерживать все подходящие кодировоки, которыми вашим пользователям может потребоваться обработать существующие документы. В общем, Unicode (UTF-16 или UTF-8) лучше для обменом информацией между различными людьми, в то время как внутри групп с одним языком или одной национальности локальный стандарт более подходящий. Наиболее важная кодировка для поддержки это та, которая возвращается функцией QTextCodec::codecForLocale(), так как это та кодировка, которая вероятнее всего необходима пользователю для общения с другими людьми и приложениями (этот кодек используется local8Bit()).
Qt наитивно поддерживает большинство из наиболее часто используемых кодировок. Для полного списка поддерживаемых кодировок смотрите документацию по QTextCodec.
В некоторых случаях и для менее часто используемых кодировок может потребоваться написать собственный дочерний класс от QTextCodec. В зависимости от срочности, может быть полезно связаться с командой технической поддержки Qt или спросить в списке рассылки qt-interest для поиска кого-нибудь еще, кто уже работает над поддержкой этой кодировки.
Локализация это процесс по адаптированию к местным соглашениям, например, представление дат и времен используя местные предпочитаемые форматы. Такая локализация может быть сделана использованием подходящих строк tr().
void Clock::setTime(const QTime &time) { if (tr("AMPM") == "AMPM") { // 12-часовые часы } else { // 24-часовые часы } }
В этом примере, для США можем оставить перевод "AMPM" как есть и использовать 12-часовую ветвь; Но в Европе мы переведем ее во что-нибудь еще и это заставит код использовать 24-часовую ветку.
Для локализации чисел используйте класс QLocale.
Локализация изображений не рекомендуется. Выберите ясные иконки, которые подходят для всех локализаций, вместо того чтобы полагаться на местные каламбуры или метафоры. Исключение только для изображений стрелок, указывающих налево и направо, которые может потребоваться перевернуть для арабской и ивритской локалей.
Некоторые приложения, такие как Qt Linguist, должны обеспечивать изменения настроек языка пользователя во время работы. Чтобы предупредить виджеты об изменениях установленного QTranslators, переопределите функцию виджета changeEvent() для проверки не является ли событие событием LanguageChange, и обновите текст, отображаемый виджетами, используя функцию tr() обычным способом. Например:
void MyWidget::changeEvent(QEvent *event) { if (e->type() == QEvent::LanguageChange) { titleLabel->setText(tr("Document Title")); ... okPushButton->setText(tr("&OK")); } else QWidget::changeEvent(event); }
Все остальные события изменения должны быть обработаны вызовом реализации по умолчанию данной функции.
Список установленных переводов может быть изменен в реакции на событие LocaleChange, или приложение может предоставлять интерфейс пользователю, который позволит ему изменить текущий язык приложения.
Обработчик событий по умолчанию для подклассов QWidget отвечает на событие QEvent::LanguageChange и вызовет эту функцию при необходимости.
События LanguageChange отправляются когда новый перевод установлен используя функцию QCoreApplication::installTranslator(). Кроме того, в других компонентах приложения можно так же заставить виджеты обновить себя отправив им событие LanguageChange.
Иногда необходимо обеспечить поддержку интернационализации для строк, используемых в классах, которые не наследуют QObject или не используют макрос Q_OBJECT для включения функций перевода. Так как Qt переводит строки во время выполнения основываясь на классах, с которыми они связаны, и lupdate ищет переводимые строки в исходном коде, классы, не входящие в Qt, должны использовать механизм, который так же обеспечивает данную информацию.
Один способ сделать это - добавить поддержку перевода для класса, не входящего в Qt, используя макрос Q_DECLARE_TR_FUNCTIONS(); например:
class MyClass { Q_DECLARE_TR_FUNCTIONS(MyClass) public: MyClass(); ... };
Это обеспечивает класс функцией tr(), которая может быть использована для перевода строк, связанных с классом, и делает возможным для lupdate найти переводимые строки в исходном коде.
Также, может быть вызвана с особым контекстом функция QCoreApplication::translate() и это будет распознано lupdate и Qt Linguist.
Некоторые операционные и оконные системы, на которых работает Qt, имеют ограниченную поддержку Unicode. Уровень поддержки, доступный в нижестоящей системе, влияет на поддержку, которую Qt может обеспечить на этих платформах, хотя в обычных программах на Qt не надо слишком беспокоиться о платформо-зависимых ограничениях.
За подробностями перевода, специфичными для Mac, обратитесь к документу "Проблемы, специфичные для Qt/Mac" здесь.
[Следующая: Написание исходного кода для перевода]
Авторские права © 2010 Nokia Corporation и/или её дочерние компании | Торговые марки | Qt 4.6.4 |
Попытка перевода Qt документации. Если есть желание присоединиться, или если есть замечания или пожелания, то заходите на форум: Перевод Qt документации на русский язык... Люди внесшие вклад в перевод: Команда переводчиков |