Bienvenue sur le forum !

Si vous souhaitez rejoindre la communauté, cliquez sur l'un de ces boutons !

Qt 5 : 5.9.1 - Qt Creator : 4.3.1 - Qt Installer : 2.0.3 - JOM : 1.1.2 - Qt Build suite : 1.7.0 - VS Qt 5 : 2.0.0

Traduire une application Qt - principes simples

Ne pas confondre traduction et internationalisation, ce dernier mot recouvrant un domaine bien plus large que le premier.

Je définis le comportement que j'attends de mon appli. Je veux que dans un système français elle m'affiche une boîte de progression du genre
"10 fichiers copiés sur 100 [Annuler]"
et que, lorsque le système est anglais, elle affiche à l'utilisateur sans qu'il ne demande rien :
"10/100 files copied [Cancel]"

Ce n'est pas magique, on va dire à Qt dans le main () de charger le fichier contenant les traductions dans la langue en cours

Quelques indications sur les processus :

Qt prévoit 2 types de fichiers de trad : le .ts et le .qm
Le TS (Translation Source file) c'est le brouillon. Le développeur le génère automatiquement et le confie au traducteur. Pour le présent exemple je jouerai le rôle du traducteur.
Le traducteur le complète, l'améliore et renvoie le TS modifié au développeur.
Le développeur le "compile" en QM (Qt Message file) et l'intègre à l'appli.
L'appli se lance et charge le QM correspondant à la langue courante. Elle affiche alors les textes dans cette langue.
Une erreur de trad ? le traducteur récupère le TS, le corrige, le renvoie au développeur qui refait un QM correct
et ainsi de suite.

Préparation :

D'abord le plus simple : indiquer à Qt que je veux qu'il affiche ses boîtes de dialogue avec des libellés dans la langue système. Dans main :
    // pour avoir les boutons des boîtes de dialogue dans la langue locale (fr par défaut)
QTranslator translator;
translator.load ("qt_" + QLocale::system ().name (), QLibraryInfo::location (QLibraryInfo::TranslationsPath));
app.installTranslator (&translator);
Ça fait barbare mais c'est très lisible quand on décompose : pour un système français par exemple, QLocale::system ().name () == "fr" On lui dit donc d'aller chercher qt_fr.qm dans le répertoire où il a installé ses traductions ( QLibraryInfo::location (QLibraryInfo::TranslationsPath) )
L'ajout de ces quelques lignes affichera automatiquement Annuler ou Cancel sur les boutons standard de Qt.

Ensuite mon appli

L'appli doit être livrée avec ses propres fichiers QM de traduction. Le mieux est de les mettre dans les resources. Pour ce faire :
Je décide du sous-répertoire de travail dans lequel je vais entreposer ces traductions : i18n ou translate ou traductions, comme vous voulez. Moi j'aime bien i18n et mon projet s'appelle "dicodor" dans le reste de ce message
Je préviens Qt qu'il doit placer les traductions dans ce répertoire en ajoutant au fichier PRO (dicodor.pro) ceci :
TRANSLATIONS += i18n/dicodor_en.ts i18n/dicodor_fr.ts i18n/dicodor_it.ts
j'ai indiqué par cette ligne mon ambition de le traduire en anglais et en italien. J'ai rajouté français pour me permettre de corriger d'éventuelles fautes d'orthographe dans mon code sans devoir aller fouiller dans les fichiers sources.

Au lancement de l'appli, Qt doit charger depuis les ressources le QM qui correspond à la langue système. Je mets ceci dans main :
    // pour avoir l'appli localisée
QTranslator appTranslator;
appTranslator.load ("dicodor_" + QLocale::system ().name (), ":/i18n/");
app.installTranslator (&appTranslator);
qui ressemble comme un frère aux commandes précédentes.

Tout est prêt pour fonctionner côté structure du projet.
Il me manque maintenant les TS et c'est un utilitaire qui va s'en charger
Dans ces TS seront collectées toutes les chaînes littérales de mon code, à savoir celles en dur, encadrées par des guillemets.
Mon boulot c'est de les encadrer avec la fonction QObject::tr (..... pour que l'utilitaire les repère
exemple : si j'écris
setWindowTitle ("Ma fenêtre");
Le titre de la fenêtre ne sera pas traduit. Il faut que j'écrive
setWindowTitle (tr ("Ma fenêtre"));
et faire ainsi pour toutes les chaînes littérales de mon code.

