How to create a multi language application/ru

From Qt Wiki
Jump to: navigation, search

En Ar Bg De El Es Fa Fi Fr Hi Hu It Ja Kn Ko Ms Nl Pl Pt Ru Sq Th Tr Uk Zh

Создайте простое приложение, например с основным окном (QMainWindow)

LanguageApp.png

В этом примере мы создадим основное окно с языковым меню и несколькими виджетами. Если пользователь открыл языковое меню, там предусмотрен выбор языка, созданный на этапе старта приложения, зависимый от имеющихся языковых файлов.

LanguageAppMenu.png

Структура файловой системы приложения:

  • Каталог приложения
    • двоичные файлы
  • Каталог приложения/languages
    • Для каждого установленного языка имеется опциональная картинка размером 16x16 пикселей с флагом (например de.png)
    • Переведённые текстовые файлы приложения (TranslationExample_*.qm, где * может принимать значения de, en, и т.д.)
    • Файлы перевода Qt (qt_*.qm)

Определение класса

В классе MainWindow, виртуальный метод changeEvent(QEvent*) переписан. Для каждого необходимого файда пеоевода создаётся эезнипляр QTranslator .(в нашем примере 2, один для текстов приложения и один для Qt). Текущий язык сохраняется чтобы подавлять события на случай того, что пользователь попытается загрузить один и тот же язык дважды.

class MainWindow : public QMainWindow {

protected:
 // Это событие вызывается когда новый переводчик загружен или был изменён язык системы
 void changeEvent(QEvent*);
protected slots:
 // Этот слот вызывается действиями (QAction) меню
 void slotLanguageChanged(QAction* action);
private:
 // загружает язык по данному префиксу (например: de, en)
 void loadLanguage(const QString& rLanguage);
 // Создаёт меню языка динамически из содержимого m_langPath
 void createLanguageMenu(void);
 Ui::MainWindow ui; // ui определение из дизайнера
 QTranslator m_translator; // содержит переводчик этого приложения
 QTranslator m_translatorQt; // содержит переводчик qt
 QString m_currLang; // содержит текущий загруженный язык
 QString m_langPath; // Путь к языковым файлам. зафиксирован как /languages.

};

Создание языковых меню

Языковое меню создаётся динамически на старте приложения, в зависимости от наличия файлов перевода. Преимущество такого решения в том, что вы можете добавить позднее любой перевод, и он будет работоспособен после перезагрузки приложения. В этом примере все текстовые файлы расположены в подкаталоге "languages". Там возможно также разместить несколько иконок (language.png) которые будут применяться как иконки в меню (флаг, например).

Каждый язык представлен QAction объектом, который добавлен в QActionGroup. Это сделано чтобы был необходин только один слот для всех языков:

connect(langGroup, SIGNAL (triggered(QAction *)), this, SLOT (slotLanguageChanged(QAction *)));

Языковое меню создаётся так:

// создаём пункты динамически, в зависимости от существующих переводов. void MainWindow::createLanguageMenu(void) {

QActionGroup* langGroup = new QActionGroup(ui.menuLanguage);
langGroup->setExclusive(true);
connect(langGroup, SIGNAL (triggered(QAction *)), this, SLOT (slotLanguageChanged(QAction *)));
// формат языка системы
QString defaultLocale = QLocale::system().name(); // e.g. "de_DE"
defaultLocale.truncate(defaultLocale.lastIndexOf('_')); // e.g. "de"
m_langPath = QApplication::applicationDirPath();
m_langPath.append("/languages");
QDir dir(m_langPath);
QStringList fileNames = dir.entryList(QStringList("TranslationExample_*.qm"));
for (int i = 0; i < fileNames.size(); ++i) {
 // получение локали из имени файлаget locale extracted by filename
 QString locale;
 locale = fileNames[i]; // "TranslationExample_de.qm"
 locale.truncate(locale.lastIndexOf('.')); // "TranslationExample_de"
 locale.remove(0, locale.lastIndexOf('_') + 1); // "de"
QString lang = QLocale::languageToString(QLocale(locale).language());
QIcon ico(QString("%1/%2.png").arg(m_langPath).arg(locale));
QAction *action = new QAction(ico, lang, this);
action->setCheckable(true);
action->setData(locale);
ui.menuLanguage->addAction(action);
langGroup->addAction(action);
// Установить переводчики и язык по умолчанию в состояние помеченых галочкой.
if (defaultLocale == locale)
{
action->setChecked(true);
}
}

}

