Tutoriel MSEide


Une application en plusieurs langues avec MSEi18n

Mon application

Mon application s’inspire de l’exemple qui se trouve dans le dossier <msedir>/apps/i18ndemo.

Création de l’application dans MSEide

L’application comporte un composant de type tstringdisp, et trois boutons qui serviront à changer la langue.

type
  tmainfo = class(tmainform)
    sd_weather: tstringdisp;
    bt_english: tbutton;
    bt_german: tbutton;
    bt_french: tbutton;

Propriétés des composants

Dans l’inspecteur d’objet, j’attribue une valeur à la propriété frame.caption du composant sd_weather.

Inspecteur d’objet

J’assigne également une valeur à la propriété text du même composant.

Inspecteur d’objet

J’ai également renseigné la propriété caption de la fiche principale.

Inspecteur d’objet

L’unité msei18nutils

Dans main.pas j’ajoute la référence à l’unité msei18nutils.

implementation

uses
  main_mfm,
  msei18nutils;

Une chaîne de type resourcestring

Je déclare une chaîne de caractères de type resourcestring.

uses
  main_mfm,
  msei18nutils;

resourcestring
  rs_goodbye = 'Good bye!';

Je compile mon application. Le compilateur m’informe qu’il crée un fichier main.rsj.

Writing Resource String Table file: main.rsj

Par curiosité, j’ouvre ce fichier, qui se trouve dans le même dossier que les unités compilées.

{"version":1,"strings":[
{"hash":90624273,"name":"main.rs_goodbye","sourcebytes":[71,111,111,100,32,98,121,101,33],"value":"Good bye!"}
]}

Tout semble correct. Il est temps d’ouvrir l’application MSEi18n.

MSEi18n

L’application MSEi18n se trouve dans le dossier <msedir>/tools/i18n/. Elle est également disponible dans le dépôt codeberg.org/rchastain/msei18n.

Configuration de MSEi18n

Après avoir compilé MSEi18n, je l’ouvre, et dans le menu Settings je clique sur l’élément de menu Configure MSEi18n.

MSEi18n Configure

Les champs MSEDIR et COMPILER doivent être renseignés.

Dans MSEDIR, j’indique le chemin du dossier de MSEgui, terminé par un / (ici /home/roland/Applications/mseide-463-dev/), car les autres macros sont construites par simple concaténation, par exemple ${MSEDIR}lib/common/. Dans COMPILER, j’indique le compilateur Free Pascal (ici ppcx64 ; fpc convient aussi).

Création d’un projet de traduction

Je crée un nouveau projet de traduction (un fichier TRP) en cliquant sur l’élément de menu New.

MSEi18n New

Après avoir choisi l’emplacement et le nom de mon projet, je clique sur OK.

Édition du projet

Je vais maintenant éditer mon projet de traduction. Pour cela, je clique sur l’élément de menu Edit.

Je clique dans la colonne File, afin de créer une nouvelle ligne dans la grille, et j’ajoute dans cette ligne le fichier main.mfm. Dans la colonne Kind, je sélectionne rfk_module.

Comme j’utilise dans mon application une chaîne de type resourcestring, je vais ajouter une deuxième ligne. Pour cela, je clique avec le bouton droit de la souris sur la première ligne, et je choisis, dans le menu qui s’affiche, Append Row.

Dans la colonne File, j’indique main.rsj. Dans la colonne Kind, je sélectionne rfk_resstrings.

Je remplis également les colonnes Language et Directory (une ligne pour l’allemand, une ligne pour le français).

MSEi18n Edit

Traduction des chaînes

Je ferme la fenêtre en cliquant sur OK. Je peux maintenant traduire, d’une part les chaînes contenues dans mon fichier MFM, d’autre part la chaîne de type resourcestring contenue dans le fichier RSJ.

MSEi18n

Vous noterez que j’ai coché les options flat et string only, afin de n’avoir sous les yeux que les données qui m’intéressent.

Sauvegarde du projet

Une fois le travail de traduction achevé, je sauvegarde mon projet en cliquant sur l’élément de menu Save.

Compilation

