FAQ sur l'internationalisationDate de publication : 01/09/2009. Date de mise à jour : 01/08/2011.
Par
Jasmin Blanchette traducteur : Thibaut Cuvelier (Site web) (Blog) Qt Quarterly
Cet article fournit des réponses à quelques questions fréquemment posées sur l'internationalisation des programmes Qt.
Il couvre des sujets variés, comme la distribution des fichiers de traduction, les traductions inversées et
le changement dynamique de langue.
I. L'article original
II. Comment puis-je distribuer les fichiers de traduction de mon application ?
III. Mon application a été développée avec Qt Designer. J'aimerais donner les fichier de Qt Designer au traducteur,
avec Qt Designer, mais je ne trouve pas de moyen pour spécifier une traduction dans Qt Designer.
Y a-t-il un moyen de prévisualiser un fichier Qt Designer avec une traduction ?
IV. Dans mon application, je dois chercher des traductions pour plusieurs langues, mais tr() ne renvoie
que la traduction de la dernière langue installée. Y a-t-il un paramètre de langue à la fonction tr()
pour spécifier le fichier de traduction à utiliser ?
V. J'aimerais stocker mes traductions dans une base de données. Comment dire à tr() d'aller les y chercher ?
VI. Mon application contient un texte en allemand ("Bestätigen"), mais, quand je charge le fichier de traduction
dans un éditeur de texte, c'est une autre chaîne qui apparaît ("BestÃtigen"). Comment le faire changer d'avis ?
VII. Comment changer la langue de mon application quand elle est lancée ?
VIII. Je crée une boîte avec les boutons tr("Yes") et tr("No"). Grâce à la fonction tr(), les chaînes sont traduites.
Par contre, à d'autres endroits, l'application nécessite les chaînes en anglais. Qt fournit-il une manière de faire
correspondre tr("Yes") à "Yes" ?
IX. Divers
I. L'article original
Qt Quarterly est une revue trimestrielle électronique proposée par Nokia à destination des développeurs et
utilisateurs de Qt. Vous pouvez trouver les
versions originales.
Nokia, Qt, Qt Quarterly et leurs logos sont des marques déposées de Nokia Corporation en Finlande
et/ou dans les autres pays. Les autres marques déposées sont détenues par leurs propriétaires respectifs.
Cet article est une traduction d'un des tutoriels écrits par Nokia Corporation and/or its subsidiary(-ies)
inclus dans la documentation de Qt, en anglais. Les éventuels problèmes résultant d'une mauvaise traduction ne sont
pas imputables à Nokia.
II. Comment puis-je distribuer les fichiers de traduction de mon application ?
La manière standard est de les mettre dans un dossier sur le client, et de les charger à l'exécution.
Cependant, si elle ne peut pas les trouver, l'application se lancera sans traduction.
Pour éviter ce problème, on peut utiliser l'outil qembed, disponible dans le dossier
tools, pour incorporer ces fichiers à l'application.
qembed myapp_de.qm myapp_fr.qm > qm_files.h
|
L'outil crée un tableau constant et statique des données qu'il suffit alors d'inclure.
# include " qm_files.h "
int main(int argc, char * argv[])
{
...
QTranslator translator;
translator.load(myapp_de_qm_data, myapp_de_qm_len);
app.installTranslator(& translator);
...
}
|
La fonction load(), surcharge apparue
dans Qt 3.2, accepte les données brutes du fichier de traduction, au lieu du nom de fichier.
qembed doit être appelé à chaque changement dans les fichiers de traduction, pour garder
la version de l'application à jour. Dans un futur, ceci pourrait être intégré à qmake,
comme ce qui arrive avec les collections d'images.
III. Mon application a été développée avec Qt Designer. J'aimerais donner les fichier de Qt Designer au traducteur,
avec Qt Designer, mais je ne trouve pas de moyen pour spécifier une traduction dans Qt Designer.
Y a-t-il un moyen de prévisualiser un fichier Qt Designer avec une traduction ?
Ni Qt Designer, ni Qt Linguist ne proposent cette fonctionnalité. Cependant, il est assez facile de le faire
avec QWidgetFactory, une classe qui construit
dynamiquement un widget sur base d'un fichier d'interface utilisateur.
# include < qapplication.h>
# include < qtranslator.h>
# include < qwidgetfactory.h>
int main(int argc, char * argv[])
{
QApplication app(argc, argv);
if (argc < 3 )
{
qWarning (" Usage: lpreview " " file.qm form1.ui... " );
return 1 ;
}
QTranslator translator;
translator.load(argv[1 ]);
app.installTranslator(& translator);
for (int i = 2 ; i < argc; + + i)
{
QWidget * widget = QWidgetFactory:: create(argv[i]);
widget- > show();
}
QObject :: connect (& app, SIGNAL (lastWindowClosed()), & app, SLOT (quit()));
return app.exec();
}
|
Cet outil prend, en paramètres, un fichier de traduction et un fichier d'interface utilisateur. Pour compiler
l'exemple, vous devrez lier contre la librairie qui de cette manière :
La ligne LIBS fonctionne correctement sur plusieurs plateformes sans problème depuis Qt 3.2.
Pour les versions plus anciennes, utilisez ces lignes-ci :
unix:LIBS += -lqui
win:LIBS += $(QTDIR)/lib/qui.lib
|
IV. Dans mon application, je dois chercher des traductions pour plusieurs langues, mais tr() ne renvoie
que la traduction de la dernière langue installée. Y a-t-il un paramètre de langue à la fonction tr()
pour spécifier le fichier de traduction à utiliser ?
tr() est basé sur l'idée qu'une seule langue doit être chargée à la fois. Cependant,
vous pouvez instancier plusieurs QTranslator,
chacun chargeant une langue, et, ensuite, appeler
findMessage() pour trouver une
traduction, au lieu de tr().
QTranslator thaiTranslator;
thaiTranslator.load(" myapp_th.qm " );
QTranslator urduTranslator;
urduTranslator.load(" myapp_da.qm " );
thaiStr = thaiTranslator.findMessage(" MainForm " , " Help " ).translation();
urduStr = urduTranslator.findMessage(" MainForm " , " Help " ).translation();
|
V. J'aimerais stocker mes traductions dans une base de données. Comment dire à tr() d'aller les y chercher ?
class DBTranslator : public QTranslator
{
public :
QTranslatorMessage findMessage(const char * context,
const char * sourceText, const char * comment);
} ;
QTranslatorMessage DBTranslator:: findMessage(const char * context,
const char * sourceText, const char * comment)
{
QSqlQuery query;
query.prepare(" SELECT translation FROM message "
" WHERE context=? AND sourcetext=? AND comment=? " );
query.addBindValue(context);
query.addBindValue(sourceText);
query.addBindValue(comment);
query.exec();
if (query.next())
{
return QTranslatorMessage(context, sourceText, comment, query.value(0 ).toString());
}
return QTranslatorMessage();
}
|
Dans la fonction main(), vous devriez écrire quelque chose de ce genre :
int main(int argc, char * argv[])
{
...
DBTranslator translator;
app.installTranslator(& translator);
...
}
|
VI. Mon application contient un texte en allemand ("Bestätigen"), mais, quand je charge le fichier de traduction
dans un éditeur de texte, c'est une autre chaîne qui apparaît ("BestÃtigen"). Comment le faire changer d'avis ?
Les fichiers XML, les sources de la traduction générés par lupdate, utilisent l'encodage UTF-8.
C'est l'encodage par défaut, mais il est incompatible avec d'autres encodages populaires, comme le Latin-1
(ISO 8859-1) dans l'Europe de l'Ouest.
Pour convertir un fichier XML, il ne suffit pas de changer l'encodage à l'enregistrement, il faut aussi
modifier son en-tête, que nous devons mettre au début du fichier.
<? xml version="1.0" encoding="ISO-8859-1"? >
|
On peut écrire un outil pour automatiser cette conversion.
int main(int argc, char * argv[])
{
if (argc < 3 ) {
qWarning (" Usage: lencode encoding file1.ts... " );
return 1 ;
}
QTextCodec * codec = QTextCodec :: codecForName(argv[1 ]);
if (! codec) {
qWarning (" Unknown encoding: %s " , argv[1 ]);
return 1 ;
}
for (int i = 2 ; i < argc; + + i)
encodeFile(codec, argv[i]);
return 0 ;
}
|
L'outil prend deux paramètres : l'encodage, et le fichier à encoder. Ensuite, il convertit le fichier dans l'encodage
spécifié. La majeure partie du travail est effectuée par cette fonction.
void encodeFile(QTextCodec * codec, const char * fileName)
{
QFile file(fileName);
QDomDocument doc;
if (! file.open(IO_ReadOnly | IO_Translate))
;
if (! doc.setContent(& file, true ))
;
if (doc.firstChild().isProcessingInstruction() & & doc.firstChild().nodeName() = = " xml " )
doc.removeChild(doc.firstChild());
QDomNode node = doc.createProcessingInstruction(" xml " ,
QString (" version=\"1.0\" encoding=\" " ) + codec- > mimeName() + " \" " );
doc.insertBefore(node, doc.firstChild());
file.close();
if (! file.open(IO_WriteOnly | IO_Translate))
;
QTextStream out(& file);
doc.save(out, 4 );
}
|
La fonction encodeFile() charge le fichier dans un arbre DOM. Ensuite, elle supprime tout en-tête
préexistant, et ajoute l'en-tête correspondant à l'encodage. À la fin, elle appelle
save() pour enregistrer l'arbre sur le disque dur.
Cette fonction lit l'en-tête nouvellement ajouté, et utilise l'encodage spécifié pour l'enregistrement. S'il n'est pas
précisé, elle retombe sur UTF-8. Le code pour la gestion des erreurs a été enlevé pour garder un peu d'espace pour le
reste.
VII. Comment changer la langue de mon application quand elle est lancée ?
Ce serait bien si l'application pouvait changer de langue en même temps que l'utilisateur change
ses paramètres de langue. Cependant, cela est impossible, car les widgets n'ont accès qu'aux versions traduites
des chaînes.
tr(" Host %1 found " ).arg(host)
|
Cette chaîne pourrait être vu comme "Hôte www.troll.no trouvé", depuis laquelle il est virtuellement impossible
de découvrir d'où elle vient, et de la traduire vers "Rechner %1 gefunden".
Néanmoins, il est assez facile de changer dynamiquement de langue avec Qt. L'idée de base est de créer une fonction
qui donne à tous les widgets leur texte.
MyDialog:: MyDialog(QWidget * parent, const char * name)
: QDialog (parent, name)
{
label = new QLabel (this );
lineEdit = new QLineEdit (this );
label- > setBuddy(lineEdit);
okButton = new QPushButton (this );
connect (okButton, SIGNAL (clicked()), this , SLOT (accept()));
retranslateStrings();
}
void MyDialog:: retranslateStrings()
{
label- > setText(tr(" &Name: " ));
okButton- > setText(tr(" OK " ));
}
|
Il suffit alors d'appeler la fonction retranslateStrings() à chaque changement de langue.
VIII. Je crée une boîte avec les boutons tr("Yes") et tr("No"). Grâce à la fonction tr(), les chaînes sont traduites.
Par contre, à d'autres endroits, l'application nécessite les chaînes en anglais. Qt fournit-il une manière de faire
correspondre tr("Yes") à "Yes" ?
Oui. Bien que QTranslator ne fournisse pas
de méthode appropriée pour cela, messages()
retourne une liste des entrées du fichier de traduction. Vous pouvez ensuite la parcourir pour trouver
une entrée avec la bonne traduction.
QCString reverseLookup(const QTranslator & translator,
const char * context, const QString & translation)
{
typedef QValueList< QTranslatorMessage> MessageList;
MessageList messages = translator.messages();
MessageList:: iterator it = messages.begin();
while (it ! = messages.end())
{
if ((* it).translation() = = translation & & (* it).context() = = QCString(context))
return (* it).sourceText();
+ + it;
}
return " " ;
}
|
 |
Ceci ne fonctionne que sur des fichiers non compressés. Sinon, la valeur de retour de la fonction est indéterminée.
pour générer des fichiers non compressés, appelez lrelease avec le paramètre
-nocompress, apparu avec Qt 3.2.
|
IX. Divers
Ceci a été écrit pour Qt3. Cependant, la majorité du contenu reste d'actualité pour Qt4.
Au nom de toute l'équipe Qt, j'aimerais adresser le plus grand remerciement à Nokia pour nous avoir
autorisé la traduction de cet article !
Copyright ©2003 Jasmin Blanchette.
Aucune reproduction, même partielle, ne peut être faite
de ce site et de l'ensemble de son contenu : textes, documents, images, etc
sans l'autorisation expresse de l'auteur. Sinon vous encourez selon la loi jusqu'à 3 ans de prison et jusqu'à 300 000 E
de dommages et intérêts. Cette page est déposée à la SACD.
|