Garder les traductions avec cx_Freeze

Jean-Paul Vidal

Vous avez fait un joli programme en PyQt4 qui utilise un QMessageBox du genre “Voulez-vous vraiment quitter ?” avec les boutons Oui/Non. Mais ces boutons persistent à vous dire “Yes/No”.

Même si tout le monde comprend, c'est irritant et ça donne une impression “pas fini” à votre application.

Commentez : Commentez

- Titre : Garder les traductions avec cx_Freeze

- Auteur : Jean-Paul Vidal

- Parution : 25 février 2011

- Licence : Copyright ® 2011 Jean-Paul Vidal. 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'à trois ans de prison et jusqu'à 300 000 € de dommages et intérêts.

Sommaire

- I. Solution pour l'interpréteur "normal"

- II. Solution pour un exécutable cx_Freeze (ou équivalent)

- III. Remerciements

I - Solution pour l'interpréteur "normal"

La solution est la suivante : il faut dire à PyQt4 qu'il doit traduire, mais il faut aussi lui dire où il doit trouver les fichiers de traduction selon la locale du PC.

Voilà le code à insérer, ce qui donnera pour le code de démarrage standard :

from PyQt4 import QtCore, QtGui
# ...
# ...ici la classe Fenetre
# ...
if __name__ == "__main__":

# lancement de l'application
app = QtGui.QApplication(sys.argv)

#========================================================================
# pour assurer la traduction automatique du conversationnel à la locale
locale = QtCore.QLocale.system().name()
translator = QtCore.QTranslator ()
translator.load(QtCore.QString("qt_") + locale,
QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.TranslationsPath))
app.installTranslator(translator)

#========================================================================
# lancement de la fenetre
fen = Fenetre()
fen.show()
sys.exit(app.exec_())

II - Solution pour un exécutable cx_Freeze (ou équivalent)

Vous avez fait ce qui précède, et vous essayez de faire une version autonome de votre programme grâce à cx_Freeze, transportée dans un Windows ou Linux sans PyQt4. Et là, ça ne marche plus !

Pourquoi ? Parce que l'exécutable ne trouve plus les fichiers de traduction de la locale. Et s'il ne les trouve pas, c'est qu'il les cherche au mauvais endroit.

L'exécutable après cx_Freeze cherche les fichiers de traduction :

- sous Windows, ici: C:\Qt\4.7.1\translations (bizarre, parce qu'avec l'interpréteur, c'est: C:\Python27\Lib\Site-packages\PyQt4\translations) ;

- sous Linux (Ubuntu 10.10), ici: /usr/share/qt4/translations.

La solution est dès lors évidente :

- pendant le traitement par cx_Freeze, il faut copier le contenu du répertoire cherché dans un sous-répertoire “translations”. Cela peut se faire automatiquement en utilisant l'option “include_files” ;

- il faut tester si on est avec l'interpréteur normal ou avec un exécutable fabriqué avec cx_Freeze. On peut faire ça en testant si le programme qu'on vient de lancer a une extension '.py' ou '.pyw' ;

- il ne reste plus qu'à donner le bon chemin des fichiers de traduction à “translator.load”

Voilà le code que ça donne.

Pour le setup.py de cx_Freeze (tenir compte des éventuelles autres copies à faire par l'option “include_files”) :

if sys.platform == "linux2":
options["include_files"] = [("/usr/share/qt4/translations","translations")]
elif sys.platform == "win32":
options["include_files"] = [(r"C:\Python27\Lib\site-packages\PyQt4\translations","translations")]
else:
# mettre ici la solution pour les autres OS
pass

Et pour le code de démarrage de l'application :

from PyQt4 import QtCore, QtGui
# ...
# ...ici la classe Fenetre
# ...
if __name__ == "__main__":

# lancement de l'application
app = QtGui.QApplication(sys.argv)

#========================================================================
# pour assurer la traduction automatique du conversationnel à la locale
locale = QtCore.QLocale.system().name()
translator = QtCore.QTranslator ()
if os.path.splitext(sys.argv[0])[1] in ['.py', '.pyw']:
# exécution par l'interpréteur normal
reptrad = unicode(QtCore.QLibraryInfo.location(QtCore.QLibraryInfo.TranslationsPath))
else:
# exécution de la version exécutable après cx_Freeze (ou équivalent):
#les fichiers de traduction doivent se trouver dans "translations"
reptrad = unicode("translations")
translator.load(QtCore.QString("qt_") + locale, reptrad)
app.installTranslator(translator)

#========================================================================
# lancement de la fenetre
fen = Fenetre()
fen.show()
sys.exit(app.exec_())

Et là, ça marche dans tous les cas.

Pour la version Windows traitée par cx_Freeze, ça continue à fonctionner avec le programme d'installation InnoSetup (qui va vraiment très bien avec cx_Freeze !).

À noter que je ne me suis pas contenté de la traduction en français : c'est la “locale” du PC qui sera utilisée !

III - Remerciements

Merci à dourouc05 et à ClaudeLELOUP pour leur relecture !