--> Attention : tr ne peut pas fonctionner sur des variables ! il ne reconnaît que les chaînes entre guillemets !
--> Oui mais si je veux faire apparaître des variables, comme dans ma boîte de dialogue du début ?

Facile, on va utiliser la fonction arg () de QString, que tr comprend parfaitement :
int dejaCopies = 10;
int total = 100;
QString affichage = tr ("%1 fichiers copiés sur %2").arg (dejaCopies).arg (total);
Vous voyez l'astuce ? le TS contiendra la chaîne à traduire "%1 fichiers copiés sur %2".
Mon copain traducteur va indiquer (on verra comment plus bas) qu'en anglais cette chaîne doit être remplacée par
"%1/%2 files copied"
et le tour est joué.

Je résume : après les modifs de main et du fichier PRO, je dois juste penser à utiliser tr ("....."), éventuellement avec arg(), pour les chaînes.

Bon, je développe, j'écris du code, et vient le moment de voir si le mécanisme fonctionne.

1/ récupérer les chaînes traduisibles dans les TS.
l'utilitaire qui fait ça est livré avec Qt et s'appelle lupdate.
On peut le lancer en ligne de commande
--> depuis le répertoire du projet, lancer lupdate *.pro et il fait tout le boulot.
Depuis la version xxx ? de Qt Creator, lupdate se lance sans sortir de l'IDE, par
--> Outils > Externe > Linguiste > Mettre à jour les traductions.
Après cette commande, je regarde dans i18n : les 3 TS sont là !

2/ Ouvrir les TS et traduire :
L'outil livré par Qt est linguist. Il suffit de double-cliquer sur un TS pour l'ouvrir avec linguist.

linguist est une appli à part entière et permet de faire plein de choses. Je me bornerai pour ce soir à mettre sous le texte français ma traduction en anglais.
Pas besoin de doc, j'ouvre le TS avec linguist,
je remarque en passant que TOUTES LES CHAÎNES saisies dans Qt Designer sont là...
je sélectionne la chaîne "%1 fichiers copiés sur %2"
j'écris dans le champ "English translation" le texte suivant %1/%2 files copied
j'enregistre
et je quitte.
Il m'a modifié le TS en mettant de l'anglais en face du français.

3/ compiler les TS en QM
l'outil est lrelease. Soit en ligne de commande soit depuis Qt Creator
--> Outils > Externe > Linguiste > Publier les traductions
les QM apparaissent dans le même répertoire que les TS
Je les intègre une fois pour toutes dans ma ressource, et c'est terminé.


Notes

** lorsque je voudrai mettre à jour les trads je refais le cycle 1/2/3 ci-dessus.

** pour tester le mécanisme sans devoir passer l'OS dans une autre langue vous pouvez modifier le TS français (fr) et mettre ce que vous voulez à la place des libellés existants.

Réponses

  • Soyez indulgents j'ai écrit ça très vite et je reviendrai dessus. Si un ou des points ne sont pas clairs faites moi signe.
    Ce sont vraiment las bases, il manque la façon d'implémenter un menu pour changer la langue de l'appli en cours de route par exemple. J'y reviendrai aussi. ;)
  • Une précision sur la gestion du pluriel par tr () :

    Une boîte d'alerte indiquant la fin d'une opération ressemble généralement à ceci
        QMessageBox::information (this, 
    tr ("Opération terminée"),
    tr ("%1 fichier(s) effacé(s)").arg (count));
    en fonction de count, ceci affiche (en français)
    10 fichier(s) effacé(s)
    0 fichier(s) effacé(s)
    et son équivalent en anglais, ce qui n'est pas très esthétique.
    De plus l'anglais a une règle différente du pluriel, on écrit
    0 files deleted // seul 1 n'impose pas le pluriel
    1 file deleted
    2 files deleted

    le 3è paramètre du tr() nous permet de gérer cela élégamment. Il nous suffit de coder
    tr ("%1 fichier(s) effacé(s)", 0, count);
    et linguist nous proposera de renseigner 2 traductions : le singulier et le pluriel. Il sera capable d'appliquer tout seul les règles de chaque langue
    dans le TS français, on saisit
    singulier : %1 fichier effacé
    pluriel : %1 fichiers effacés

    et dans le TS anglais
    singulier : %1 file deleted
    pluriel : %1 files deleted

    Ensuite, c'est Qt qui gère en fonction de count. Magique, plus de parenthèses disgracieuses dans le libellé, plus de tests sur le nombre pour savoir si count > 1 ou pas, etc...
Connectez-vous ou Inscrivez-vous pour répondre.