Переключение языка

Если язык должен быть переключен, необходимый целевой язык получаем из объекта QAction и существующие переводчики удаляются. QApplication::removeTranslator(). Затем, загружаются новые языковые файлы, и в случае успеха, переводчик устанавливается снова QApplication::installTranslator(). Делается это для того чтобы гарантировать факт того что сигнал QEvent::LanguageChange будет выпущен объектом приложения. Если у приложения есть только одно окно верхнего уровня, созданное полностью в дизайнере, то также возможно просто прочитать новые файлы переводов и вызвать ui.retranslateUi(this) напрямую.

// Вызывается каждый раз, когда вызывается пункт языкового меню void MainWindow::slotLanguageChanged(QAction* action) {

if(0 != action) {
 // load the language dependant on the action content
 loadLanguage(action->data().toString());
 setWindowIcon(action->icon());
}

}

void switchTranslator(QTranslator& translator, const QString& filename) {

// убрать старый переводчик
qApp->removeTranslator(&translator);
// загрузить новый переводчик

QString path = QApplication::applicationDirPath(); path.append("/languages/");

if(translator.load(path + filename)) // Здесь необходимо указывать путь и имя файла, потому что система иначе не найдёт файлы QM Files else
 qApp->installTranslator(&translator);

}

void MainWindow::loadLanguage(const QString& rLanguage) {

if(m_currLang != rLanguage) {
 m_currLang = rLanguage;
 QLocale locale = QLocale(m_currLang);
 QLocale::setDefault(locale);
 QString languageName = QLocale::languageToString(locale.language());
 switchTranslator(m_translator, QString("TranslationExample_%1.qm").arg(rLanguage));
 switchTranslator(m_translatorQt, QString("qt_%1.qm").arg(rLanguage));
 ui.statusBar->showMessage(tr("Current Language changed to %1").arg(languageName));
}

}

  • QEvent::LanguageChange всегда будет вызываться, если объект переводчика устанавливается в объект приложенияif a translator object is installed in the application object
  • QEvent::LocaleChange вызывается когда изменяется системный язык

void MainWindow::changeEvent(QEvent* event) {

if(0 != event) {
 switch(event->type()) {
  // это событие посылается если переводчик загружен
  case QEvent::LanguageChange:
   ui.retranslateUi(this);
   break;
  // это событие вызывается если системный язык меняется
  case QEvent::LocaleChange:
  {
   QString locale = QLocale::system().name();
   locale.truncate(locale.lastIndexOf('_')); 
   loadLanguage(locale);
  }
  break;
 }
}
QMainWindow::changeEvent(event);

}

Добавление переводов в проект

В вашем проектном файле qmake такая переменная TRANSLATIONS должна была быть добавлена и содержать все языковые файлы, которые Вы изначаально были намерены создавать.

TRANSLATIONS = languages/TranslationExample_en.ts  languages/TranslationExample_de.ts


Запуская lupdate

lupdate -verbose TranslationExample.pro

Вы тем самым создаёте языковой файл (.ts), который вы переводите инструментом Qt Linguist.

linguist languages/TranslationExample_en.ts languages/TranslationExample_de.ts

После того как Вы это сделали, вы запустите lrelease для создания двоичных файлов перевода (.qm):

lrelease TranslationExample.pro