Qt wiki will be updated on October 12th 2023 starting at 11:30 AM (EEST) and the maintenance will last around 2-3 hours. During the maintenance the site will be unavailable.

How to create a multi language application/el: Difference between revisions

From Qt Wiki
Jump to navigation Jump to search
No edit summary
No edit summary
Line 1: Line 1:
[[Category:HowTo]]<br />'''Ελληνικά''' [[How_to_create_a_multi_language_application_German|German]] [[How_to_create_a_multi_language_application|English]]
[[Category:HowTo]]<br />'''Ελληνικά''' [[How_to_create_a_multi_language_application_German|German]] [[How_to_create_a_multi_language_application|English]]


[toc align_right=&quot;yes&amp;quot; depth=&quot;2&amp;quot;]
[toc align_right="yes" depth="2"]


= Πώς να δημιουργήσετε μια πολυγλωσσική εφαρμογή με δυνατότητα εναλλαγής γλώσσας κατά το χρόνο εκτέλεσης; =
= Πώς να δημιουργήσετε μια πολυγλωσσική εφαρμογή με δυνατότητα εναλλαγής γλώσσας κατά το χρόνο εκτέλεσης; =
Line 11: Line 11:
== Η δομή αρχείων της εφαρμογής: ==
== Η δομή αρχείων της εφαρμογής: ==


* &amp;lt;Κατάλογος εφαρμογής&amp;amp;gt;
* <Κατάλογος εφαρμογής&amp;amp;gt;
** binaries
** binaries
* &amp;lt;Κατάλογος εφαρμογής&amp;amp;gt;/languages
* <Κατάλογος εφαρμογής&amp;amp;gt;/languages
** Για κάθε εγκατεστημένη γλώσσα, υπάρχει ένα (προαιρετικό) αρχείο εικόνας μεγέθους 16x16 pixel με μία σημαία (π.χ. de.png)
** Για κάθε εγκατεστημένη γλώσσα, υπάρχει ένα (προαιρετικό) αρχείο εικόνας μεγέθους 16x16 pixel με μία σημαία (π.χ. de.png)
** Τα μεταφρασμένα αρχεία κειμένου της εφαρμογής (TranslationExample_'''.qm, όπου''' μπορεί να είναι be de, en, …)
** Τα μεταφρασμένα αρχεία κειμένου της εφαρμογής (TranslationExample_'''.qm, όπου''' μπορεί να είναι be de, en, …)
** τα αρχεία μετάφρασης του Qt (qt_'''.qm)
** τα αρχεία μετάφρασης του Qt (qt_'''.qm)
<br />h2. Ορισμός κλάσης
<br />h2. Ορισμός κλάσης
<br />Στην κλάση MainWindow, η virtual method &quot;changeEvent(QEvent''')&quot;:http://doc.qt.nokia.com/latest/qwidget.html#changeEvent γίνεται overwritten. Για κάθε αρχείο μετάφρασης που απαιτείται, ένα &quot;QTranslator&amp;quot;:http://doc.qt.nokia.com/latest/qtranslator.html στιγμιότυπο δημιουργείται (στο συγκεκριμένο παράδειγμα 2, ένα για τα application texts, ένα για το qt). Η τρέχουσα γλώσσα αποθηκεύεται για να suppress events, εάν ο χρήστης προσπαθήσει να φορτώσει την ίδια γλώσσα δύο φορές.
<br />Στην κλάση MainWindow, η virtual method "changeEvent(QEvent''')":http://doc.qt.nokia.com/latest/qwidget.html#changeEvent γίνεται overwritten. Για κάθε αρχείο μετάφρασης που απαιτείται, ένα "QTranslator":http://doc.qt.nokia.com/latest/qtranslator.html στιγμιότυπο δημιουργείται (στο συγκεκριμένο παράδειγμα 2, ένα για τα application texts, ένα για το qt). Η τρέχουσα γλώσσα αποθηκεύεται για να suppress events, εάν ο χρήστης προσπαθήσει να φορτώσει την ίδια γλώσσα δύο φορές.


