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

C++ Discussion :

gettext et locale


Sujet :

C++

  1. #1
    Membre averti Avatar de Flo.
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2002
    Messages : 379
    Points : 404
    Points
    404
    Par défaut gettext et locale
    Bonjour,

    J'essaie de comprendre comme utiliser gettext avec ce code là dans un fichier "main.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
    #include <iostream>
    #include <string>
    #include <libintl.h>
    #include <locale.h>
     
    void main()
    {
    #if 1
    	char const * const catalog = "fr_FR";
    	char const * const locale = "french_France.1252";
    #else
    	char const * const catalog = "es_ES";
    	char const * const locale = "Spanish_Spain.1252";
    #endif
     
    	char const * const a = setlocale(LC_ALL, locale);
    	char const * const b = textdomain(catalog);	
    	char const * const c = bindtextdomain(catalog, "i18n");
    	char const * const d = bind_textdomain_codeset(catalog, "UTF-8");
    	std::string const e = gettext("hello");
    	std::cout << e << std::endl;
    	std::cin.get();
    }
    Au même niveau que mon fichier "main.cpp", j'ai les fichiers suivants
    • i18n\es_ES\LC_MESSAGES\es_ES.po
    • i18n\es_ES\LC_MESSAGES\es_ES.mo
    • i18n\fr_FR\LC_MESSAGES\fr_FR.po
    • i18n\fr_FR\LC_MESSAGES\fr_FR.mo


    En espagnol, "Hello" est traduit par "Hola".
    En français, "Hello" est traduit par "Bonjour".

    Mon système d'exploitation est Windows XP en version française.

    Évidement, en français cela marche mais pas quand j'essaye en espagnol. En espagnol, la fonction "setlocale" me renvoie bien "Spanish_Spain.1252". Mais le texte "hello" reste "hello".

    Comment dois-je modifier mon code pour que cela fonctionne ? Ca me rend un peu fou cette histoire .

    Je suppose que l'on doit pouvoir changer la locale de l'application par n'importe quelle locale, non ?

    Merci

    Flo.

  2. #2
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Salut,

    Avec un code proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    #if 1
    	char const * const catalog = "fr_FR";
    	char const * const locale = "french_France.1252";
    #else
    	char const * const catalog = "es_ES";
    	char const * const locale = "Spanish_Spain.1252";
    #endif
    ce n'est pas vraiment étonnant

    Ce code dit au compilateur : si 1 est vrai, tu gardes les eeux premières lignes (celles qui parlent francais), sinon tu gardes les deux dernières lignes (celles qui parlent l'espagnol).

    Et, comme 1 est toujours vrai, bah, tu n'auras jamais que les deux premières lignes.

    Sinon, l'idée de base, c'est que tu créeras tous les messages que tu veux afficher en anglais, en les faisant passer par la "machinerie" de gettext.

    En ne me basant que sur ton code, cela donnerait quelque chose comme (attention, adapté, non testé
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    #include <iostream>
    #include <string>
    #include <libintl.h>
    #include <locale.h>
     int main(){
        setlocale( LC_ALL, "" );
        textdomain("TonApplication");
        bindtextdomain("TonApplication", "i18n");
        bind_textdomain_codeset("TonApplication", "UTF-8");
        std::cout<<gettext("hello world!");
        return 0;
    }
    Une fois que c'est fait, tu extrait les chaines qu'il faut traduire avec xgettext sous la forme de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    xgettext -d TonApplication -s -o main.pot main.cpp
    Cette commande te créera un fichier (main.)pot (portable object template) qui est un modèle que tu pourras utiliser pour tes traductions.

    La troisième étape est d'obtenir "une copie de travail" du fichier pot afin d'effectuer les traductions.

    Tu peux assez facilement copier le fichier main.pot en main.po, mais, l'idéal est d'utiliser msginit, sous une forme proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    msginit -l <locale à utiliser pour la traduction> -o <nom du fichier po à créer > -i <fichier.pot d'origine>
    Si tu veux, par exemple, permettre la traduction en francais et en espagnol, tu créeras les fichiers po grace aux deux commandes (une pour le francais, l'autre pour l'espagnole)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    msginit -l fr_FR -o main_fr.po -i main.pot
    msginit -l es_ES -o main_es.po -i main.pot
    La première commande t'aura créé le fichier main_fr.po et la seconde le fichier main_es.po, qui prendront tous les deux une forme proche de
    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
      # <nom du projet> translations for PACKAGE package.
      # Copyright (C) 2004 THE PACKAGE'S COPYRIGHT HOLDER
      # This file is distributed under the same license as the PACKAGE package.
      # <ton nom> <ton e-mail> <annee>.
      #
      msgid ""
      msgstr ""
      "Project-Id-Version: PACKAGE VERSION\n"
      "Report-Msgid-Bugs-To: \n"
      "POT-Creation-Date:<date et heure>\n"
      "PO-Revision-Date: <date et heure \n"
      "Last-Translator: <toi> <ton e-mail>\n"
      "Language-Team: <nom dui projet>\n"
      "MIME-Version: 1.0\n"
      "Content-Type: text/plain; charset=UTF-8\n"
      "Content-Transfer-Encoding: 8bit\n"
     
      #: hello.c:10
      msgid "Hello, world!\n"
      msgstr ""
    La quatrième étape consiste à modifier les chaines de caratère msgstr afin de traduire les chaines telles qu'elles sont indiquées par les chaines msgid.

    Il ne te restera plus qu'à créer le fichier objet (qui contient les chaines au format binaire adéquat) avec la commande
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    msgfmt -c -v -o main.mo main_fr.po
    et à copier le fichier main.mo dans le dossier adéquat pour que la magie fonctionne

    Si, par la suite, tu rajoutes des chaines de caractères qui doivent être traduites, tu regénère un nouveau fichier pot et tu peux les rajouter aux fichiers déjà générés avec msmerge, grace à une commande proche de
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    msgmerge -s -U main_fr.po nouveau_fichier.pot
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  3. #3
    Membre averti Avatar de Flo.
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2002
    Messages : 379
    Points : 404
    Points
    404
    Par défaut
    Merci pour la réponse.

    Désolé pour le "1" c'est juste que j'ai du recopier le code après avoir remplacé le "0" par un "1". Bref c'est un copié-foiré et ça n'est pas le problème: avec un "0" ça marche pas non plus.

    Merci pour les informations.

    Bon ...

    Je mets déjà en œuvre tout ce que tu décris. Merci encore pour le détail.

    Ma question porte plus sur la façon (si possible) de procéder pour changer de catalogue. Je ne parviens qu'à utiliser gettext avec la langue (français) définie sur l'ordinateur. Par exemple, en français mon code fonctionne mais pas en espagnol.

    Désolé de ne pas avoir été plus clair et de t'avoir fait répondre à côté.

    Flo.

  4. #4
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par Flo. Voir le message
    Ma question porte plus sur la façon (si possible) de procéder pour changer de catalogue. Je ne parviens qu'à utiliser gettext avec la langue (français) définie sur l'ordinateur. Par exemple, en français mon code fonctionne mais pas en espagnol.
    En fait, tu n'auras la traduction que si le système utilise la locale indiquée.

    Tu ne pourras donc voir que les messages qui correspondent à ta locale particulière. Si tu veux voir les messages correspondant à une autre langue, il faut "permuter" le système pour qu'il fonctionne avec cette autre langue
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  5. #5
    Membre averti Avatar de Flo.
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2002
    Messages : 379
    Points : 404
    Points
    404
    Par défaut
    Ok merci c'est la réponse que j'attendais.

    Je reprends ta réponse pour vérifier que j'ai bien compris.

    Si je veux passer mon application en espagnol, il faut que Windows soit en espagnol. C'est bien ça ? Ça me paraît gros quand même !

    Flo.

  6. #6
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    Citation Envoyé par Flo. Voir le message
    Ok merci c'est la réponse que j'attendais.

    Je reprends ta réponse pour vérifier que j'ai bien compris.

    Si je veux passer mon application en espagnol, il faut que Windows soit en espagnol. C'est bien ça ?
    Oui, du moins, c'est ce qu'il me semble
    Ça me paraît gros quand même !
    Ben à moins que les messages soient en espagnol à l'origine, je ne vois pas pourquoi cela te parait gros

    L'idée est que les messages soient adaptés à la langue de l'utilisateur, donc, si l'ordinateur a le choix entre la langue de l'utilisateur et une autre, il choisira celle de l'utilisateur.

    Qu'est ce qui te parait gros là dedans
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  7. #7
    Membre averti Avatar de Flo.
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2002
    Messages : 379
    Points : 404
    Points
    404
    Par défaut
    D'accord.

    Ce qui me semble curieux, c'est que l'on ne puisse pas décorréler, avec gettext, la langue d'une application et la langue de l'OS.

    C'est intéressant quand même qu'un italien (technicien de maintenance par exemple d'une société italienne) puisse passer l'interface d'une application en italien sur un ordinateur espagnol (l'ordinateur de son client espagnol par exemple) où cette même application apparaît naturellement en espagnol.

    Enfin bon, merci pour tout ton aide.

    Je clos le sujet.

    Flo.

  8. #8
    Expert éminent sénior
    Avatar de koala01
    Homme Profil pro
    aucun
    Inscrit en
    Octobre 2004
    Messages
    11 614
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 52
    Localisation : Belgique

    Informations professionnelles :
    Activité : aucun

    Informations forums :
    Inscription : Octobre 2004
    Messages : 11 614
    Points : 30 626
    Points
    30 626
    Par défaut
    En fait, il y a parfois moyen...

    Mais cela dépend du système et de l'application en elle-même : il faut, pour y arriver, que l'application permette de choisir la langue au niveau des différents réglages / paramètres utilisés par l'application.

    Je sais qu'il y a moyen avec Qt et son linguist, mais je ne suis pas persuadé qu'il y ait moyen de faire pareil avec gettext (il faudrait que je me renseigne, tiens, sur le sujet).

    Note que, à bien y réfléchir, je ne vois pas trop pourquoi il n'y aurait pas moyen de le faire
    A méditer: La solution la plus simple est toujours la moins compliquée
    Ce qui se conçoit bien s'énonce clairement, et les mots pour le dire vous viennent aisément. Nicolas Boileau
    Compiler Gcc sous windows avec MinGW
    Coder efficacement en C++ : dans les bacs le 17 février 2014
    mon tout nouveau blog

  9. #9
    Rédacteur/Modérateur


    Homme Profil pro
    Network game programmer
    Inscrit en
    Juin 2010
    Messages
    7 115
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 36
    Localisation : Canada

    Informations professionnelles :
    Activité : Network game programmer

    Informations forums :
    Inscription : Juin 2010
    Messages : 7 115
    Points : 32 967
    Points
    32 967
    Billets dans le blog
    4
    Par défaut
    Bonsoir,

    il n'y a rien de choquant, locale sert justement à s'adapter à la langue du système. Mais aussi à tout ce qui est heure, décallage horaire, format de date, ...
    Dans la plupart des applications (pour ne pas dire toutes ?), locale est uniquement utilisé à des fins d'initialisation de la config, mais la langue de l'appli n'est ni plus ni moins qu'un paramètre de la config. Et donc modifiable à souhait.
    Pensez à consulter la FAQ ou les cours et tutoriels de la section C++.
    Un peu de programmation réseau ?
    Aucune aide via MP ne sera dispensée. Merci d'utiliser les forums prévus à cet effet.

  10. #10
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par Flo. Voir le message
    Ce qui me semble curieux, c'est que l'on ne puisse pas décorréler, avec gettext, la langue d'une application et la langue de l'OS.
    Vu l'origine de gettext, ça m’étonne beaucoup. Sous Linux, j'ai aucun problème avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    #include <iostream>
    #include <string>
    #include <libintl.h>
    #include <locale.h>
     
    int main(int argc, char**argv){
        setlocale( LC_MESSAGES, argv[1] );
        textdomain("localisation");
        bindtextdomain("localisation", "i18n");
        bind_textdomain_codeset("localisation", "UTF-8");
        std::cout<<gettext("hello world!")<< '\n';
        return 0;
    }
    à avoir la langue que j'ai passée en argument.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     
    $ ./a.out fr_FR.utf8
    Salut le monde!
    $ ./a.out en_US.utf8
    Hi world!
    $ ./a.out en_UK.utf8
    hello world!
    Je pencherais plutôt vers un problème dans le choix des noms des locales -- je ne connais rien aux conventions de Windows, et il n'est pas improbable que gettext utilise celle de Unix même sous Windows -- ou la position ou le nom des fichiers. (i18n/fr/LC_MESSAGES/localisation.mo et i18n/en/LC_MESSAGES/localisation.mo pour moi)
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

  11. #11
    Membre averti Avatar de Flo.
    Homme Profil pro
    Inscrit en
    Mai 2002
    Messages
    379
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations forums :
    Inscription : Mai 2002
    Messages : 379
    Points : 404
    Points
    404
    Par défaut
    Merci Jean-Marc.Bourguet,

    J'ai repris ton code. Sous msvc2008, l'exécution crash au niveau du setlocale dans locale.h:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
        /* Validate category */
        _VALIDATE_RETURN(LC_MIN <= _category && _category <= LC_MAX, EINVAL, NULL);
    Les catégories que je peux spécifier doivent être comprises, semble-t-il, entre LC_MIN et LC_MAX lesquels sont définis ainsi:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    #define LC_ALL          0
    #define LC_COLLATE      1
    #define LC_CTYPE        2
    #define LC_MONETARY     3
    #define LC_NUMERIC      4
    #define LC_TIME         5
     
    #define LC_MIN          LC_ALL
    #define LC_MAX          LC_TIME
    LC_MESSAGES n'est pas défini dans locale.h comme les précédents mais dans libintl.h par le code suivant:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    /* The LC_MESSAGES locale category is the category used by the functions
       gettext() and dgettext().  It is specified in POSIX, but not in ANSI C.
       On systems that don't define it, use an arbitrary value instead.
       On Solaris, <locale.h> defines __LOCALE_H (or _LOCALE_H in Solaris 2.5)
       then includes <libintl.h> (i.e. this file!) and then only defines
       LC_MESSAGES.  To avoid a redefinition warning, don't define LC_MESSAGES
       in this case.  */
    #if !defined LC_MESSAGES && !(defined __LOCALE_H || (defined _LOCALE_H && defined __sun))
    # define LC_MESSAGES 1729
    #endif
    J'ai remplacé LC_MESSAGES par LC_ALL.

    Le code fonctionne donc en français seulement. D'ailleurs, quelque soit la locale que j'essaye de mettre, il me retourne le texte en français. Voici mon code :

    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
    #include <iostream>
    #include <string>
    #include <libintl.h>
    #include <locale.h>
     
    int main(int argc, char**argv)
    {
        std::cout << argv[1] << '\n';
        setlocale( LC_ALL, argv[1] );
        textdomain("localisation");
        bindtextdomain("localisation", "i18n");
        bind_textdomain_codeset("localisation", "UTF-8");
        std::cout<<gettext("hello")<< '\n'; 
        std::cin.get();
        return 0;
    }
    Et d'ailleurs, en espagnol, italien (autre chose que de l'anglais et du français), ton code fonctionne-t-il toujours ?

    Merci

    Flo.

  12. #12
    Expert éminent

    Inscrit en
    Novembre 2005
    Messages
    5 145
    Détails du profil
    Informations forums :
    Inscription : Novembre 2005
    Messages : 5 145
    Points : 6 911
    Points
    6 911
    Par défaut
    Citation Envoyé par Flo. Voir le message
    Et d'ailleurs, en espagnol, italien (autre chose que de l'anglais et du français), ton code fonctionne-t-il toujours ?
    Oui.
    Les MP ne sont pas là pour les questions techniques, les forums sont là pour ça.

Discussions similaires

  1. Réponses: 1
    Dernier message: 24/03/2015, 19h47
  2. gettext I18n et locale
    Par zevince dans le forum Langage
    Réponses: 0
    Dernier message: 16/11/2011, 22h08
  3. Réponses: 0
    Dernier message: 14/12/2010, 17h12
  4. gettext : No translation file found for domain using custom locale folder
    Par martin-damien dans le forum Général Python
    Réponses: 4
    Dernier message: 02/10/2010, 09h52
  5. Internationalisation, gettext et std::local
    Par 3DArchi dans le forum C++
    Réponses: 8
    Dernier message: 30/07/2008, 01h26

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