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++Builder Discussion :

Projet multi-langue sous C++ Builder, message interne en ressource (String Tables) [Interface]


Sujet :

C++Builder

  1. #1
    Membre à l'essai
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2011
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Juillet 2011
    Messages : 20
    Points : 20
    Points
    20
    Par défaut Projet multi-langue sous C++ Builder, message interne en ressource (String Tables)
    Bonjour à tous,

    Je viens de démarrer un projet en C++ sous Embarcadero® C++Builder® XE Version 15.0.3953.35171 (La dernière version de Borland C++ Builder en somme), et je suis confronter à un problème tout simple, que tout le monde à déjà dus rencontrer : Je cherche à faire un projet multi-langue, Français & Anglais.

    Alors ajouter une nouvelle langue au projet et assez simple : un coup d’aide en ligne et on trouve la réponse, idem pour exécuter l’app en Français ou en Anglais.

    Là ou ça ce complique, c’est que C++Builder, via la gestion des langues (Menu, projet, langues) ne prend en compte que les labels et les textes des boîtes de dialogues.

    Par conséquent, tous les messages internes (par ex. Application->MessageBox(L"Sauvegarde des paramètres",L"Information :", MB_OK); ) ne sont pas pris en compte dans le fichier de ressources de langue généré (*._DRC.rc).

    Je cherche donc un moyen de rajouter une ressource de type « string tables » (comme je pourrais le faire en .NET), afin d’y adjoindre mes textes (ici, Sauvegarde des paramètres, Information).

    De cette manière je pourrais remplacer mes textes par quelque chose du genre LoadString(XXX).

    Ensuite je cherche un moyen de lire cette ressource en fonction de la langue dans laquelle je lance mon application...

    Si je démarre mon application en Français, je lis la colonne Français de ma ressource en fonction de l’ID de ressource recherché.
    Si je démarre mon application en Anglais, je lis la colonne Anglais de ma ressource en fonction de l’ID de ressource recherché.

    Cela me parais tellement évident que je ne comprends pas pourquoi cela n’existe pas simplement dans la gestion des langues d’un projet...
    Je pense donc que je dois rater un truc qui doit être vraiment très gros...

    Si par hasard vous avez un Tuto, un exemple à transmettre je suis preneur!

    Je vous remercie par avance pour votre aide.

  2. #2
    Expert éminent sénior
    Avatar de ShaiLeTroll
    Homme Profil pro
    Développeur C++\Delphi
    Inscrit en
    Juillet 2006
    Messages
    13 567
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 43
    Localisation : France, Seine Saint Denis (Île de France)

    Informations professionnelles :
    Activité : Développeur C++\Delphi
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2006
    Messages : 13 567
    Points : 25 184
    Points
    25 184
    Par défaut
    Je ne connais pas le module intégré de Delphi, je l'ai essayé une fois (en D5, il y 10 ans), il était pénible au possible !
    Mais semble que cela ne soit toujours pas un truc fun !

    Pour les ressources, la classe String fourni LoadStr, LoadString, LoadResString, LoadResourceString doit être ce que tu recherche, cela utilise l'API LoadString qui nécessite un identifiant numérique !
    En Delphi, facile, c'est le mot clé resourcestring, je ne le connais pas en C++
    avec l'API FindResource(...RT_STRING), tu peux retrouver l'identifiant numérique via le nom de la ressource

    Pour la gestion des Langues, il me semble que cela utilise une DLL, en fonction du pays lors de l'installation du programme, tu fournis telle ou telle DLL, les ressources DFM et STRING seront chargé par LoadResource et LoadString ... j'ai un vieux souvenir de cela, mon tuteur d'apprentissage à l'époque avait mis dans une DLL, les Images, les Ressources ainsi que tous les BPL dans une DLL (et cela utilisais le BPL de la DLL dans l'Exe, à l'époque, je n'avais pas le niveau pour comprendre, et je n'ai jamais cherché à le reproduire)


    Dans le sujet Localisation d'une application (Delphi 2009) , j'expliquais diverses méthodes "a la main" !

  3. #3
    Membre à l'essai
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2011
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Juillet 2011
    Messages : 20
    Points : 20
    Points
    20
    Par défaut
    @ShaiLeTroll:
    Décidément tu es mon sauveur en Borland C++ Builder! Merci beaucoup pour ton aide précieuse.

    Pour la gestion des dll de langue, tout est fait par l’IDE :
    Quand tu passes ton projet en multilangue (via le menu, projet, langues), il créer automatiquement un projet de dll, pour les différentes langues sélectionnées. Il ne reste plus qu’à traduire les différents textes dans c’est projets (en double cliquant sur le .dfm du projet dll de langue concerné).

    Ensuite pour lancer ton application dans les différentes langues il suffit d’avoir dans le répertoire de sortie les dll de langue (par ex. dans mon cas avec un formulaire TestContexte: TestContexte.ENG & TestContexte.FRA, pour l’Anglais et le Français), et de modifier c’est clés dans la base de registre :

    [HKEY_CURRENT_USER\Software\Embarcadero\Locales]
    "D:\\Mes documents\\RAD Studio\\Projets\\GestCtrlCumul\\TestContexte\\Debug\\TestContexte.exe"="ENG" | "FRA"

    [HKEY_LOCAL_MACHINE\SOFTWARE\Embarcadero\Locales]
    "D:\\Mes documents\\RAD Studio\\Projets\\GestCtrlCumul\\TestContexte\\Debug\\TestContexte.exe"="ENG" | "FRA"

    En rouge le chemin vers ton exe.

    Malheureusement, dans ce projet DLL de langue seul les textes des formulaires sont pris en compte. D’où mon problème, pour les messages d’erreur, qui ne sont pas pris en compte…

    Il ne reste comme solution que de passer par une ressource de type StringTable, qui normalement gère les langues… Les StringTable, je connais ça sous Visual C++, VB, et dans le monde .NET.

    Dans cette ressource StringTable Tu as en colonne la langue, en ligne un ID de chaine, et en cellule associer la traduction dans les différentes langues.

    Pour accéder à cette ressource, on utilise bien un LoadResString + l’ID de la chaine que l’on souhaite lire…

    Malheureusement je n’arrive pas à trouver comment rajouter une ressource de Type StringTable sous Borland… Il ne prend que des images, des icônes, des curseurs (via le menu, projet, ressources et images…).

    Alors je suis perplexe. Et bien entendu pas moyen de trouver un exemple dans l’aide ou sur la toile…

    Par contre vus que tu as l’aire de connaitre un peut, est-ce que par hasard tu aurais un exemple à me transmettre, car bien entendu dans l’aide seule sont donné la définition des fonctions…

    Merci d’avance pour ton aide, encore une nouvelle fois.

  4. #4
    Membre chevronné
    Avatar de DjmSoftware
    Homme Profil pro
    Responsable de compte
    Inscrit en
    Mars 2002
    Messages
    1 044
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Suisse

    Informations professionnelles :
    Activité : Responsable de compte
    Secteur : High Tech - Opérateur de télécommunications

    Informations forums :
    Inscription : Mars 2002
    Messages : 1 044
    Points : 2 187
    Points
    2 187
    Billets dans le blog
    1
    Par défaut
    Salut
    Delphi et C++ Builder ne dispose pas d'un outil permettant de créer des fichiers de ressources, par contre il est livré un compilateur de ressource
    BRCC32.exe
    pour créer des fichies RC contenant des stringTable tu peux t'inspirer de l'exemple suivant
    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
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
     
    // déclaration d'un fichier Include
    #ifndef RessourceH
    #define RessourceH
     
    #define IDS_English             1000
    #define IDS_SelectD_Display     1001
    #define IDS_YES                 1002
    #define IDS_NO                  1003
    #define IDS_Maybe               1004
     
    #define IDS_French              2000
    #define IDS_SelectD_Moniteur    2001
    #define IDS_Oui                 2002
    #define IDS_Non                 2003
    #define IDS_Petre               2004
     
    #endif
     
    // définition d'un fichier RC (Type Texte)
    #include "Ressource.h"
     
     
    STRINGTABLE
    {
     
    IDS_English             L"English"
    IDS_SelectD_Display     L"Display selected"
    IDS_YES                 L"Yes"
    IDS_NO                  L"No"
    IDS_Maybe               L"Maybe"
     
     
    IDS_French              L"Français"
    IDS_SelectD_Moniteur    L"Moniteur Sélectionné"
    IDS_Oui                 L"Oui"
    IDS_Non                 L"Non"
    IDS_Petre               L"Peut-être"
    }
     
    // CI-dessous une petite app de Test
    //le .h
    //---------------------------------------------------------------------------
     
    #ifndef Unit61H
    #define Unit61H
    //---------------------------------------------------------------------------
    #include <Classes.hpp>
    #include <Controls.hpp>
    #include <StdCtrls.hpp>
    #include <Forms.hpp>
    #include "Ressource.h"
    #include <ExtCtrls.hpp>
    //---------------------------------------------------------------------------
    class TForm61 : public TForm
    {
    __published:	// Composants gérés par l'EDI
    	TRadioGroup *LangGrp;
    	TListBox *Lb;
    	void __fastcall FormDestroy(TObject *Sender);
    	void __fastcall LangGrpClick(TObject *Sender);
    private:	// Déclarations utilisateur
    	TStringList* ResList;
    	bool __fastcall GetResourceStrings(int Nbr);
    	void  __fastcall FillList();
     
    public:		// Déclarations utilisateur
    	__fastcall TForm61(TComponent* Owner);
     
    };
    //---------------------------------------------------------------------------
    extern PACKAGE TForm61 *Form61;
    //---------------------------------------------------------------------------
    #endif
     
    // le .cpp
    //---------------------------------------------------------------------------
     
    #include <vcl.h>
    #pragma hdrstop
     
    #include "Unit61.h"
    //---------------------------------------------------------------------------
    #pragma package(smart_init)
    #pragma resource "*.dfm"
    TForm61 *Form61;
    //---------------------------------------------------------------------------
    __fastcall TForm61::TForm61(TComponent* Owner)
    	: TForm(Owner)
    {
      ResList = new TStringList();
      if(GetResourceStrings(5))
    	FillList();
     
    }
    //---------------------------------------------------------------------------
    bool __fastcall TForm61::GetResourceStrings(int Nbr)
    {
       ResList->Clear();
       char Buffer[255];
       int  Base= (LangGrp->ItemIndex+1)*1000;
       bool retValue=false;
       for (int i = 0; i < Nbr; i++) {
    	  retValue=(LoadString(HInstance,Base+i,Buffer,255)!=0);
    	  ResList->Add(Buffer);
    	}
       return  retValue;
     
    }
    //---------------------------------------------------------------------------
    void __fastcall TForm61::FormDestroy(TObject *Sender)
    {
       delete  ResList;
    }
    //---------------------------------------------------------------------------
    void  __fastcall TForm61::FillList(){
     
     LangGrp->Caption=ResList->Strings[0];
     Lb->Items->Clear();
     for (int i = 1; i < 5; i++) {
       Lb->Items->Add(ResList->Strings[i]);
     }
     
    //---------------------------------------------------------------------------
     
    }
    void __fastcall TForm61::LangGrpClick(TObject *Sender)
    {
       if(GetResourceStrings(5))
    	FillList();
    }
    //---------------------------------------------------------------------------
    // le .dfm
    object Form61: TForm61
      Left = 0
      Top = 0
      Caption = 'Form61'
      ClientHeight = 175
      ClientWidth = 635
      Color = clBtnFace
      Font.Charset = DEFAULT_CHARSET
      Font.Color = clWindowText
      Font.Height = -11
      Font.Name = 'Tahoma'
      Font.Style = []
      OldCreateOrder = False
      OnDestroy = FormDestroy
      PixelsPerInch = 96
      TextHeight = 13
      object LangGrp: TRadioGroup
        Left = 32
        Top = 24
        Width = 169
        Height = 105
        Caption = 'Language'
        ItemIndex = 0
        Items.Strings = (
          'English'
          'Fran'#231'ais')
        TabOrder = 0
        OnClick = LangGrpClick
      end
      object Lb: TListBox
        Left = 288
        Top = 24
        Width = 201
        Height = 97
        ItemHeight = 13
        TabOrder = 1
      end
    end

    cordialement

  5. #5
    Membre à l'essai
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Juillet 2011
    Messages
    20
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur .NET

    Informations forums :
    Inscription : Juillet 2011
    Messages : 20
    Points : 20
    Points
    20
    Par défaut
    Merci DjmSoftware pour ta réponse, et pour les exemples qu’elle contient.

    Je viens de tester tout ça et le résultat correspond à ce que je cherchais.
    Super, tu m’enlèves une grosse épine du pied!

    Encore merci pour ton aide

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

Discussions similaires

  1. Réponses: 0
    Dernier message: 01/04/2015, 17h36
  2. Moteur de recherche interne sur site dynamique et multi-langues
    Par lucimed dans le forum Développement Web en Java
    Réponses: 4
    Dernier message: 30/06/2008, 11h34
  3. Multi langues et multi projets Netbeans
    Par genamiga dans le forum NetBeans
    Réponses: 4
    Dernier message: 10/06/2008, 20h42
  4. Projet Multi Langue
    Par MAGNUM_HEAD dans le forum VC++ .NET
    Réponses: 4
    Dernier message: 19/07/2006, 14h28
  5. Programme international avec IHM multi-langues
    Par calogerogigante dans le forum API standards et tierces
    Réponses: 6
    Dernier message: 26/04/2006, 00h49

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