<code><br />class MainWindow : public QMainWindow<br />{<br /> …
<code><br />class MainWindow : public QMainWindow<br />{<br /> …


protected:<br /> /** this event is called, when a new translator is loaded or the system language is changed<br /> '''/<br /> void changeEvent(QEvent''');
protected:<br /> /** this event is called, when a new translator is loaded or the system language is changed<br /> */<br /> void changeEvent(QEvent''');


protected slots:<br /> /** this slot is called by the language menu actions<br /> '''/<br /> void slotLanguageChanged(QAction''' action);
protected slots:<br /> /** this slot is called by the language menu actions<br /> */<br /> void slotLanguageChanged(QAction''' action);


private:<br /> /** loads a language by the given language shortcur (e.g. de, en, …)<br /> '''/<br /> void loadLanguage(const QString&amp;amp; rLanguage);
private:<br /> /** loads a language by the given language shortcur (e.g. de, en, …)<br /> */<br /> void loadLanguage(const QString&amp;amp; rLanguage);
<br /> /'''* creates the language menu dynamically from the content of m_langPath<br /> '''/<br /> void createLanguageMenu(void);
<br /> /'''* creates the language menu dynamically from the content of m_langPath<br /> */<br /> void createLanguageMenu(void);
<br /> Ui::MainWindow ui; /&lt; ui definition from designer'''/<br /> QTranslator m_translator; /*'''&lt; contains the translations for this application'''/<br /> QTranslator m_translatorQt; /*'''&lt; contains the translations for qt'''/<br /> QString m_currLang; /*'''&lt; contains the currently loaded language'''/<br /> QString m_langPath; /*'''&lt; Path of language files. This is always fixed to /languages.'''/<br />};<br /></code>
<br /> Ui::MainWindow ui; /< ui definition from designer*/<br /> QTranslator m_translator; /*'''< contains the translations for this application*/<br /> QTranslator m_translatorQt; /*'''< contains the translations for qt*/<br /> QString m_currLang; /*'''< contains the currently loaded language*/<br /> QString m_langPath; /*'''< Path of language files. This is always fixed to /languages.*/<br />};<br /></code>


== Δημιουργία των language μενού ==
== Δημιουργία των language μενού ==


Το language μενού δημιουργείται δυναμικά κατά την έναρξη της εφαρμογής, ανάλογα με τα υπάρχοντα αρχεία μετάφρασης. Το πλεονέκτημα αυτής της λύσης είναι ότι μπορείτε να δώσετε οποιαδήποτε μετάφραση στην πορεία και απλά θα δουλεύει μετά από μια επανεκκίνηση. Στο συγκεκριμένο παράδειγμα, όλα τα αρχεία κειμένου βρίσκονται στον υποκατάλογο &quot;languages&amp;quot;. Είναι δυνατόν να τοποθετηθούν κάποια εικονίδια εκεί (language.png) για χρήση ως εικονίδιο του μενού (π.χ. μία σημαία).
Το language μενού δημιουργείται δυναμικά κατά την έναρξη της εφαρμογής, ανάλογα με τα υπάρχοντα αρχεία μετάφρασης. Το πλεονέκτημα αυτής της λύσης είναι ότι μπορείτε να δώσετε οποιαδήποτε μετάφραση στην πορεία και απλά θα δουλεύει μετά από μια επανεκκίνηση. Στο συγκεκριμένο παράδειγμα, όλα τα αρχεία κειμένου βρίσκονται στον υποκατάλογο "languages". Είναι δυνατόν να τοποθετηθούν κάποια εικονίδια εκεί (language.png) για χρήση ως εικονίδιο του μενού (π.χ. μία σημαία).


Κάθε γλώσσα αντιπροσωπεύετα από ένα &quot;QAction&amp;quot;:http://doc.qt.nokia.com/latest/qaction.html αντικείμενο το οποίο προστίθεται σε ένα &quot;QActionGroup&amp;quot;:http://doc.qt.nokia.com/latest/qactiongroup.html. Αυτό γίνεται ώστε να διασφαλισθεί το ότι μόνο ένας υποδοχέας (slot) χρειάζεται για όλες τις γλώσσες:<br />* '''connect(langGroup, SIGNAL (triggered(QAction *)), this, SLOT (slotLanguageChanged(QAction *)));'''
Κάθε γλώσσα αντιπροσωπεύετα από ένα "QAction":http://doc.qt.nokia.com/latest/qaction.html αντικείμενο το οποίο προστίθεται σε ένα "QActionGroup":http://doc.qt.nokia.com/latest/qactiongroup.html. Αυτό γίνεται ώστε να διασφαλισθεί το ότι μόνο ένας υποδοχέας (slot) χρειάζεται για όλες τις γλώσσες:<br />* '''connect(langGroup, SIGNAL (triggered(QAction *)), this, SLOT (slotLanguageChanged(QAction *)));'''


<code><br />// we create the menu entries dynamically, dependant on the existing translations.<br />void MainWindow::createLanguageMenu(void)<br />{<br /> QActionGroup* langGroup = new QActionGroup(ui.menuLanguage);<br /> langGroup-&gt;setExclusive(true);
<code><br />// we create the menu entries dynamically, dependant on the existing translations.<br />void MainWindow::createLanguageMenu(void)<br />{<br /> QActionGroup* langGroup = new QActionGroup(ui.menuLanguage);<br /> langGroup->setExclusive(true);


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


// format systems language<br /> QString defaultLocale = QLocale::system&amp;amp;#40;&amp;#41;.name(); // e.g. &quot;de_DE&amp;quot;<br /> defaultLocale.truncate(defaultLocale.lastIndexOf('''')); // e.g. &quot;de&amp;quot;
// format systems language<br /> QString defaultLocale = QLocale::system().name(); // e.g. "de_DE"<br /> defaultLocale.truncate(defaultLocale.lastIndexOf('''')); // e.g. "de"
<br /> m_langPath = QApplication::applicationDirPath();<br /> m_langPath.append(&quot;/languages&amp;quot;);<br /> QDir dir(m_langPath);<br /> QStringList fileNames = dir.entryList(QStringList(&quot;TranslationExample''*.qm&amp;quot;));
<br /> m_langPath = QApplication::applicationDirPath();<br /> m_langPath.append("/languages");<br /> QDir dir(m_langPath);<br /> QStringList fileNames = dir.entryList(QStringList("TranslationExample''*.qm"));


for (int i = 0; i &lt; fileNames.size(); +''i)<br /> {<br /> // get locale extracted by filename<br /> QString locale;<br /> locale = fileNames[i]; // &quot;TranslationExample_de.qm&amp;quot;<br /> locale.truncate(locale.lastIndexOf('.')); // &quot;TranslationExample_de&amp;quot;<br /> locale.remove(0, locale.indexOf('''') + 1); // &quot;de&amp;quot;
for (int i = 0; i < fileNames.size(); +''i)<br /> {<br /> // get locale extracted by filename<br /> QString locale;<br /> locale = fileNames[i]; // "TranslationExample_de.qm"<br /> locale.truncate(locale.lastIndexOf('.')); // "TranslationExample_de"<br /> locale.remove(0, locale.indexOf('''') + 1); // "de"
<br /> QString lang = QLocale::languageToString(QLocale(locale).language());<br /> QIcon ico(QString(&quot;%1/%2.png&amp;quot;).arg(m_langPath).arg(locale));
<br /> QString lang = QLocale::languageToString(QLocale(locale).language());<br /> QIcon ico(QString("%1/%2.png").arg(m_langPath).arg(locale));
<br /> QAction *action = new QAction(ico, lang, this);<br /> action-&gt;setCheckable(true);<br /> action-&gt;setData(locale);
<br /> QAction *action = new QAction(ico, lang, this);<br /> action->setCheckable(true);<br /> action->setData(locale);
<br /> ui.menuLanguage-&gt;addAction(action);<br /> langGroup-&gt;addAction(action);
<br /> ui.menuLanguage->addAction(action);<br /> langGroup->addAction(action);
<br /> // set default translators and language checked<br /> if (defaultLocale == locale)<br /> {<br /> action-&gt;setChecked(true);<br /> }<br /> }<br />}<br /></code>
<br /> // set default translators and language checked<br /> if (defaultLocale == locale)<br /> {<br /> action->setChecked(true);<br /> }<br /> }<br />}<br /></code>
<br />h2. Αλλαγή γλώσσας
<br />h2. Αλλαγή γλώσσας
<br />Εάν η γλώσσα πρέπει να αλλαχθεί, η απαιτούμενη γλώσσα-στόχος εξάγεται από το &quot;QAction&amp;quot;:http://doc.qt.nokia.com/latest/qaction.html αντικείμενο και οι υπάρχουσες μεταφράσεις απομακρύνονται (&quot;QApplication::removeTranslator&amp;quot;:http://doc.qt.nokia.com/latest/qapplication.html#removeTranslator ). Μετά από αυτό, τα νέα γλωσσικά αρχεία φορτώνονται, και εάν αυτό γίνει επιτυχώς, ο μεταφραστής εγκαθίσταται και πάλι (&quot;QApplication::installTranslator&amp;quot;:http://doc.qt.nokia.com/latest/qapplication.html#installTranslator ). Αυτό γίνεται για να διασφαλισθεί ότι ένα &quot;QEvent::LanguageChange&amp;quot;:http://doc.qt.nokia.com/latest/qevent.html#Type-enum event εκπέμπεται (emitted) από το αντικείμενο της εφαρμογής. Εάν η εφαρμογή απλά περιέχει μόνο ένα top level window, το οποίο δημιουργείται εξ' ολοκλήρου από τον designer, είναι επίσης εφικτό να διαβαστούν απλά τα νέα αρχεία μετάφρασης και να κληθεί το '''ui.retranslateUi(this)''' απευθείας.<br /><code><br />// Called every time, when a menu entry of the language menu is called<br />void MainWindow::slotLanguageChanged(QAction* action)<br />{<br /> if(0 != action)<br /> {<br /> // load the language dependant on the action content<br /> loadLanguage(action-&gt;data().toString());<br /> setWindowIcon(action-&gt;icon());<br /> }<br />}
<br />Εάν η γλώσσα πρέπει να αλλαχθεί, η απαιτούμενη γλώσσα-στόχος εξάγεται από το "QAction":http://doc.qt.nokia.com/latest/qaction.html αντικείμενο και οι υπάρχουσες μεταφράσεις απομακρύνονται ("QApplication::removeTranslator":http://doc.qt.nokia.com/latest/qapplication.html#removeTranslator ). Μετά από αυτό, τα νέα γλωσσικά αρχεία φορτώνονται, και εάν αυτό γίνει επιτυχώς, ο μεταφραστής εγκαθίσταται και πάλι ("QApplication::installTranslator":http://doc.qt.nokia.com/latest/qapplication.html#installTranslator ). Αυτό γίνεται για να διασφαλισθεί ότι ένα "QEvent::LanguageChange":http://doc.qt.nokia.com/latest/qevent.html#Type-enum event εκπέμπεται (emitted) από το αντικείμενο της εφαρμογής. Εάν η εφαρμογή απλά περιέχει μόνο ένα top level window, το οποίο δημιουργείται εξ' ολοκλήρου από τον designer, είναι επίσης εφικτό να διαβαστούν απλά τα νέα αρχεία μετάφρασης και να κληθεί το '''ui.retranslateUi(this)''' απευθείας.<br /><code><br />// Called every time, when a menu entry of the language menu is called<br />void MainWindow::slotLanguageChanged(QAction* action)<br />{<br /> if(0 != action)<br /> {<br /> // load the language dependant on the action content<br /> loadLanguage(action->data().toString());<br /> setWindowIcon(action->icon());<br /> }<br />}
<br />void switchTranslator(QTranslator&amp;amp; translator, const QString&amp;amp; filename)<br />{<br /> // remove the old translator<br /> qApp-&gt;removeTranslator(&amp;translator;);
<br />void switchTranslator(QTranslator&amp;amp; translator, const QString&amp;amp; filename)<br />{<br /> // remove the old translator<br /> qApp->removeTranslator(&amp;translator;);
<br /> // load the new translator<br /> if(translator.load(filename))<br /> qApp-&gt;installTranslator(&amp;translator;);<br />}
<br /> // load the new translator<br /> if(translator.load(filename))<br /> qApp->installTranslator(&amp;translator;);<br />}
<br />void MainWindow::loadLanguage(const QString&amp;amp; rLanguage)<br />{<br /> if(m_currLang != rLanguage)<br /> {<br /> m_currLang = rLanguage;<br /> QLocale locale = QLocale(m_currLang);<br /> QLocale::setDefault(locale);<br /> QString languageName = QLocale::languageToString(locale.language());<br /> switchTranslator(m_translator, QString(&quot;TranslationExample''%1.qm&amp;quot;).arg(rLanguage));<br /> switchTranslator(m_translatorQt, QString(&quot;qt_%1.qm&amp;quot;).arg(rLanguage));<br /> ui.statusBar-&gt;showMessage(tr(&quot;Current Language changed to %1&amp;quot;).arg(languageName));<br /> }<br />}<br /></code>
<br />void MainWindow::loadLanguage(const QString&amp;amp; rLanguage)<br />{<br /> if(m_currLang != rLanguage)<br /> {<br /> m_currLang = rLanguage;<br /> QLocale locale = QLocale(m_currLang);<br /> QLocale::setDefault(locale);<br /> QString languageName = QLocale::languageToString(locale.language());<br /> switchTranslator(m_translator, QString("TranslationExample''%1.qm").arg(rLanguage));<br /> switchTranslator(m_translatorQt, QString("qt_%1.qm").arg(rLanguage));<br /> ui.statusBar->showMessage(tr("Current Language changed to %1").arg(languageName));<br /> }<br />}<br /></code>
<br />* &quot;QEvent::LanguageChange&amp;quot;:http://doc.qt.nokia.com/latest/qevent.html#Type-enum θα καλείται πάντα, εάν ένα αντικείμενο μετάφρασης είναι εγκατεστημένο στο αντικείμενο της εφαρμογής<br />* &quot;QEvent::LocaleChange&amp;quot;:http://doc.qt.nokia.com/latest/qevent.html#Type-enum καλείται, όταν η γλώσσα του συστήματος αλλάζει
<br />* "QEvent::LanguageChange":http://doc.qt.nokia.com/latest/qevent.html#Type-enum θα καλείται πάντα, εάν ένα αντικείμενο μετάφρασης είναι εγκατεστημένο στο αντικείμενο της εφαρμογής<br />* "QEvent::LocaleChange":http://doc.qt.nokia.com/latest/qevent.html#Type-enum καλείται, όταν η γλώσσα του συστήματος αλλάζει
<br /><code><br />void MainWindow::changeEvent(QEvent* event)<br />{<br /> if(0 != event)<br /> {<br /> switch(event-&gt;type())<br /> {<br /> // this event is send if a translator is loaded<br /> case QEvent::LanguageChange:<br /> ui.retranslateUi(this);<br /> break;<br /> // this event is send, if the system, language changes<br /> case QEvent::LocaleChange:<br /> {<br /> QString locale = QLocale::system&amp;amp;#40;&amp;#41;.name();<br /> locale.truncate(locale.lastIndexOf('_'));<br /> loadLanguage(locale);<br /> }<br /> break;<br /> }<br /> }
<br /><code><br />void MainWindow::changeEvent(QEvent* event)<br />{<br /> if(0 != event)<br /> {<br /> switch(event->type())<br /> {<br /> // this event is send if a translator is loaded<br /> case QEvent::LanguageChange:<br /> ui.retranslateUi(this);<br /> break;<br /> // this event is send, if the system, language changes<br /> case QEvent::LocaleChange:<br /> {<br /> QString locale = QLocale::system().name();<br /> locale.truncate(locale.lastIndexOf('_'));<br /> loadLanguage(locale);<br /> }<br /> break;<br /> }<br /> }
<br /> QMainWindow::changeEvent(event);<br />}<br /></code>
<br /> QMainWindow::changeEvent(event);<br />}<br /></code>
<br />h2. Προσθήκη μεταφράσεων στο project
<br />h2. Προσθήκη μεταφράσεων στο project
<br />Στο &quot;QMake&amp;quot;:http://doc.qt.nokia.com/latest/qmake-manual.html σας project αρχείο, η ακόλουθη μεταβλητή &quot;'''TRANSLATIONS'''&quot;:http://doc.qt.nokia.com/latest/qmake-variable-reference.html#translations πρέπει να προστεθεί και πρέπει να περιέχει όλα τα αρχεία συστήματος που θέλετε να δημιουργήσετε αρχικά.<br /><code><br />TRANSLATIONS = languages/TranslationExample_en.ts  languages/TranslationExample_de.ts<br /></code>
<br />Στο "QMake":http://doc.qt.nokia.com/latest/qmake-manual.html σας project αρχείο, η ακόλουθη μεταβλητή "'''TRANSLATIONS'''":http://doc.qt.nokia.com/latest/qmake-variable-reference.html#translations πρέπει να προστεθεί και πρέπει να περιέχει όλα τα αρχεία συστήματος που θέλετε να δημιουργήσετε αρχικά.<br /><code><br />TRANSLATIONS = languages/TranslationExample_en.ts  languages/TranslationExample_de.ts<br /></code>
<br />Καλώντας την &quot;lupdate&amp;quot;:http://doc.qt.nokia.com/latest/linguist-manager.html#lupdate<br /><code><br />lupdate -verbose TranslationExample.pro<br /></code><br />Δημιουργείτε τα γλωσσικά αρχεία ('''.ts), τα οποία μεταφράζετε χρησιμοποιώντας το εργαλείο &quot;Qt Linguist&amp;quot;:http://doc.qt.nokia.com/latest/linguist-manual.html  
<br />Καλώντας την "lupdate":http://doc.qt.nokia.com/latest/linguist-manager.html#lupdate<br /><code><br />lupdate -verbose TranslationExample.pro<br /></code><br />Δημιουργείτε τα γλωσσικά αρχεία ('''.ts), τα οποία μεταφράζετε χρησιμοποιώντας το εργαλείο "Qt Linguist":http://doc.qt.nokia.com/latest/linguist-manual.html  
<br /><code><br />linguist languages/TranslationExample_en.ts languages/TranslationExample_de.ts<br /></code>
<br /><code><br />linguist languages/TranslationExample_en.ts languages/TranslationExample_de.ts<br /></code>
<br />Μετά από αυτό, καλείτε την &quot;lrelease&amp;quot;:http://doc.qt.nokia.com/latest/linguist-manager.html#lrelease για να δημιουργήσετε τα binary γλωσσικά αρχεία ('''.qm):
<br />Μετά από αυτό, καλείτε την "lrelease":http://doc.qt.nokia.com/latest/linguist-manager.html#lrelease για να δημιουργήσετε τα binary γλωσσικά αρχεία ('''.qm):
<br /><code><br />lrelease TranslationExample.pro<br /></code>
<br /><code><br />lrelease TranslationExample.pro<br /></code>
<br />h3. Στοχεύοντας το Symbian
<br />h3. Στοχεύοντας το Symbian
<br />Σε περίπτωση που η εφαρμογή σας έχει ως στόχο και το Symbian, τότε πρέπει να προστεθεί και ένας ακόμα ειδικός κανόνας στο .pro αρχείο ώστε να τοποθετήσει τα .qm αρχεία μαζί με το εκτελέσιμο αρχείο. Οπότε η προσθήκη είναι η εξής:
<br />Σε περίπτωση που η εφαρμογή σας έχει ως στόχο και το Symbian, τότε πρέπει να προστεθεί και ένας ακόμα ειδικός κανόνας στο .pro αρχείο ώστε να τοποθετήσει τα .qm αρχεία μαζί με το εκτελέσιμο αρχείο. Οπότε η προσθήκη είναι η εξής:
<br /><code><br />symbian: {<br />addFiles.sources = TranslationExample_en.qm TranslationExample_de.qm<br />addFiles.path = .<br />DEPLOYMENT''= addFiles<br />}<br /></code>
<br /><code><br />symbian: {<br />addFiles.sources = TranslationExample_en.qm TranslationExample_de.qm<br />addFiles.path = .<br />DEPLOYMENT''= addFiles<br />}<br /></code>

Revision as of 14:47, 24 February 2015


Ελληνικά German English

[toc align_right="yes" depth="2"]

Πώς να δημιουργήσετε μια πολυγλωσσική εφαρμογή με δυνατότητα εναλλαγής γλώσσας κατά το χρόνο εκτέλεσης;

Δημιουργήστε μία standard εφαρμογή, δηλαδή με main window

Hauptfenster der Applikation
Στο παράδειγμα αυτό, δημιουργούμε ένα main window με ένα μενού Language και κάποια widget. Εάν ο χρήστης άνοιξε το μενού language, υπάρχει μια επιλογή γλώσσας, η οποία δημιουργείται κατά την έναρξη της εφαρμογής, και εξαρτάται από τα υπάρχοντα γλωσσικά αρχεία.
Hauptfenster der Applikation mit Sprachmenü

Η δομή αρχείων της εφαρμογής:

  • <Κατάλογος εφαρμογής&amp;gt;
    • binaries
  • <Κατάλογος εφαρμογής&amp;gt;/languages
    • Για κάθε εγκατεστημένη γλώσσα, υπάρχει ένα (προαιρετικό) αρχείο εικόνας μεγέθους 16x16 pixel με μία σημαία (π.χ. de.png)
    • Τα μεταφρασμένα αρχεία κειμένου της εφαρμογής (TranslationExample_.qm, όπου μπορεί να είναι be de, en, …)
    • τα αρχεία μετάφρασης του Qt (qt_.qm)


h2. Ορισμός κλάσης
Στην κλάση MainWindow, η virtual method "changeEvent(QEvent)":http://doc.qt.nokia.com/latest/qwidget.html#changeEvent γίνεται overwritten. Για κάθε αρχείο μετάφρασης που απαιτείται, ένα "QTranslator":http://doc.qt.nokia.com/latest/qtranslator.html στιγμιότυπο δημιουργείται (στο συγκεκριμένο παράδειγμα 2, ένα για τα application texts, ένα για το qt). Η τρέχουσα γλώσσα αποθηκεύεται για να suppress events, εάν ο χρήστης προσπαθήσει να φορτώσει την ίδια γλώσσα δύο φορές.

<br />class MainWindow : public QMainWindow<br />{<br /> 

protected:<br /> /** this event is called, when a new translator is loaded or the system language is changed<br /> */<br /> void changeEvent(QEvent''');

protected slots:<br /> /** this slot is called by the language menu actions<br /> */<br /> void slotLanguageChanged(QAction''' action);

private:<br /> /** loads a language by the given language shortcur (e.g. de, en, …)<br /> */<br /> void loadLanguage(const QString&amp;amp; rLanguage);
<br /> /'''* creates the language menu dynamically from the content of m_langPath<br /> */<br /> void createLanguageMenu(void);
<br /> Ui::MainWindow ui; /< ui definition from designer*/<br /> QTranslator m_translator; /*'''< contains the translations for this application*/<br /> QTranslator m_translatorQt; /*'''< contains the translations for qt*/<br /> QString m_currLang; /*'''< contains the currently loaded language*/<br /> QString m_langPath; /*'''< Path of language files. This is always fixed to /languages.*/<br />};<br />

Δημιουργία των language μενού

Το language μενού δημιουργείται δυναμικά κατά την έναρξη της εφαρμογής, ανάλογα με τα υπάρχοντα αρχεία μετάφρασης. Το πλεονέκτημα αυτής της λύσης είναι ότι μπορείτε να δώσετε οποιαδήποτε μετάφραση στην πορεία και απλά θα δουλεύει μετά από μια επανεκκίνηση. Στο συγκεκριμένο παράδειγμα, όλα τα αρχεία κειμένου βρίσκονται στον υποκατάλογο "languages". Είναι δυνατόν να τοποθετηθούν κάποια εικονίδια εκεί (language.png) για χρήση ως εικονίδιο του μενού (π.χ. μία σημαία).

Κάθε γλώσσα αντιπροσωπεύετα από ένα "QAction":http://doc.qt.nokia.com/latest/qaction.html αντικείμενο το οποίο προστίθεται σε ένα "QActionGroup":http://doc.qt.nokia.com/latest/qactiongroup.html. Αυτό γίνεται ώστε να διασφαλισθεί το ότι μόνο ένας υποδοχέας (slot) χρειάζεται για όλες τις γλώσσες:
* connect(langGroup, SIGNAL (triggered(QAction *)), this, SLOT (slotLanguageChanged(QAction *)));

<br />// we create the menu entries dynamically, dependant on the existing translations.<br />void MainWindow::createLanguageMenu(void)<br />{<br /> QActionGroup* langGroup = new QActionGroup(ui.menuLanguage);<br /> langGroup->setExclusive(true);

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

// format systems language<br /> QString defaultLocale = QLocale::system().name(); // e.g. "de_DE"<br /> defaultLocale.truncate(defaultLocale.lastIndexOf('''')); // e.g. "de"
<br /> m_langPath = QApplication::applicationDirPath();<br /> m_langPath.append("/languages");<br /> QDir dir(m_langPath);<br /> QStringList fileNames = dir.entryList(QStringList("TranslationExample''*.qm"));

for (int i = 0; i < fileNames.size(); +''i)<br /> {<br /> // get locale extracted by filename<br /> QString locale;<br /> locale = fileNames[i]; // "TranslationExample_de.qm"<br /> locale.truncate(locale.lastIndexOf('.')); // "TranslationExample_de"<br /> locale.remove(0, locale.indexOf('''') + 1); // "de"
<br /> QString lang = QLocale::languageToString(QLocale(locale).language());<br /> QIcon ico(QString("%1/%2.png").arg(m_langPath).arg(locale));
<br /> QAction *action = new QAction(ico, lang, this);<br /> action->setCheckable(true);<br /> action->setData(locale);
<br /> ui.menuLanguage->addAction(action);<br /> langGroup->addAction(action);
<br /> // set default translators and language checked<br /> if (defaultLocale == locale)<br /> {<br /> action->setChecked(true);<br /> }<br /> }<br />}<br />


h2. Αλλαγή γλώσσας


Εάν η γλώσσα πρέπει να αλλαχθεί, η απαιτούμενη γλώσσα-στόχος εξάγεται από το "QAction":http://doc.qt.nokia.com/latest/qaction.html αντικείμενο και οι υπάρχουσες μεταφράσεις απομακρύνονται ("QApplication::removeTranslator":http://doc.qt.nokia.com/latest/qapplication.html#removeTranslator ). Μετά από αυτό, τα νέα γλωσσικά αρχεία φορτώνονται, και εάν αυτό γίνει επιτυχώς, ο μεταφραστής εγκαθίσταται και πάλι ("QApplication::installTranslator":http://doc.qt.nokia.com/latest/qapplication.html#installTranslator ). Αυτό γίνεται για να διασφαλισθεί ότι ένα "QEvent::LanguageChange":http://doc.qt.nokia.com/latest/qevent.html#Type-enum event εκπέμπεται (emitted) από το αντικείμενο της εφαρμογής. Εάν η εφαρμογή απλά περιέχει μόνο ένα top level window, το οποίο δημιουργείται εξ' ολοκλήρου από τον designer, είναι επίσης εφικτό να διαβαστούν απλά τα νέα αρχεία μετάφρασης και να κληθεί το ui.retranslateUi(this) απευθείας.

<br />// Called every time, when a menu entry of the language menu is called<br />void MainWindow::slotLanguageChanged(QAction* action)<br />{<br /> if(0 != action)<br /> {<br /> // load the language dependant on the action content<br /> loadLanguage(action->data().toString());<br /> setWindowIcon(action->icon());<br /> }<br />}
<br />void switchTranslator(QTranslator&amp;amp; translator, const QString&amp;amp; filename)<br />{<br /> // remove the old translator<br /> qApp->removeTranslator(&amp;translator;);
<br /> // load the new translator<br /> if(translator.load(filename))<br /> qApp->installTranslator(&amp;translator;);<br />}
<br />void MainWindow::loadLanguage(const QString&amp;amp; rLanguage)<br />{<br /> if(m_currLang != rLanguage)<br /> {<br /> m_currLang = rLanguage;<br /> QLocale locale = QLocale(m_currLang);<br /> QLocale::setDefault(locale);<br /> QString languageName = QLocale::languageToString(locale.language());<br /> switchTranslator(m_translator, QString("TranslationExample''%1.qm").arg(rLanguage));<br /> switchTranslator(m_translatorQt, QString("qt_%1.qm").arg(rLanguage));<br /> ui.statusBar->showMessage(tr("Current Language changed to %1").arg(languageName));<br /> }<br />}<br />


* "QEvent::LanguageChange":http://doc.qt.nokia.com/latest/qevent.html#Type-enum θα καλείται πάντα, εάν ένα αντικείμενο μετάφρασης είναι εγκατεστημένο στο αντικείμενο της εφαρμογής
* "QEvent::LocaleChange":http://doc.qt.nokia.com/latest/qevent.html#Type-enum καλείται, όταν η γλώσσα του συστήματος αλλάζει


<br />void MainWindow::changeEvent(QEvent* event)<br />{<br /> if(0 != event)<br /> {<br /> switch(event->type())<br /> {<br /> // this event is send if a translator is loaded<br /> case QEvent::LanguageChange:<br /> ui.retranslateUi(this);<br /> break;<br /> // this event is send, if the system, language changes<br /> case QEvent::LocaleChange:<br /> {<br /> QString locale = QLocale::system().name();<br /> locale.truncate(locale.lastIndexOf('_'));<br /> loadLanguage(locale);<br /> }<br /> break;<br /> }<br /> }
<br /> QMainWindow::changeEvent(event);<br />}<br />


h2. Προσθήκη μεταφράσεων στο project


Στο "QMake":http://doc.qt.nokia.com/latest/qmake-manual.html σας project αρχείο, η ακόλουθη μεταβλητή "TRANSLATIONS":http://doc.qt.nokia.com/latest/qmake-variable-reference.html#translations πρέπει να προστεθεί και πρέπει να περιέχει όλα τα αρχεία συστήματος που θέλετε να δημιουργήσετε αρχικά.

<br />TRANSLATIONS = languages/TranslationExample_en.ts  languages/TranslationExample_de.ts<br />


Καλώντας την "lupdate":http://doc.qt.nokia.com/latest/linguist-manager.html#lupdate

<br />lupdate -verbose TranslationExample.pro<br />


Δημιουργείτε τα γλωσσικά αρχεία (.ts), τα οποία μεταφράζετε χρησιμοποιώντας το εργαλείο "Qt Linguist":http://doc.qt.nokia.com/latest/linguist-manual.html

<br />linguist languages/TranslationExample_en.ts languages/TranslationExample_de.ts<br />


Μετά από αυτό, καλείτε την "lrelease":http://doc.qt.nokia.com/latest/linguist-manager.html#lrelease για να δημιουργήσετε τα binary γλωσσικά αρχεία (.qm):


<br />lrelease TranslationExample.pro<br />


h3. Στοχεύοντας το Symbian
Σε περίπτωση που η εφαρμογή σας έχει ως στόχο και το Symbian, τότε πρέπει να προστεθεί και ένας ακόμα ειδικός κανόνας στο .pro αρχείο ώστε να τοποθετήσει τα .qm αρχεία μαζί με το εκτελέσιμο αρχείο. Οπότε η προσθήκη είναι η εξής:


<br />symbian: {<br />addFiles.sources = TranslationExample_en.qm TranslationExample_de.qm<br />addFiles.path = .<br />DEPLOYMENT''= addFiles<br />}<br />