c++ - Translation of "dynamic" content if using Internationalization with Qt -


i evaluating c++ framework qt v5.4.1. trying understand , apply internationalization qt.

i implemented switching of human language @ runtime via of article how create multi lingual application can switch language @ runtime? , know how-to work qt linguist translation source (.ts) files , how generate qt linguist message (.qm) files. use build system cmake automate generation , works nice.

in project translations loaded qt resource collection (.qrc) file compiled application. know how-to translate "static" strings via member functions qobject::tr() , qobject::translate().

now comes tricky part: want add languages while application evolves. have following 2 .ts files:

  • foo_ui_de_de.ts
  • foo_ui_en_us.ts

these compiled via lrelease following 2 .qm files build process:

  • foo_ui_de_de.qm
  • foo_ui_en_us.qm

the build process automatically generates .qrc file translations.qrc , compiles file executable via rcc.

relevant source code declaration file (.h):

#include <qmainwindow> #include <qlocale> #include <qstring> #include <qtranslator>  class mainwindow : public qmainwindow {   q_object   public:   /**    * initializes new instance of mainwindow class given parent.    *    * @param parent parent.    */   explicit mainwindow(qwidget* parent = 0);   private slots:   /**    * loads language given language shortcut (e.g. `de_de`, `en_us`).    */   void loadlanguage(qlocale const& klocale);    void switchtranslator(qtranslator& translator,                         qstring const& klocale,                         qstring const& kfilename);    /**    * creates language menu dynamically.    */   void createlanguagemenu();   protected:   /**    * handler activated when new translator loaded or system    * language changed.    */   void changeevent(qevent* event);   protected slots:   /**    * slot called language menu actions.    */   void slotlanguagechanged(qaction* action);   private:   /**    * translations application.    */   qtranslator translator_;    /**    * translations qt widgets used in application.    */   qtranslator qt_translator_;    /**    * contains loaded locale.    */   qlocale locale_;    /**    * main window of application.    */   ui::mainwindow* ui_; }; 

relevant source code definition file (.cc):

#include <qlibraryinfo>  #include "main_window.h"  #include "ui_main_window.h"  mainwindow::mainwindow(qwidget* the_parent)     : qmainwindow{the_parent},       ui_{new ui::mainwindow} {   ui_->setupui(this);   createlanguagemenu(); }  mainwindow::~mainwindow() {   delete ui_; }  void mainwindow::loadlanguage(qlocale const& knewlocale) {   qlocale::setdefault(knewlocale);   qstring const klanguagename{qlocale::languagetostring(knewlocale.language())};    switchtranslator(translator_, "qt_" + knewlocale.bcp47name(),                    qlibraryinfo::location(qlibraryinfo::translationspath));   switchtranslator(qt_translator_,                    qapp->applicationname() + '_' + knewlocale.name(),                    ":/translations");   statusbar()->showmessage(       tr("language changed %1").arg(klanguagename));   locale_ = knewlocale; }  void mainwindow::switchtranslator(qtranslator& translator,                                   qstring const& klocale,                                   qstring const& kfilename) {   qapp->removetranslator(&translator);    if (translator.load(klocale, kfilename)) {     qapp->installtranslator(&translator);   } }  void mainwindow::createlanguagemenu() {   // todo(wolters): not optimal, since not work automatically   // .qm files added resource application.   //: translation human language german.   qt_tr_noop("german");   //: translation human language english.   qt_tr_noop("english");    qactiongroup* language_group{new qactiongroup(ui_->menulanguage)};   language_group->setexclusive(true);    connect(language_group, signal(triggered(qaction*)), this,           slot(slotlanguagechanged(qaction*)));    qlocale const kdefaultlocale{qlocale::system()};   qdir const kdirectory{qapplication::applicationdirpath() + "/.."};   qstringlist const kfilenames{kdirectory.entrylist(qstringlist("*.qm"))};    (qstring const& kfilename : kfilenames) {     qlocale const klocale{qfileinfo{kfilename}.completebasename().replace(         qapp->applicationname() + "_", "")};     qstring const kcountrycode{         klocale.name().tolower().mid(klocale.name().lastindexof('_') + 1)};     qicon const kicon{":/icons/flags/" + kcountrycode + ".png"};     qaction* action{new qaction{         kicon,         // todo(wolters): not work.         tr(qlocale::languagetostring(klocale.language()).tostdstring().c_str()),         this}};     action->setcheckable(true);     action->setdata(klocale);      ui_->menulanguage->addaction(action);     language_group->addaction(action);      if (kdefaultlocale == klocale) {       action->setchecked(true);     }   } }  void mainwindow::changeevent(qevent* the_event) {   if (nullptr != the_event) {     switch (the_event->type()) {       // qevent::languagechange send if translator loaded.       case qevent::languagechange:         ui_->retranslateui(this);         break;       // qevent::localechange send, if system language changes.       case qevent::localechange:         loadlanguage(qlocale::system());         break;       default:         break;     }   }    qmainwindow::changeevent(the_event); }  void mainwindow::slotlanguagechanged(qaction* action) {   if (nullptr != action) {     loadlanguage(qvariant_cast<qlocale>(action->data()));   } } 

the source code describes problem have in comments.

  1. if application started, current system locale used re-translate ui. works , can see items in menu languages appear in german human language (i've translated both items in .ts files). when switch language via menu german english, both item labels do not translated.
  2. the approach in general not optimal, since not want modify source code (qt_tr_noop above), if new human language added application. optimal work flow be:
    1. add supported languages .ts files in proper language.
    2. dynamically translate menu items.

i think misunderstanding something, couldn't found solution while searching www while.

update 2015-04-01: think use wrong approach. important part languages menu created dynamically in member function createlanguagemenu(). need answer question how-to translate dynamically created menu items. it's line qaction* action{new qaction{kicon, tr(qlocale::languagetostring(klocale.language()).tostdstring().c_str()), this}}; in function. need kind of lookup-functionality available @ compile time think...

as mentioned need lookup-functionality in real time. suggest such hack: when creating qaction objects use object name language identifer

qt_tr_noop("lang_eng") qaction* langaction = ...; langaction->setobjectname("lang_eng"); 

on language change event call method retreanslate actions

void retranslatelangactions() {     qlist<qaction*> widgetactions = this->findchildren<qaction*>();     foreach(qaction* act, widgetactions) // qt foreach macro     {         qstring objname = act->objectname();         if (objname.startswith("lang_"))         {             act->settext(tr(objname.tostdstring().c_str()));         }     } } 

Comments

Popular posts from this blog

cakephp - simple blog with croogo -

How to group boxplot outliers in gnuplot -

bash - Performing variable substitution in a string -