IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Qt Discussion :

Problème de visibilité avec tr()/QTranslator/qApp


Sujet :

Qt

  1. #1
    Candidat au Club
    Inscrit en
    Juillet 2009
    Messages
    3
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 3
    Points : 2
    Points
    2
    Par défaut Problème de visibilité avec tr()/QTranslator/qApp
    Bonjour,

    Je développe actuellement une application multi-langues avec Qt (enfin j'essaye). Pour ce faire, j'ai crée une classe LanguageChooser qui affiche une checkbox par fichier de traduction trouvé (*.ts). Pour gérer la modification de la langue, j'utilise qApp->installTranslator(&translator). Une fois cette définition de langue effectuée, j'instancie une nouvelle fenêtre (QWidget) qui se voit belle et bien traduite dans la langue demandée. Cette fenêtre est composée de deux boutons : "Installer" et "Quitter". Lors de l'appui sur "Installer", une QMessageBox s'ouvre (toujours dans la langue demandée), et une nouvelle fenêtre est chargée (toujours QWidget).

    Et c'est là qu'arrive mon problème ! Pas moyen de charger cette fenêtre dans la langue choisie (les tr() ne me renvoie pas les valeurs traduites) !

    J'ai essayé à peu près toutes les syntaxes que je connaissais pour tr (avec arg, sauvergarder les valeurs avant le show() de la fenêtre, ...)

    Je sais que qApp est global, donc une fois la langue installée il n'est pas censé l'appliquer à toutes les fenêtres ? Si oui, pourquoi une seule alors ?

    Merci d'avance pour vos réponses

  2. #2
    Inactif  


    Homme Profil pro
    Inscrit en
    Novembre 2008
    Messages
    5 288
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 48
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Secteur : Santé

    Informations forums :
    Inscription : Novembre 2008
    Messages : 5 288
    Points : 15 620
    Points
    15 620
    Par défaut
    Bonjour toto4242 et bienvenue sur le forum

    Un peu de code pour nous aider ?

    Sinon, regarde un peu dans les différents tutoriels :
    - http://qt-quarterly.developpez.com/q...-chef-suedois/
    - http://qt-quarterly.developpez.com/q...-chef-suedois/
    - http://qt.nokia.com/developer/qtquar...ic-translation (en cours de traduction)
    - http://qt-quarterly.developpez.com/q...l-traductions/

  3. #3
    Candidat au Club
    Inscrit en
    Juillet 2009
    Messages
    3
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 3
    Points : 2
    Points
    2
    Par défaut
    J'avais déjà regardé les liens que tu m'as envoyé

    main.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
     
    int                 main(int argc, char* argv[])
    {
        QApplication    app(argc, argv);
        app.setStyle("plastique");
     
        LanguageChooser chooser;
        chooser.show();
     
        return (app.exec());
    }
    languagechooser.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
     
    LanguageChooser::LanguageChooser(QWidget *parent) : QDialog(parent, Qt::WindowSystemMenuHint | Qt::WindowTitleHint)
    {    
    Création des checkbox par fichier de traduction trouvés...
    }
     
    void            LanguageChooser::checkBoxToggled()
    {
        QCheckBox*     checkBox    =   qobject_cast<QCheckBox *>(sender());
        FenPrincipale*   window      =   mainWindowForCheckBoxMap[checkBox];
     
        if (!window)
        {
            QTranslator translator;
            translator.load(qmFileForCheckBoxMap[checkBox]);
            qApp->installTranslator(&translator);
            window = new FenPrincipale;
            mainWindowForCheckBoxMap.insert(checkBox, window);
        }
        window->setVisible(checkBox->isChecked());
        this->setShown(false);
    }
    FenPrincipale.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
     
    FenPrincipale::FenPrinciale()
    {
    ...
    initTrad();
    }
     
    void    FenChoix::initTrad()
    {//Champs private pour les traductions initialisés
        msgBoxTitle = tr("2RP V7 - Installation");
        msgBoxText = tr("L'installation de 2RP va commencer.\nVeuillez fermer toutes les applications"
                        "et documents ouverts.\n\nAppuyez sur le bouton pour poursuivre l'installation.");
    }
     
    void FenChoix::on_pushButton_install_clicked()
    {
        this->close();
     
        QMessageBox::information(this, msgBoxTitle, msgBoxText);
     
        FenInstall *fenetre_install = new FenInstall();// Creation de la fenetre suivante
        fenetre_install->show();                            // Affichage de la fenetre suivante
    }
    FenInstall.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
     
    FenInstall::FenInstall(QWidget *parent) : QWidget(parent)
    {
        setupUi(this);
     
        QMessageBox msgBox;
        msgBox.setWindowTitle(tr("Phrase traduite"));
        msgBox.setText(tr("Une autre phrase traduite"));
        msgBox.exec();
    }
    L'explication du code se trouve normalement dans mon premier post, mais pour revenir sur l'erreur, la mesageBox dans FenInstall ne m'affiche pas la phrase traduite du fichier de langue choisie.

    Si besoin, je posterais le code complet mais je me suis dit que ce serait que peut être un peu lourd (c'est déjà par forcément très léger là ...).

    Merci d'avance

  4. #4
    Candidat au Club
    Inscrit en
    Juillet 2009
    Messages
    3
    Détails du profil
    Informations forums :
    Inscription : Juillet 2009
    Messages : 3
    Points : 2
    Points
    2
    Par défaut Résolution
    Bonjour,

    Je repasse pour poster ma solution au cas où ça intéresserait quelqu'un.

    Tout d'abord, les composants :
    • main.cpp
    • translatedMessages.h
    • LanguageChooser.cpp/.h
    • Fenêtre exemple.cpp/.h


    main.cpp : le code expliquera mieux que moi
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include <QApplication>
    #include "LanguageChooser.h"
     
    int                 main(int argc, char* argv[])
    {
        QApplication    app(argc, argv);
        app.setStyle("plastique");
     
        LanguageChooser chooser;// Appel de l'interface de sélection de langage
        chooser.show();
     
        return (app.exec());
    }
    translatedMessage.h : ce fichier contient une simple structure avec toutes les string allant stocker les traductions de tous les messages du projet

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    #ifndef TRANSLATEDMSG_H
    #define TRANSLATEDMSG_H
     
    #include <QString>
     
    struct  translatedMsg
    {
        /*FenChoix*/
        QString     FenChoixUn;
        QString     FenChoixDeux;
     
        /*FenInstall*/
        QString     FenInstallUn;
        QString     FenInstallDeux;
    };
     
    #endif // TRANSLATEDMSG_H
    Ensuite le LanguageChooser : petite interface composée de CheckBox associées chacune à une langue. Une fois la checkbox de la langue voulue cochée, l'interface se ferme et appelle la "première" fenêtre de votre projet.
    Pour info, la liste des langues est fabriquée à partir des .qm trouvés dans le dossier d'exécution du priojet. Une balise message dans chaque .ts a été rajouté manuellement pour indiquer la langue en clair dans l'interface :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    <context>
        <name>LanguageChooser</name>
        <message>
            <location filename="../../LanguageChooser.cpp" line="137"/>
            <source>Language</source>
            <translation>English</translation>
        </message>
    </context>
    LanguageChooser.h :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    #ifndef LANGUAGECHOOSER_H
    #define LANGUAGECHOOSER_H
     
    #include <QDialog>
    #include <QMap>
    #include <QStringList>
    #include <QString>
    #include "translatedMsg.h"
     
    QT_BEGIN_NAMESPACE
    class   QAbstractButton;
    class   QCheckBox;
    class   QDialogButtonBox;
    class   QGroupBox;
    QT_END_NAMESPACE
    class   FenChoix; // Classe de la fenêtre à appeler une fois la langue choisie
     
    class   LanguageChooser : public QDialog
    {
        Q_OBJECT
     
        public:
            LanguageChooser(QWidget* parent = 0);
     
        protected:
            void        closeEvent(QCloseEvent* event);
     
        private slots:
            void        checkBoxToggled();
     
        private:
            void        setTranslatedMsg();
            QStringList findQmFiles();
            QString     languageName(const QString &qmFile);
     
            translatedMsg               s_msg;
            QGroupBox*                  groupBox;
            QDialogButtonBox*           buttonBox;
            QMap<QCheckBox*, QString>   qmFileForCheckBoxMap;
            QMap<QCheckBox*, FenChoix*> mainWindowForCheckBoxMap;
    };
     
    #endif
    LanguageChooser.cpp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    #include <QtGui>
    #include "languagechooser.h"
    #include "FenChoix.h"
    #include "translatedMsg.h"
     
    LanguageChooser::LanguageChooser(QWidget *parent) : QDialog(parent, Qt::WindowSystemMenuHint | Qt::WindowTitleHint)
    {    
        groupBox                        =   new QGroupBox("Languages");
        buttonBox                       =   new QDialogButtonBox;
        QGridLayout*    groupBoxLayout  =   new QGridLayout;
        QStringList     qmFiles         =   findQmFiles();
        QVBoxLayout*    mainLayout      =   new QVBoxLayout;
     
        if (qmFiles.size() == 0) //Si aucun fichier qm trouvé, une checkbox défault pour utiliser les valeurs en brut dans le code
        {
            QCheckBox* checkBox = new QCheckBox(QString("Default"));
            qmFileForCheckBoxMap.insert(checkBox, QString("Default"));
            connect(checkBox, SIGNAL(toggled(bool)), this, SLOT(checkBoxToggled()));
            groupBoxLayout->addWidget(checkBox, 0, 0);
        }
        for (int i = 0; i < qmFiles.size(); ++i)// Parcours de tous les fichiers, récupère la balise language ("English" par exemple), et ajoute une checkbox par nom dans l'interface
        {
            QCheckBox* checkBox = new QCheckBox(languageName(qmFiles[i]));
            qmFileForCheckBoxMap.insert(checkBox, qmFiles[i]);
            connect(checkBox, SIGNAL(toggled(bool)), this, SLOT(checkBoxToggled()));
            groupBoxLayout->addWidget(checkBox, i / 2, i % 2);
        }
        groupBox->setLayout(groupBoxLayout);
        mainLayout->addWidget(groupBox);
        mainLayout->addWidget(buttonBox);
        setLayout(mainLayout);
        setWindowTitle("Language selection");
    }
     
    void    LanguageChooser::closeEvent(QCloseEvent*)
    {//Un peu brutal je sais
        exit(0);
    }
     
    void            LanguageChooser::setTranslatedMsg()
    {// Liste de tous les messages pour toutes les fenêtres
        /*FenChoix*/
        s_msg.FenChoixUn                  =   tr("Coucou");
        s_msg.FenChoixDeux                       =   tr("tout le monde");
        /*FenInstall*/
        s_msg.FenInstallUn                   =   tr("Developpez.net");
        s_msg.FenInstallDeux              =   tr("ROX !");
    }
     
    void            LanguageChooser::checkBoxToggled()
    {//Appelé lors d'un clic sur checkbox, défini la langue du prog à celle de la checkbox, puis appelle la "première" fenêtre du projet (FenChoix ici)
        QCheckBox*  checkBox    =   qobject_cast<QCheckBox *>(sender());
        FenChoix*   window      =   mainWindowForCheckBoxMap[checkBox];
     
        if (!window)
        {
            QTranslator translator;// Défini la langue du prog
            translator.load(qmFileForCheckBoxMap[checkBox]);
            qApp->installTranslator(&translator);
     
            setTranslatedMsg();
     
            window = new FenChoix; //Création de la fenêtre suivante
            window->setTrad(&s_msg); //méthode à implémenter dans chaque classe 'fenêtre', envoie la structure des msgs intialisée
        }
        window->setVisible(checkBox->isChecked()); //Affiche la "première" fenêtre
        this->setShown(false); //Cache l'interface de langue
    }
     
    QStringList                     LanguageChooser::findQmFiles()
    {
        QDir                        dir("./");
        QStringList                 fileNames   =   dir.entryList(QStringList("2RP*.qm"), QDir::Files, QDir::Name);
        QMutableStringListIterator  i(fileNames);
     
        while (i.hasNext())
        {
            i.next();
            i.setValue(dir.filePath(i.value()));
        }
     
        return fileNames;
    }
     
    QString         LanguageChooser::languageName(const QString &qmFile)
    {
        QTranslator translator;
        translator.load(qmFile);
     
        // Cherche dans le fichier .qm, dans le context "LanguageChooser", le <message> de <source> "Language", et retourne sa <translation> (en l'occurence le langage en clair : English, Français, ...)
        return translator.translate("LanguageChooser", "Language");
    }
    Maintenant qu'on a sélectionné un langage, fermé notre interface de sélection et appelé la "première" interface, je vais vous montrer son code et les manipulations qui la font marcher ^_^

    FenChoix : 'tite interface qui contient un Label txt (Tu veux installer ?), un Label Image (soyons joli), deux boutons (Installer, Quitter)

    FenChoix.h :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    #ifndef HEADER_FENCHOIX
    #define HEADER_FENCHOIX
     
    #include <QtGui/QWidget>
    #include <QString>
    #include "ui_fenchoix.h"
    #include "FenInstall.h"// La prochaine fenêtre
    #include "translatedMsg.h"
     
    class   FenChoix : public QWidget, private Ui::Form_main
    {
        Q_OBJECT
     
        public:
            FenChoix(QWidget *parent = 0);              // Constructeur
     
            void    keyPressEvent(QKeyEvent* event);
            void    setTrad(translatedMsg* msgs);
     
        private:
            FenInstall*     fenetre_install; //Prochaine fenêtre
            translatedMsg*  s_msg;//Le pointeur sur la structure des msgs
     
        private slots:
            void on_pushButton_quitter_clicked();       // Signal clique sur quitter
            void on_pushButton_install_clicked();       // Signal clique sur installer
    };
     
    #endif // HEADER_FENCHOIX
    FenChoix.cpp :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    #include "FenChoix.h"
     
    // Constructeur
    FenChoix::FenChoix(QWidget *parent) : QWidget(parent)
    {
        setupUi(this);
     
        pushButton_install->setFocus();
    }
     
    void    FenChoix::setTrad(translatedMsg* msgs)
    {
        s_msg = msgs;
     
        label_install->setText(s_msg->FenChoixUn);
        pushButton_install->setText(s_msg->FenChoixUn);
        pushButton_quitter->setText(s_msg->FenChoixDeux);
    }
     
    void FenChoix::keyPressEvent(QKeyEvent* event)
    {
        if ((event->key() == Qt::Key_Enter || event->key() == Qt::Key_Return))
        {
            if (pushButton_install->hasFocus())
                on_pushButton_install_clicked();
            if (pushButton_quitter->hasFocus())
                on_pushButton_quitter_clicked();
        }
    }
     
    // Slot : Clique sur INSTALL
    void FenChoix::on_pushButton_install_clicked()
    {
        this->close();
     
        QMessageBox::information(this, PROJ_NAME, s_msg->FenChoixUn);
     
        fenetre_install = new FenInstall;     // Creation de la fenetre suivante
        fenetre_install->setTrad(s_msg);    // On lui passe le pointeur sur struct
        fenetre_install->show();                // Affichage de la fenetre
    }
     
    // Slot : Clique sur QUITTER
    void FenChoix::on_pushButton_quitter_clicked()
    {
        exit(0);
    }
    Bon voilà, je crois avoir fait le tour. Après il suffit de passer le pointeur sur struct dans une méthode setTrad() et puis le tour est joué. Je ne sais pas s'il y a plus simple et/ou optimisé, mais là tous les messages sont à un seul endroit ce qui fait que quand on modifie les interfaces (Ajout/Suppression de messages), il suffit d'ajouter ou virer une variable de la struct et de la méthode d'init et c'est tout. En plus tout est fait à l'init, après on se trimballe juste un pointeur donc 4 malheureux octets.
    Un point négatif c'est que le .ts généré ne contient qu'une partie avec tous les messages. Donc pas découpé par fenêtre.

    En espérant que ça aidera qqn

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème de visibilité avec un panel
    Par Sh0ck dans le forum Composants VCL
    Réponses: 7
    Dernier message: 20/01/2009, 09h42
  2. problème de requête avec jointures
    Par tinhat dans le forum Requêtes
    Réponses: 7
    Dernier message: 11/08/2003, 10h33
  3. Problème dans requête avec count()
    Par BadFox dans le forum Requêtes
    Réponses: 3
    Dernier message: 08/07/2003, 18h02
  4. [Kylix] problème compilation kylix3 avec redhat 9.0
    Par madininaoursa dans le forum EDI
    Réponses: 1
    Dernier message: 02/07/2003, 16h21
  5. Problèmes de versions avec Xalan, Xerces et Java
    Par honeyz dans le forum XML/XSL et SOAP
    Réponses: 4
    Dernier message: 05/06/2003, 10h18

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo