Данная статья не претендует на уникальность, но простым языком объясняет как начать использовать возможности встроенной интернационализации в Qt приложениях.
Как сделать текстовую константу переводимой?
Текстовые константы у нас могут быть использованы в C++ коде, в QtScript - скриптах (и их расширениях), в QML и в UI файлах. Для UI делать ничего не нужно, только не забываем, что поумолчанию мы все тексты пишем на английском.
Для C++ кода, чтобы сделать текстовую константу переводимой достаточно обернуть ее в вызов статического метода QObject::tr(const *char text). Если вы и так имеете текстовую константу внутри класса-наследника QObject, то, естественно указывать им класса перед методом нет необходиомости.
Для скриптов и QML существуют две функции qsTr(string) и qsTranslate(string, string)
Первая может применятся в файлах со скриптами, для экстеншенов надо применять вторую функцию, это связано с тем, что все файлы экстеншенов называются одинаково (__init__.js). Первый параметр функции qsTranslate принимает текстовый идентификатор уникальный для каждого файла (за этим надо следить самому, иначе некорректно создасться перевод), я использую и предлагаю всем последовать моему примеруу следующий способ формирования идентификатора, из названия модуля, т.е. например если мы имеем модуль views.somemodel.modelclass, то идетификатор будет views_somemodel_modelclass.
Для скриптов и QML существуют две функции qsTr(string) и qsTranslate(string, string)
Первая может применятся в файлах со скриптами, для экстеншенов надо применять вторую функцию, это связано с тем, что все файлы экстеншенов называются одинаково (__init__.js). Первый параметр функции qsTranslate принимает текстовый идентификатор уникальный для каждого файла (за этим надо следить самому, иначе некорректно создасться перевод), я использую и предлагаю всем последовать моему примеруу следующий способ формирования идентификатора, из названия модуля, т.е. например если мы имеем модуль views.somemodel.modelclass, то идетификатор будет views_somemodel_modelclass.
Важно отметить, что оборачивать в данные функции можно только константный текст, т. е. если используется конкатенация, то оборачивать необходимо каждый кусок отдельно, пример:
error = qsTr("File ") + filename + qsTr (" not found!") // Правильно
error = qsTr("File " + filename + " not found!") // Неправильно!
Пример для QML:Text { text: qsTr("Pictures") }
Как обновить файл перевода
Если вы хотите создать новый перевод или обновить старый вам необходимо в консоли перейти в конфигурации в директорию в которой вы хотите сохранять переводы и там запустить следующую команду для каждого языка:
lupdate -recursive -extensions qs,js,ui,cpp,h,qml <path to app> -ts translation.ru_RU.ts
вместо ru_RU подставляя необходимый код языка.
Как перевести
После того как ts файл создан, можно занятся переводом, для этого нужно открыть приложение QtLinguist, оно есть в стандартной поставке Qt SDK, если вы затрудняетесь его найти проверьте путь /bin, если вы собирали qt из исходников и в этой папке нет файла linguist(.exe), то это значит что при сборке вы выключили сборку утилит, ключ “-nomake tools” и вам придется пересобрать Qt без этого ключа, либо найти это приложение где-нибудь еще.
Само приложение очень просто, достаточно открыть в нем файл и сразу становиться понятно, где и что переводить.
Не забудьте сохранить файл после того как вы его перевели.
Не забудьте сохранить файл после того как вы его перевели.
Как добавить новый перевод в приложение
Для добавления перевода его сначала необходимо скомпилировать, это делается с помощью выполнения команды:
lrelease -compress translation.ru_RU.ts -qm translation.ru_RU.qm
для каждого языка, заменяя ru_RU на необходимую локаль.
В дальнейшем я планирую автоматизировать этот процесс, с помощью .pro-файла, но пока в этом нет необходимость, а процесс этот мне кажется достатчно трудоемким.
После как .qm созданы/обновлены, я добавляю их в специально для этого заведенный файл ресурсов translations.qrc, который потом подгружаю в приложение.
Это завершающий этап, теперь новая локаль будет доступна для выбора
P.S. Как использовать переводы в приложении.
Для того чтобы использовать файлы интернационализации в вашем приложении, вам необходимо добавить следующую конструкцию (например в main.cpp):
Естественно, если вы озаботитесь сохранением доступа к вашему экземпляру транслятора, с помощью метода load() вы сможете менять локаль на лету.
Мне бы эту статью года 3 назад : )
ReplyDeleteОт меня несколько минорных замечаний/предложений:
> error = qsTr("File ") + filename + qsTr (" not found!") // Правильно
Думаю, правильнее было бы
> error = sprintf(qsTr("File %s found!"), filename);
иначе переводчику будет сложнее уловить контекст
Как альтернативу QtLinguist могу предложить неплохой ресурс http://crowdin.net
Согласен, правда Qt Linguist неплохо подсвечивает в исходниках строчку перевода, так что контекст улавливается вполне.
ReplyDeleteтеоретически, у переводчиков нет исходников (разве что при опенсорс).
ReplyDeleteКстати, в Qt есть возможность задавать контекст перевода в исходниках ? (такая возможность есть в GetText, коментариями)
Да есть, qsTranslate например, то что я для простоты назвал идентификатором, первым параметром как раз принимает контекст, нсколько помню, он также может принимать третьим параметром комментарий.
ReplyDeleteQt Linguist очень вредная разработка - создает иллюзию дружелюбности для переводчика, но препядствует формированию удобной централизованной базы переводов, вводя еще в добавок понятия 'контекст', не имеющее ничего общего со смыслом различия тех или иных фраз. Лучше видеть два разных ключа для перевода, чем Form1::tag и Form2::tag.
ReplyDeleteФайл с двумя колонками 'ключ' и 'перевод' + online ресурс для его просмотра + сценарий сборки, генерирующий .ts как промежуточный артефакт и вставляющий туда переводы.
ReplyDeleteСхема работы: перевода нет -> разработчик создает тег и забывает -> увидев отсутствие перевода на прототипе, ответственные выполняют добавление перевода + find/replace тега по базе кода, если его необходимо заменить.
Также так гораздо проще искать разные ключи для одного перевода, имея перед глазами отсортированный по алфавиту целевого языка файл.
Назвали это в шутку Agile Translation:
ReplyDelete- разработчики и переводчики полностью изолированы друг от друга;
- разработчик пишет тег для перевода однажды и забывает о нем;
- переводчикам не нужно видеть приложение, чтобы писать перевод, так как есть удобочитаемый ключ;
- синхронизацией тегов и нормализацией файлов переводов могут заниматься специально обученные люди, имеющие доступ к файлам и базе кода;
- так, наработанные переводы удобно каталогизировать и использовать в других проектах (не обязательно иметь один файл перевода на русский - можно составлять сколько угодно и разбивать по темам и областям);
- прочие выгоды от централизации и управления переводами..
А как в самой программе Qt Linguist включить русский язык? ведь, в SDK Qt есть папка с пакетами переводов к Linguist... - вот как их связать?
ReplyDelete@Alexey Khudyakov AFAIK Qt Linguist будет запускаться с переводом под дефолтную системную локаль.
ReplyDelete