Avant de compiler le projet, je crée les dossiers devant contenir les modules, en fonction de ce que j’avais indiqué en éditant le projet.

mkdir -p de
mkdir -p fr

Je peux maintenant compiler le projet en cliquant sur Make. Une fenêtre s’ouvre, me permettant de vérifier que la compilation des modules par Free Pascal s’est bien passée.

MSEi18n Make

Voici le contenu du dossier du projet après la compilation.

projet
├── de
│   ├── demo_de.pas
│   ├── libdemo_de.so
│   ├── main.mfm
│   ├── main_mfm.pas
│   ├── main.rsj
│   └── main_rst.pas
├── demo
├── demo.pas
├── demo.prj
├── demo.trd
├── demo.trp
├── fr
│   ├── demo_fr.pas
│   ├── libdemo_fr.so
│   ├── main.mfm
│   ├── main_mfm.pas
│   ├── main.rsj
│   └── main_rst.pas
├── libdemo_de.so
├── libdemo_fr.so
├── main.mfm
├── main_mfm.pas
├── main.pas
├── Makefile
├── MakefileWin
└── out
    ├── main.rsj
    └── … (unités compilées)

Il est temps de terminer mon application. Je rouvre donc (si je l’avais fermé) mon projet demo.prj dans MSEide.

Changer la langue de l’application

La fonction loadlangunit

Je crée une méthode pour l’événement onexecute du bouton bt_german.

Dans le corps de cette méthode, j’utilise la fonction loadlangunit pour changer la langue, avec comme paramètre le nom de base du module.

procedure tmainfo.onexecute_bt_german(const sender: TObject);
begin
  loadlangunit('demo_de');
end;

Le nom du module est formé du nom du projet (demo), d’un tiret bas et de la langue indiquée dans la colonne Language (de).

Sous Linux, loadlangunit('demo_de') cherche la bibliothèque libdemo_de.so d’abord dans les dossiers de bibliothèques habituels du système, puis dans le dossier de l’exécutable ; sous Windows, elle cherche demo_de.dll. C’est pourquoi MSEi18n copie les bibliothèques dans le dossier du projet après la compilation : voilà pourquoi libdemo_de.so et libdemo_fr.so apparaissent deux fois dans l’arborescence ci-dessus.

Je fais la même chose pour le français.

procedure tmainfo.onexecute_bt_french(const sender: TObject);
begin
  loadlangunit('demo_fr');
end;

Pour remettre l’application en anglais (la langue des chaînes de caractères contenues dans le fichier MFM), je n’aurai qu’à appeler la fonction loadlangunit avec une chaîne vide comme argument.

procedure tmainfo.onexecute_bt_english(const sender: TObject);
begin
  loadlangunit('');
end;

La fonction utf8tostring

Il me reste à faire quelque chose de ma chaîne rs_goodbye de type resourcestring. Je voudrais que mon application dise au revoir à l’utilisateur, dans la dernière langue sélectionnée, lorsque celui-ci fermera la fenêtre.

J’ajoute donc une méthode pour l’événement onclosequery de la classe tmainfo.

procedure tmainfo.onclosequery_mainfo(const sender: tcustommseform; var amodalresult: modalresultty);
begin
end;

Dans le corps de cette méthode, j’utilise la fonction utf8tostring pour obtenir la traduction de la chaîne rs_goodbye.

En effet, un resourcestring est un AnsiString codé en UTF-8, alors que MSEgui travaille avec des chaînes Unicode (le type msestring de MSEgui correspond à unicodestring). La fonction utf8tostring de Free Pascal effectue la conversion, afin que les caractères spéciaux comme ä ou é s’affichent correctement. C’est pourquoi je déclare la variable s de type unicodestring.

procedure tmainfo.onclosequery_mainfo(const sender: tcustommseform; var amodalresult: modalresultty);
var
  s: unicodestring;
begin
  s := utf8tostring(rs_goodbye);
  showmessage(s);
end;

C’est tout ! Je n’ai plus qu’à compiler et qu’à essayer mon application.

Au revoir

Si vous le souhaitez, vous pouvez télécharger le code source du projet.