La locale.library
Un article de GuruMed.
Internationalisation des programmes avec CatComp
Par DaddyDav
La localisation, voilà un élément de notre système qui fait la fierté de tout Amigaïste. Ce procédé permet de gérer les différents langages au coeur même du système grâce à la locale.library qui fut intégrée à partir de AmigaOS 2.1.
Mais comment ça marche ?
On va ici comprendre comment créer les différents fichiers pour "localiser" un programme.
Tout d'abord il faut se procurer CATCOMP présent dans le NDK3.1 (CD Developer) ou plus simplement dans le NDK3.9 accessible en ligne (regardez dans le répertoire Tool). On peut le faire avec d'autres outils disponibles sur l'Aminet mais je voulais commencer par le début. Et CatComp est l'outil original de Commodore !
Placez CatComp dans le répertoire C: (mais bon ça vous le saviez) et le cas échéant lisez la doc. Maintenant on peut commencer.
Quels sont les fichiers nécessaires pour faire de la localisation en C et pour un programme TOTO ? On en compte quatre :
- TOTO.cd : Il est la base de tout, c'est par celui-ci que tout commence. On l'appelle le fichier de description.
- TOTO.ct : Il est presque identique au TOTO.cd à cela près qu'il contient la traduction des lignes de texte et qu'il permettra de générer les catalogues dans les différentes langues.
- TOTO.catalog : Il permet de stocker les différentes lignes de texte d'un langage mais ici sous forme binaire. Il en existe un différent pour chaque langage et ils sont stockés sous PROGDIR:Catalogs/Français/ ou sous Locale:Catalogs/Français/
- TOTO.h : Il sert à inclure dans notre source les lignes de texte de notre fichier de description, chaque chaîne de caractères de base se retrouvera dans l'exécutable.
Créons le fichier TOTO.cd :
;exemple de fichier de description en anglais ;TOTO.cd MSG_INIT (0/5/20) Catalog ; MSG_TXT_1 (1/10/30) I am the first sentence ; MSG_TXT_2 (+1//) I am the second ; MSG_TXT_3 (//) I am after the %d and before the %s sentence\n ; MSG_TXT_4 (//) I am the %s\n ; MSG_TXT_5 (//) last ;
Voyons voir ce que l'on trouve dans ce fichier :
- ";" : le point virgule permet de mettre en commentaire et est obligatoire devant une nouvelle entrée.
- "MSG_TXT_1" : ce titre indique tout simplement la constante qui sera utilisée dans notre TOTO.h et TOTO.c pour cette ligne de texte.
- "(1/10/20)" "(+1//)" "(//)" : ce qui se trouve entre parenthèses correspond à : (ID de la ligne de texte / Nb minimum de caractères / Nb maximum de caractères).
Dans le premier cas on détermine tous les paramètres. Dans le deuxième on incrémente seulement le premier par rapport au précédant et les autres sont ignorés. Dans le dernier tous sont ignorés car facultatifs.
- "%d" "%s" : CATCOMP supporte des commandes de formatage compatibles avec la commande printf().
Nous pouvons valider le fichier de description grâce à CATCOMP. Dans le Shell allez dans le répertoire et lancez "CATCOMP TOTO.cd". Il nous signalera les défauts de notre fichier ou le validera.
Maintenant créons le fichier include TOTO.h pour notre source. Au même endroit que précédemment tapez :
CATCOMP NOARRAY NOBLOCK NOCODE TOTO.cd CFILE TOTO.h
Les options :
- CFILE x.h : indique que nous voulons créer un include pour le langage C que l'on ommera x.h
- NOARRAY : interdit l'édition de la section CATCOMP_ARRAY
- NOBLOCK : interdit l'édition de la section CATCOMP_BLOCK
- NOCODE : interdit l'édition de la section CATCOMP_CODE
Chaque section représente une manière d'exprimer les chaînes de caractères. Nous ne nous servirons dans notre exemple que de la section de base qui utilise des #define.
Voici le résultat :
#ifndef TOTO_H
#define TOTO_H
/****************************************************************/
/* This file was created automatically by CatComp.
* Do NOT edit by hand!
*/
#ifndef EXEC_TYPES_H
#include <exec/types.h>
#endif
#ifdef CATCOMP_ARRAY
#undef CATCOMP_NUMBERS
#undef CATCOMP_STRINGS
#define CATCOMP_NUMBERS
#define CATCOMP_STRINGS
#endif
#ifdef CATCOMP_BLOCK
#undef CATCOMP_STRINGS
#define CATCOMP_STRINGS
#endif
/****************************************************************/
#ifdef CATCOMP_NUMBERS
#define MSG_INIT 0
#define MSG_TXT_1 1
#define MSG_TXT_2 3
#define MSG_TXT_3 4
#define MSG_TXT_4 5
#define MSG_TXT_5 6
#endif /* CATCOMP_NUMBERS */
/****************************************************************/
#ifdef CATCOMP_STRINGS
#define MSG_INIT_STR "Catalog"
#define MSG_TXT_1_STR "I am the first sentence"
#define MSG_TXT_2_STR "I am the second"
#define MSG_TXT_3_STR "I am after the %d and before the %d sentence\n"
#define MSG_TXT_4_STR "I am the %s\n"
#define MSG_TXT_5_STR "last"
#endif /* CATCOMP_STRINGS */
/****************************************************************/
struct LocaleInfo
{
APTR li_LocaleBase;
APTR li_Catalog;
};
#endif /* TOTO_H */
On aura besoin que de ce qui se trouve dans les sections CATCOMP_NUMBERS et CATCOMP_STRINGS.
Nous pouvons désormais écrire le programme principal : TOTO.c
/* Programme de test de localisation pour GURUMED
** TOTO.c
** vc TOTO.c -o TOTO <- compilation par VBCC
** gcc TOTO.c -o TOTO <- compilation par GCC
*/
#include <stdio.h>
#include <amiga-align.h> /* <- alignement dans le cas d'une version MOS */
#include <proto/exec.h>
#include <proto/locale.h>
#include <default-align.h> /* <- fin d'alignement dans le cas d'une version MOS
*/
#include <string.h>
/* C'est ici que nous décidons d'inclure les parties */
/* nécessaire du fichier TOTO.h */
#define CATCOMP_NUMBERS
#define CATCOMP_STRINGS
/* Ici nous incluons le Fichier TOTO.h */
#include "TOTO.h"
/* Initialisation de variables pour utilisation de la locale.library */
struct LocaleBase *LocaleBase=NULL;
struct Catalog *catalog=NULL;
/* On entre dans le vif du sujet */
int main(void){
/* On ouvre la locale.library et on teste si elle est bien ouverte */
if((LocaleBase=(struct LocaleBase *)OpenLibrary("locale.library",39))){
/* On ouvre le catalogue. S'il n'existe pas ou que notre langue n'est pas présente
OpenCatalog() retournera "NULL" */
catalog=OpenCatalogA(NULL,"TOTO.catalog",NULL);
/* Puis on affiche les différentes phrases */
/* On indique si le catalogue est trouvé (dans mon exemple il n'existe que le
catalogue français) */
printf("%s :
%s\n",GetCatalogStr(catalog,MSG_INIT,MSG_INIT_STR),catalog?"OUI":"NO");
printf("%s\n",GetCatalogStr(catalog,MSG_TXT_1,MSG_TXT_1_STR));
printf("%s\n",GetCatalogStr(catalog,MSG_TXT_2,MSG_TXT_2_STR));
/* Dans ce cas on utilise les commande de formatage de la ligne du catalogue */
printf(GetCatalogStr(catalog,MSG_TXT_3,MSG_TXT_3_STR),2,GetCatalogStr(catalog,MS
G_TXT_5,MSG_TXT_5_STR));
/* Dans celui ci on utilise le Formatage de la première tout en intégrant la deuxième */
printf(GetCatalogStr(catalog,MSG_TXT_4,MSG_TXT_4_STR),GetCatalogStr(catalog,MSG
_TXT_5,MSG_TXT_5_STR));
/* si le catalogue a été ouvert, on le referme */
if(catalog) CloseCatalog(catalog);
/* On ferme la locale.library */
CloseLibrary((struct Library *)LocaleBase);
}
/* On quitte */
return 0;
}
Comment avons-nous fait pour trouver toutes nos lignes de caractères dans le catalogue ?
Il faut commencer par procéder à l'ouverture du catalogue :
catalog=OpenCatalogA(NULL,"TOTO.catalog",NULL);
- Le premier paramètre -NULL- indique à OpenCatalog() que vous vouliez utiliser le système de locale par défaut. Si par exemple le système est réglé par défaut pour le langage "deutsch", OpenCatalog() va tenter d'ouvrir "TOTO.catalog" ici :
PROGDIR:Catalogs/deutsch/TOTO.catalog
Et si jamais il ne le trouvait pas il ira essayer ici :
LOCALE:Catalogs/deutsch/TOTO.catalog
S'il ne le trouvait pas encore il retournerait "NULL".
- Le deuxième vous l'auvez compris correspond au nom du catalogue à ouvrir.
- Le troisième correspond au pointeur d'un tableau de TAG à passer en argument, dans notre exemple il vaut "NULL".
Dans ce cas de figure, nous indiquons implicitement que notre programme à été programmé avec des lignes de textes par défaut en anglais le fameux "built-in". Si nous voulions utiliser des lignes par défaut en français il faudrait ouvrir le catalogue comme ceci :
catalog = OpenCatalog(NULL, "TOTO.catalog", OC_BuiltInLanguage, "français", TAG_DONE);
D'autres tags sont possible mais faudrait lire plus en avant les autodocs.
Ce qui nous intéresse vraiment, l'extraction des lignes de texte traduites, se présente ainsi :
GetCatalogStr(catalog,MSG_INIT,MSG_INIT_STR)
- Le premier argument désigne le pointeur du catalogue que l'on a essayé d'ouvrir tout à l'heure. S'il est "NULL" GetCatalogStr() renverra automatiquement la ligne de texte par défaut MSG_INIT_STR qui correspond à "Catalog".
- Le deuxième argument correspond à la constante représentant le numéro de la ligne de texte dans le catalogue, ici MSG_INIT qui correspond à "Catalogue".
- Le troisième argument correspond à la constante où est stockée la ligne de texte par défaut, ici MSG_INIT_STR qui correspond à "Catalog".
Donc rien de bien compliqué en somme. Nous pouvons passer maintenant à la création du fameux catalogue.
Créons dans un premier temps le fichier TOTO.ct. La commande CATCOMP va nous mâcher le travail en créant le squelette du fichier TOTO.ct que nous allons remplir :
CATCOMP TOTO.cd CTFILE TOTO.ct
Ce qui, une fois les chaînes en français saisies aux endroits vides, nous donne ceci :
;exemple de fichier de translation en français ;TOTO.ct ; ## version $VER: TOTO.catalog 0.0 (17.09.03) ## codeset 0 ## language français ; MSG_INIT Catalogue ;Catalog ; MSG_TXT_1 Je suis la première phrase ;I am the first sentence ; MSG_TXT_2 Je suis la seconde ;I am the second ; MSG_TXT_3 Je suis après la %d et avant la %s phrase\n ;I am after the %d and before the %s sentence\n ; MSG_TXT_4 Je suis la %s\n ;I am the %s\n ; MSG_TXT_5 dernière ;last ;
- ";" : Comme pour le fichier TOTO.cd le ";" correspond à des commentaires et il reste obligatoire devant une nouvelle entrée.
- "##" : correspond lui à une commande pour la création du catalogue.
Le reste est la même chose que le fichier TOTO.cd sauf que l'on ne remet pas les (//).
Enfin passons à la création du dit catalogue. Il faut au préalable créer les répertoires catalogs et français pour pouvoir sauver notre catalogue français :
CATCOMP TOTO.cd TOTO.ct CATALOG catalogs/français/TOTO.catalog
Voila, il n'y a plus qu'à compiler notre source TOTO.c et exécuter TOTO pour voir si tout cela marche bien. Pour forcer le programme à ne pas trouver le catalogue il suffit de renommer le répertoire "catalogs" en autre chose pour avoir nos lignes de textes en anglais.
Pour information, il existe différents programme, sur aminet, facilitant la localisation tel que Dorkalise (qui génère des hits), ReCatIt, FlexCat, etc. J'espère que cet article vous aura ouvert les yeux sur le fonctionnement de la locale.library et vous donnera envie d'aller plus loin dans ce domaine.
