home *** CD-ROM | disk | FTP | other *** search
/ Freelog Special Edition 1: Linux / CD2.iso / docs / locale.fr < prev    next >
Text File  |  1999-03-14  |  46KB  |  1,160 lines

  1.                            MANUEL "Locale"
  2.  
  3.                 Ecrit par Patrick D'Cruze 
  4.                 (pdcruze@orac.iinet.com.au, pdcruze@li.org)   
  5.         
  6.                 avec l'aide de Mitchum Dsouza 
  7.             (m-dsouza@mrc-applied-psychologie.cambridge.ac.uk)
  8.  
  9. ---------------------------------------------------------------------------
  10.     Traduction Francaise : Eric DUMAS dumas@emi.u-bordeaux.fr
  11. ---------------------------------------------------------------------------
  12. Note du traducteur :
  13.  
  14.     Le texte original peut etre trouve sur ftp.sunsite.edu. 
  15.     La version francaise sera deposee sur ftp.sunsite.edu et sur 
  16. ftp.ibp.fr (/pub/linux/french/docs).
  17.  
  18.     La traduction de notes anglaises est un sport assez difficile, 
  19. surtout lorsqu'il s'agit d'un texte technique. Bien souvent, j'ai essaye de 
  20. traduire les termes techniques par leur equivalent en francais. J'ai conserve 
  21. les termes anglais lorsqu'il n'y avait pas d'equivalent.
  22.  
  23.     Le terme central de ce texte est "Local". Ce terme peut etre traduit
  24. par milieu. Toutefois, a de nombreuses occasions, je conserverai le terme 
  25. anglais pour des raisons de comprehension.
  26.  
  27.     Ce texte ne possede par d'accents. Une version accentuee sera 
  28. disponible sous peu, sous la forme d'un fichier postscript ou d'un fichier
  29. LaTeX.
  30.  
  31.     En esperant qu'il n'y ait pas trop d'erreurs.
  32.             
  33.                 Fevrier 1995, Bordeaux - France
  34.                     Eric DUMAS
  35.                         dumas@emi.u-bordeaux.fr
  36.  
  37. -------------------------------------------------------------------------
  38. Sommaire :
  39.     I       Une Introduction a "Locale" et aux catalogues.
  40.     I.1     Qu'est-ce que "Locale" ?
  41.     I.2     Qu'est-ce que sont les catalogues ?
  42.     I.3     Quel est le format d'un message du catalogue ?
  43.     II      Quelles sont les routines appelees ?
  44.     II.1    SetLocale().
  45.     II.2    CatOpen().
  46.     II.3    CatGets().
  47.     II.4    CatClose().
  48.     II.5    Xtract.
  49.     II.6    Gencat.
  50.     III     Ecrire des programmes avec "Locale".
  51.     III.1   Ecrire et modifier des programmes pour qu'ils puissent 
  52.             utiliser le catalogue des messages.
  53.     3.2     Ecrire des programmes qui doivent etre utilises sur des 
  54.          systemes se servant de "Locale" ou non.
  55.     IV      Ou sont stockes mes messages ?
  56.     V       Questions les plus frequemment posees. (F.A.Q.)
  57. -------------------------------------------------------------------------
  58.  
  59. I- Introduction a "Locale" et aux catalogues :
  60. ----------------------------------------------
  61.  
  62. I-1 : Qu'est-ce que "Locale" ?
  63.  
  64.     Il y a un bon nombre de parametres necessaires pour definir les
  65. conventions culturelles d'un pays. Ces attributs incluent la langage du
  66. pays, le format de la date et de l'heure, la representation des nombres, 
  67. les caracteres pour la monnaie, etc. Ces "regles" locales definissent les
  68. specification pour le milieu du pays. Le "Locale" represente la 
  69. connaissance necessaire pour supporter les specificitees d'un pays.
  70.  
  71.     Il y a cinq principales zones qui risquent differer entre les 
  72. pays et les zones de milieu.
  73.  
  74.     Caracteres et Codage des caracteres :
  75.     -------------------------------------
  76.     Le codage le plus repandu aux USA et dans la majorite des pays 
  77. anglo-saxons est le codage ASCII. Toutefois, il y a de nombreux caracteres 
  78. necessaires par divers pays qui ne sont pas fournis avec ce codage. Le 
  79. systeme de codage ISO 8859-1 (8 bits) possede la plupart des caracteres 
  80. necessaires pour gerer la plupart des langages europeens. Toutefois, dans 
  81. beaucoup de cas, la police de caracteres ISO-8859-1 n'est pas adequate. A 
  82. partir de la, chaque milieu aura besoin de specifier le type de codage des 
  83. caracteres dont il a besoin et devra avoir les routines de gestion de ces 
  84. caracteres pour pouvoir les utiliser.
  85.  
  86.     Monnaie :
  87.     --------
  88.     Les symboles utilises changent suivant les pays comme le fait la 
  89. position de ces symboles. Les programmes doivent etre capables d'afficher les
  90. chiffres monetaires dans leur forme exacte, suivant les differents pays.
  91.  
  92.     Dates :
  93.     -------
  94.     Le format varie suivant les milieux. Le jour de noel en 1994 s'ecrit
  95. 12/25/94 aux USA mais 25/12/94 en Australie et en France. Certains milieux 
  96. desirent la date sur 24 heures plutot que le format AM/PM.
  97.  
  98.     Nombres :
  99.     ---------
  100.     Les nombres peuvent etre representes de manieres differentes suivant 
  101. les milieux. Par exemple, les nombres suivants sont ecrits suivant plusieurs 
  102. formats, en fonction du milieu :
  103.  
  104.     12.345,67       Francais
  105.     12,345.67       Anglais/Americain
  106.     1,2345.67       Asiatique
  107.  
  108.     Messages :
  109.     ----------
  110.     L'application la plus evidente est sans nulle doute le support des
  111. messages en fonction du milieu. Un mecanisme facile a utiliser doit etre 
  112. fournis pour que les developeurs et les utilisateurs puissent selectionner la
  113. langue que le logiciel utilise. 
  114.  
  115.     Ce document ne se concentrera que sur le support des  messages pour 
  116. les programmes. Dans une prochaine etape, il sera mis a jour pour illustrer 
  117. la facilite avec laquelle les developeurs peuvent ajouter d'autres 
  118. specificites nationales. En plus, on peut preciser que les routines et 
  119. fonctions "Locales" sont utilisees la plupart du temps par des programmes en 
  120. mode texte, c'est a dire des programmes fonctionnant sur des xterm ou des 
  121. consoles virtuelles. D'autres routines existent pour des programmes utilisant 
  122. XWindows. Elles seront decrites lors d'une prochaine mise a jour de ce 
  123. document.
  124.  
  125.  
  126. I.2     Qu'est-ce que sont les catalogues ?
  127.  
  128.     Les programmes communiquent avec l'utilisateur en ecrivant des 
  129. messages (du texte) a l'ecran. Ces messages peuvent etre eparpilles dans tout
  130. le code source d'un progamme. Pour pouvoir supporter plusieurs langages, il
  131. est necessaire de traduire ces messages dans differentes langues. Cela est
  132. impossible a faire dans le code source pour deux raisons :
  133.     
  134.     1- Pour traduire les messages dans une autre langue, les traducteurs 
  135. devraient aller a la recherche des messages dans le code source. Cela 
  136. est une pure perte de temps. De plus, bon nombre de traducteurs risquent 
  137. de ne meme pas avoir acces au code source.
  138.  
  139.     2- Gerer une nouvelle langue signifie que les messages a l'interieur 
  140. du code source, doivent etre traduits, puis il faut recompiler le code source. 
  141. Ce qui devra etre fait pour tout langage.
  142.  
  143.     La solution est d'avoir tous les messages enregistres dans un fichier 
  144. externe, appelle catalogue des messages. A chaque fois que le programme a 
  145. besoin d'afficher un message, le programme demande au systeme d'exploitation
  146. de chercher le message approprie dans le catalogue et de l'afficher sur l'ecran.
  147.  
  148.     Les avantages sont les suivants :
  149.     - Le catalogue peut etre traduit sans qu'il soit necessaire d'avoir
  150.     acces au code source.
  151.     - Le code source est compile une et une seule fois. Pour gerer un 
  152.     nouveau langage, il suffit de traduire les messages et  de l'envoyer
  153.     a l'utilisateur.
  154.     - Tous les messages sont stockes en un seul endroit.
  155.  
  156.  
  157. I.3     Quel est le format d'un message du catalogue ?
  158.  
  159.     Une fois que tous les messages ont ete extraits du code source, ils
  160. sont ranges dans un fichier texte ordinaire qui est reference comme etant 
  161. le fichier des messages. Le fichier possede souvent la structure suivante :
  162.  
  163.     1       Impossible d'ouvrir le fichier foo.bar
  164.     2       Impossible d'ecrire dans le fichier foo.bar
  165.     3       Impossible d'acceder au repertoire
  166.  
  167.     Bien que cela soit une representation utile pour les programmeurs et 
  168. pour les traducteurs, cela se revele insuffisant pour le systeme 
  169. d'exploitaton. En effet, le systeme d'exploitation doit pouvoir y acceder 
  170. pour rechercher le message d'une maniere la plus rapide possible. Un fichier
  171. binaire correspond a cet etat d'esprit, et c'est ce qui est fait dans la 
  172. realite.
  173.  
  174.     Un catalogue de messages est une representation binaire des messages
  175. utilises dans le logiciel. Les fichiers textes de messages sont compiles
  176. en utilisant le programme "gencat" en un format binaire. Le catalogue ainsi
  177. compile dans un format depend de la machine et il n'est pas portable. Il est
  178. tres facile de recompiler les fichiers textes de messages sur d'autres 
  179. architectures (plateformes).
  180.     
  181.     Les programmeurs et les traducteurs ecrivent les messages utilises
  182. par leur programme dans des fichiers et ces fichiers sont compiles en un
  183. catalogue de messages. Toutefois, une seule partie d'un logiciel peut 
  184. contenir des centaines d'instructions printf(), chacune etant constituee
  185. d'un seul message. Chacun de ces messages devant etre stocke dans un fichier
  186. de messages. Il n'est pas tres raisonnable de supposer d'avoir tous ces 
  187. messages dans un seul fichier texte de messages. Editer, modifier, detruire 
  188. et ajouter de nouveaux messages risquent de faire grossir le fichier jusqu'a 
  189. ce que cela pose des problemes.
  190.  
  191.     La solution consiste a fractionner les messages en modules. Chacun de 
  192. ces modules contient les messages pour une partie specifique de 
  193. l'application. En combinant tous les modules, on obtient tous les messages 
  194. utilises. Ces modules peuvent etre compiles dans un seul catalogue de 
  195. messages. Le programme peut alors acceder a un message particulier situe 
  196. dans un module specifique a l'interieur du catalogue de messages.
  197.  
  198.     Cela rend le travail du programmeur (et du traducteur) plus facile. 
  199. Le programme peut assigner des modules separes pour des routines importantes.
  200. Alors, lorsqu'une routine est modifee, il suffit de modifier uniquement
  201. le module dans lequel se trouve le message correspondant. Tous les autres
  202. modules restent tels qu'il sont.
  203.  
  204.    Exemple :
  205.        Pour le programme gnubar, nous avons deux endroits qui utilisent les
  206. communications avec l'utilisateur (affichage d'erreurs et des resultats).
  207.  Les catalogues resultant sont normalement appelles : errors.m et results.m.
  208.  
  209.     (Rq :Nous avons adopte la convention d'utiliser .m pour une fichier de 
  210.         message)
  211.      
  212.     Toutes les messages d'erreur se trouvent dans errors.m. Nous modifions 
  213. alors le programme pour que lorsqu'une erreur se produit, le programme accede au
  214. module des messages d'erreurs et affiche le message d'erreur. De meme avec 
  215. les resultats.
  216.  
  217.     Ces deux fichiers sont alors compiles pour former le catalogue des 
  218. messages pour gnubar. Le fichier resultant de la compilation est appelle 
  219. gnubar.cat. Ce catalogue est constitue de deux modules, errors et results, 
  220. chacun contenant les messages numerotes.
  221.  
  222.     Pour acceder a un message particulier, le programme a besoin de 
  223. specifier quel module doit etre utilise et le numero du messsage qui doit etre 
  224. affiche.
  225.  
  226.  
  227.  
  228. II       Quelles sont les routines appellees ?
  229. ----------------------------------------------
  230.  
  231.     Les quatre routines centrales pour acceder et utiliser les catalogues
  232. de messages dans votre code source sont setlocale(), catopen(), catgets() et
  233. catclose().
  234.  
  235.     NB: Souvenez-vous que les Catalogues de Messages ne sont qu'un element 
  236. du milieu. Les autres elements seront traites dans les versions futures de ce 
  237. document. 
  238.  
  239.     NB pour LINUX : Pour acceder et utiliser les fonctions "locale", vous
  240. aurez besoin de libc.so.4.4.4c ou version ulterieure. (Je vous recommande
  241. d'utiliser au moins libc.so.4.5.26 ou superieur etant donne qu'elle inclue 
  242. de nombreuses ameliorations dans la gestion des milieux.). Vous aurez 
  243. egalement besoin des fichiers d'entete <locale.h> et <nl_types.h>. Si vous 
  244. avez une libc qui supporte les fonctions locales, alors il est fort 
  245. probable que vous possediez les fichiers d'entete egalement. (/usr/include)
  246.  
  247. II-1. SETLOCALE() :
  248.  
  249.     La premier chose qu'un programme doit faire est de positionner le milieu
  250. dans lequel il va s'executer. Cette operation est realisee avec la fonction
  251. setlocale(). Elle est definie comme etant :
  252.     #include <locale.h>
  253.  
  254.     char *setlocale(int categorie, const char *locale);
  255.  
  256.     L'argument "categorie" indique a la fonction quel attribut positionner.
  257. Les differents attributs sont :
  258.  
  259.     - LC_COLLATE    : Modifie le fonctionnement de strcoll() et strxfrm()
  260.     - LC_CTYPE      : Modifie le fonctionnement de la  gestion des caracteres
  261.                 isalpha(), islower(), isupper(), isprint(),...
  262.     - LC_MESSAGE    : Positionne la langue dans laquelle les messages seront
  263.                 affiches.
  264.     - LC_MONETARY   : Modifie les informations retournees par localeconv()
  265.     - LC_NUMERIC    : Positionne le caractere decimal pour les nombres
  266.     - LC_TIME       : Modifie le fonctionnement de strftime()
  267.     - LC_ALL        : Change tout !
  268.  
  269.     Dans notre exemple, nous allons nous occuper uniquement des catalogues de
  270. messages. C'est pourquoi nous allons uniquement positionner l'attribut 
  271. LC_MESSAGES avec la fonction setlocale(). L'attribut LC_ALL aurait egalement 
  272. pu etre utilise. Toutefois, il est bon d'utiliser uniquement les attributs 
  273. dont vous avez besoin dans votre programme. La raison sera expliquee 
  274. rapidement ulterieurement.
  275.  
  276. L'argument "locale" est le nom du milieu. Deux noms speciaux du milieux sont :
  277.     C       Cela rend les prototypes des fonctions standard a la norme du C... 
  278.     POSIX   idem, mais pour la norme POSIX.
  279.  
  280.     Generalement, l'argument du milieu sera : "" (guillemets vides). Cela 
  281. pour effet de selectionner le milieu par defaut de l'utilisateur. Cela est 
  282. realise par le systeme d'exploitation de cette maniere :
  283.     1- Si l'utilisateur possede la variable d'environnement LC_ALL , et
  284. qui n'est pas nulle, alors la valeur de cette variable est utilisee comme 
  285. l'argument du milieu.
  286.  
  287.     2- Si l'utilisateur possede une variable d'environnement ayant le meme 
  288.     nom que l'attribut, et qui est non nul, alors cette variable est utilisee comme
  289. l'argument du milieu.
  290.  
  291.     3- Si la variable LANG est positionnee et non nulle alors cette valeur
  292. est utilisee comme argument du milieu.
  293.  
  294.     Si la valeur est valide, supportee par le milieu, alors le milieu est 
  295. modifie. Toutefois, si la valeur est non nulle et contient une valeur non 
  296. suportee par le milieu alors setlocale() revera un pointeur NULL et le 
  297. milieu ne sera pas change par rapport a la valeur du mileu par defaut "C".
  298.  
  299.     Au debut du programme, le systeme d'exploitation execute la fonction 
  300. suivante :
  301.     setlocale(LC_ALL, "C");
  302.     
  303.     Si votre programme n'utilise pas setlocale() ou ne peut pas changer le
  304. milieu (en raison d'un mauvais environnement de variables), alors le 
  305. programme utilisera le milieu par defaut : "C".
  306. Si setlocale() n'est pas capable de changer le milieu, NULL est retourne.
  307.  
  308.     Une bonne methode de programmation consiste a uniquement utiliser les 
  309. attributs qui conviennent a votre logiciel. Un exemple va en illustrer les
  310. raisons :
  311.  
  312.     main()
  313.     {
  314.     setlocale( LC_ALL, "");
  315.     ....
  316.     }
  317.  
  318.     Le programme va maintenant positionner tous les attributs du milieu 
  319. avec soit la valeur de la variable d'environnement LC_ALL si elle est 
  320. positionnee, soit avec la valeur de la variable d'environnement LANG ou bien 
  321. dans le dernier cas, le milieu par defaut "C".
  322.  
  323.     Maintenant supposez que l'utilisateur souhaite avoir tous les messages 
  324. affiches sur son ecran en Anglais, mais il desire utiliser les autres
  325. attributs du milieu Francais. L'utilsateur realise ceci en positionnant la 
  326. variable LC_MESSAGES pour le milieu Anglais, et la variable LANG pour le 
  327. Francais.
  328.  
  329.     L'exemple ci-dessus (utilise LC_ALL) ignore la varible LC_MESSAGES et 
  330. va utiliser a la place la variable LANG ... donc tous les messages seront 
  331. affiches en Francais. L'utilsateur peut soit avoir tous les attributs
  332. positionnes pour le Francais, soit pour l'Anglais.
  333.  
  334.     Admetons que cette situation est un peu exceptionnelle, mais si votre 
  335. programme a juste besoin d'avoir acces aux messages, alors il est juste 
  336. necessaire de positionner cet attribut. Si votre programme a besoin de 
  337. quatre attributs alors, vous devrez utiliser quatre fois setlocale().
  338.  
  339.     C'est a l'utilisateur de bien positionner ses variables 
  340. d'environnement. Il lui est aussi tres facile de le deteriorer, simplement en 
  341. modifiant ses variables. Il est donc plus prudent d'include des informations 
  342. dans votre programme pour que l'utilisateur configure d'une maniere correcte 
  343. son environnement. Cette question sera vue dans une section ulterieure.
  344.  
  345. II-2 CATOPEN()
  346.  
  347.     La fonction setlocale() etablit uniquement le bon milieu que doit 
  348. utiliser le programme. Pour acceder au catalogue, il faut d'abord l'ouvrir. 
  349. Cette fonction realise cette operation. Elle est definie de la maniere 
  350. suivante :
  351.  
  352.     #include <nl_types.h>
  353.     nl_catd catopen(char *nom, int option);
  354.  
  355.     catopen() ouvre le catalogue des messages et retourne un descripteur de 
  356. catalogue. Le "nom" correspond au nom du catalogue qui doit etre ouvert. Si
  357. le nom correspond a un chemin absolu (Contient un /), le nom correspond au 
  358. chemin d'acces a ce fichier. Sinon, la variable NLSPATH est utilisee. Si
  359. NLSPATH n'existe pas, ou si le catalogue ne peux pas etre trouve ou ouvert 
  360. dans les repertoires specifies dans NLSPATH, alors le catalogue est recherche 
  361. dans les repertoires suivants, dans l'ordre :
  362.     /usr/lib/locale/LC_MESSAGES
  363.     /usr/lib/locale/name/LC_MESSAGES
  364.  
  365.     L'argument option est utilise pour indiquer le type de chargement 
  366. desire. Cela peut etre soit MCLoadBySet ou soit MCLoadAll. Le premier indique 
  367. que l'on ne charge que le module necessaire, le dernier specifie que l'on 
  368. charge TOUT le catalogue en memoire.
  369.  
  370. catopen() renvoie soir un descripteur de catalogue nl_catd, soit -1 en cas
  371. d'erreur.
  372.  
  373. Exemple d'utilisation :
  374.     static nl_catd catdc = 0;
  375.     
  376.     catdc = catopen("foo.cat", MCLoadBySet);
  377.  
  378.     if ( catdc == -1)
  379.     printf(" Impossible d'ouvrir le catalogue des messages \n');
  380.  
  381. II-3 CATGETS ()
  382.  
  383.     Une fois que le catalogue des messages a ete ouvert, nous avons besoin 
  384. d'une routine pour acceder au catalogue et recuperer les messages. C'est la 
  385. fonction de catgets()
  386.  
  387.     #include <nl_types.h>
  388.  
  389.     char *catgets(nl_catd catdc, int numero_module, int numero_message \
  390.             char *message);
  391.  
  392.     catgets() lit le message "numero_message", dans "numero_module", dans 
  393. le catalogue des messages identifie par catdc. catfd est le descripteur du
  394. catalogue (cf catopen()). Le quatrieme argument est un pointeur sur une 
  395. chaine par defaut qui sera retournee si le catalogue n'est pas ouvert, ou 
  396. s'il est endommage. Le texte du message est stocke dans un tampon interne 
  397. et doit etre copie par l'application s'il doit etre conserve ou modifie. 
  398. La chaine retournee est toujours terminee par \0.
  399.  
  400.     En cas d'erreur, catgets renvoie un pointeur sur "message" si le 
  401. cataloguen'est pas ouvert. Dans le cas ou le message n'est pas trouve, catgets 
  402. retourne un pointeur sur une chaine vide.
  403.  
  404. Exemple d'utilisation :
  405.  
  406.     printf( catgets( catdc, 3, 7, "Erreur d'acces au bloc No %d"),Num_Bloc );
  407.  
  408.     La fonction ci-dessus essaye d'acceder au 7eme message du 3eme module du
  409. catalogue des messages. Si ce message ne peut etre trouve pour n'importe
  410. quelle raison, alors le message "Erreur d'acces au bloc No %d" est affiche a
  411. la place.
  412.  
  413. II-4 CATCLOSE ()
  414.  
  415.     Une fois qu'un programme a termine d'utiliser un catalogue de messages,
  416. le catalogue doit etre ferme pour que la memoire utilisee soit liberee. 
  417.  
  418.     #include <nl_types.h>
  419.  
  420.     void catclose(nl_catd catdc);    
  421.  
  422.    catclose() ferme le catalogue specifie par catdc. 
  423. catclose() retourne 0 en cas de succes, -1 en cas d'echec.
  424.  
  425. Exemple d'utilisation :
  426.      {
  427.     ...
  428.     catclose(catdc);
  429.     exit(0);
  430.      }
  431.  
  432.     Nous vous avons presente les quatre fonctions C dont vous avez besoin 
  433. pour utiliser les catalogues de messages dans votre logiciel. La prochaine 
  434. partie traitera les outils qui sont disponibles pour vous aider a extraire les 
  435. messages existants dans votre application, et detaillera le programme gencat
  436. utilise pour compiler les messages.
  437.  
  438.     Avant tout, voici le format du fichier de messages. Gencat a besoin 
  439. d'un fichier d'un format special pour qu'il puisse compiler les messages.
  440.  
  441. Exemple de fichier de messages :
  442.     $set 2 #chmod
  443.     $   #1 Original Message:(invalid mode)
  444.     # invalid mode
  445.     $   #2 Original Message:(virtual memory exhausted)
  446.     # virtual memory exhausted
  447.     ...
  448.  
  449.     La premiere ligne est utilisee pour definir le numero du module. Le mot
  450. clef "set" doit etre present dans TOUS les fichiers de messages. Le second champ
  451. est le numero du module et doit etre unique pour le catalogue de message.
  452. Le troisieme est utilise pour identifier le module (Le numero peut etre
  453. egalement utilise):
  454.     $set <No Module> #<Identificateur du Module >
  455.  
  456.     La seconde ligne est l'unique identificateur du message. Il est 
  457. important de remarquer la present du signe $ et du deuxieme champ #<No>. Le 
  458. signe $ est necessaire pour permettre de differencier un message de son 
  459. identificateur. Le second champ (sans #) est l'identificateur du message. Le 
  460. reste est ignore. C'est souvent utile pour inclure le message original pour le 
  461. suivi du code, la traduction, etc
  462.     $   #<No_Message>   [ Texte Ignore ]
  463.  
  464.     La troisieme ligne est le texte du message. Dans ce cas, c'est le 
  465. texte pour le premier message dans le deuxieme module. 
  466.     # < Texte du Message >
  467.  
  468.     Lorsque vous traduisez les fichiers de messages dans d'autres langues, 
  469. il est juste necessaire de traduire les lignes de texte 
  470. ( < Texte du Message > ),c'est a dire les lignes commencant par #. Aucune ligne 
  471. debutant par $ ne sera a modifier.
  472.  
  473.     Le format du fichier ci-dessus correspond parfaitement aux arguments de
  474. la fonction catgets(). La fonction catgets a besoin de No_Module et de
  475. No_Message (deux entiers). Pour affichier le premier message du second 
  476. module,
  477.  
  478.     $set 2 #chmod
  479.   +------^
  480.   | +------v  
  481.   | | $   #1 Original Message:(invalid mode)
  482.   | | # invalid mode
  483.   | | $   #2 Original Message:(virtual memory exhausted)
  484.   | | # virtual memory exhausted
  485.   | |
  486.   | | printf( catgets(catdc, 2, 1, "Mode Invalide") );
  487.   | +---------------------------^
  488.   +--------------------------^
  489.  
  490.     Bien que ces fonctions fonctionnent sans probleme, leur utilisation 
  491. n'est pas intuitive lors de la creation d'un programme. Par exemple, a chaque 
  492. fois qu'un programmer a besoin d'afficher un message, il doit tout d'abords 
  493. chercher le message dans le bon module, trouver son numero et le reporter 
  494. dans son code source. Cela peut rapidement devenir rapidement penible 
  495. lorsque les programmes ont besoin d'acceder a plusieurs modules ou a 
  496. plusieurs catalogues. Autant chercher une aiguille dans une bote de foin !
  497.  
  498.     Au lieu d'utiliser un entier comme numero de module ou numero de 
  499. message, il serait plus facile d'utiliser des noms (texte ASCII). On peut 
  500. utiliser ce systeme si l'on emploi un #define pour faire correspondre le texte 
  501. a un entier.
  502.  
  503. Au lieu d'avoir :
  504.     $set 2 #chmod
  505.     $   #1 Original Message:(invalid mode)
  506.     # invalid mode
  507.     $   #2 Original Message:(virtual memory exhausted)
  508.     # virtual memory exhausted
  509.     ...
  510.  
  511. on aurait :
  512.     $set 2 #chmod
  513.     $   #Invalid_Mode
  514.     # invalid mode
  515.     $   #VM_exhausted
  516.     # virtual memory exhausted
  517.     ...
  518.  
  519.     On peut remarquer qu'aucun changement n'est a effectuer pour le nom du 
  520. module car la troisieme partie de cette ligne est le nom du module.
  521.  
  522.     Pour acceder au second message, on peut utiliser le code suivant :
  523.     printf( catgets(catdc, chmodSet, chmodVM_exhausted, \
  524.             "Plus de memoire virtuelle"));
  525.     
  526.     L'argument No_Module de la fonction catopen() est toujours le nom du
  527. module (chmod ici), rattache au mot "Set" => "chmodSet". Le numero du 
  528. message est toujours le nom du module (chmod) ajoute avec 
  529. l'identificateur du message (VM_exhausted) =>chmodVM_exhausted.
  530.  
  531.     Pour pouvoir utiliser ces noms, le programme doit associer les noms avec
  532. des entiers car la fonction catopen() n'accepte que des entiers comme
  533. parametre. On realise cette association en utilsant le programme gencat qui
  534. va generer les fichiers d'entetes qui sont utilises par le programme.
  535.  
  536. Pour les message ci-dessus, le fichier d'entete ainsi genere ressemble a :
  537.     #define chmodSet            0x2
  538.     #define chmodInvalid_Mode   0x1
  539.     #define chmodVM_exhausted   0x2
  540.     
  541.     Ce fichier d'entete a ete genere a partir du fichier chmod.m. Nous avons
  542. decide d'appeler les fichiers d'entete xxx-nls.h donc dans notre cas, le 
  543. fichier d'entete est appele :  chmod-nls.h
  544.  
  545.     Il ne reste plus qu'a rajouter la ligne 
  546.         #include "chmod-nls.h"   
  547.             au debut du programme.. 
  548.  
  549. II-5 XTRACT :
  550.  
  551.     xtract est un programme ecrit avec yacc pour extraire les messages 
  552. d'un code source. Vous pouvez le trouver sur le site ftp :
  553.    sunsite.unc.edu:/pub/Linux/utils/nls/catalogs/locale-package.tar.gz (US)
  554.    
  555.     xtract recherche dans les sources toutes les chaines de caracteres etant
  556. entre quotes. Il affiche a l'ecran tout ce qu'il trouve.
  557.  
  558.     Il s'utilise de la maniere suivante :
  559.     xtract < source.c > message.m
  560.  
  561.     Le fichier message.m contient alors tous les message que xtract a trouve
  562. dans le source. Les messages sont places dans le format habituel.
  563.  
  564. Toutefois, il est necessaire d'editer le fichier :
  565.     - les deux premieres lignes doivent etre detruites
  566.     - la ligne $set <No_Module> #<Nom_Module> doit etre ajoutee.
  567.  
  568. Exemple :
  569.     Le message original ressemble a cela :
  570.     
  571.     $ #0 Message Original :(Probleme de Configuration)
  572.     #   Probleme de Configuration
  573.     $ #1 Message Original :(Impossible d'ouvir le fichier)
  574.     #   Impossible d'ouvir le fichier
  575.     $ #2 Message Original :(Erreur lors de l'acces au fichier)
  576.     #   Erreur lors de l'acces au fichier
  577.     ...
  578.  
  579. Ce n'est un format correct car il manque ke numero du module. Il suffit de 
  580. rajouter alors la ligne 
  581.     $set X #Descripteur 
  582. au tout debut du fichier. X represente le numero du module.
  583.  
  584. Le fichier ressemble alors a :
  585.  
  586.     $set 17 #Descripteur 
  587.     $ #0 Message Original :(Probleme de Configuration)
  588.     #   Probleme de Configuration
  589.     $ #1 Message Original :(Impossible d'ouvir le fichier)
  590.     #   Impossible d'ouvir le fichier
  591.     $ #2 Message Original :(Erreur lors de l'acces au fichier)
  592.     #   Erreur lors de l'acces au fichier
  593.     ...
  594.  
  595. II-6 GENCAT
  596.  
  597.     (Remarque du traducteur : Il semble qu'il y ait plusieurs versions de 
  598. gencat. Je travaille sur un systeme Linux mais aussi sur Solaris 4.2.3 et le 
  599. gencat standard sun ne possede pas les options qui vont etre expliquees 
  600. ci-dessous.)
  601.  
  602.     Gencat est le programme utilise pour compiler les fichiers de messages. 
  603. Le resultat de la compilation est le catalogue des messages. Voici le detail 
  604. des options de la ligne de commande :
  605.  
  606.   gencat [-new] [-lang C | C++ | ANSIC ] fic_cat fic_msg [ -h <header_file>]
  607.  
  608. Description :
  609.     -new        Detruit le catalogue des message et en cree un nouveau. 
  610.         Le comportement par defaut est de mettre a jour le catalogue 
  611.         avec le(s) fic_msg(s). 
  612.     -lang <l>   Indique le format du fichier d'entete. Pour le moment, les 
  613.         trois formats suportes sont les langages C, C++ et ANSIC. Les
  614.         deux derniers sont identiques. Cet argument peut etre place
  615.         n'importe ou dans la ligne de commande.
  616.     -h <hfile>  Identificateurs des fichiers d'entete crees en sortie.
  617.         
  618.         Cela cree un fichier d'entete avec tous les #define 
  619.         appropries. Sans cela, ca serait a vous de verifier que 
  620.         votre code soit coherent avec le catalogue. Le fichier 
  621.         d'entete est cree a partir de tous les fic_msg de la ligne de 
  622.         commande, donc l'ordre dans la ligne de commande est 
  623.         important. Cela signifie que si vous mettez a la fin l'entete, 
  624.         toutes les entetes seront dans un seul fichier :
  625.             gencat vodka.m pineau.m gin.m -h cuite.h
  626.         Si vous preferez conserver la dependance, vous pouvez 
  627.         specifier un fichier entete par fichier de messages : 
  628.             gencat vodka.m -h beurk.h pineau.m -h c1.h gin.m -h \
  629.                                     cuite.h
  630.         De plus, si vous executez l'instruction suivante,
  631.             gencat vodka.m -h beurk.h
  632.         le fichier beurk.h ne sera pas modifie la deuxieme fois. 
  633.         Gencat verifie si le contenu a ete modifie avant de le 
  634.         retraiter. Vous pouvez egalement utiliser un fichier 
  635.         Makefile de ce genre:
  636.         
  637.         MSGSRC=vodka.m gin.m
  638.         GENFLAGS=-new -lang C
  639.         GENCAT=gencat
  640.         NLSLIB=nlslib/OM/C
  641.         $(NLSLIB):  $(MSGSRC)
  642.             @for i in $?; do cmd="$(GENCAT) $(GENFLAGS) $@$$i -h \
  643.             basename $$i .m'.H"; echo $$cmd; $$cmd; done
  644.         vodka.o:    vodka.h
  645.  
  646.         La boucle for/loop n'est pas tres jolie mais elle marche. 
  647.         Pour chacun des fichier .m qui ont ete modifies, on 
  648.         relance gencat.
  649.  
  650.     Le programme gencat possede deux fonctions et il est utilise 
  651. generalement en deux fois. 
  652.  
  653.     La premiere fonction est de generer les fichiers d'entete a partir
  654. des fichiers de messages pour que les programmes puissent utiliser des noms
  655. quand ils font referenceaux modules et aux messages. La commande suivante 
  656. realise cette operation :
  657.     gencat -new /dev/null foobar.m -h foobar-nls.h
  658.  
  659.     Le -new /dev/null signifie que le catalogue des messages est envoye dans
  660. le fichier null. 
  661.  
  662. La deuxieme fonction est la generation du catalogue des messages :
  663.  
  664.     gencat -new foobar.cat foobar.m
  665.  
  666. Pour generer le catalogue a partir d'un Makefile :
  667.     MESSAGEFILES = toto.m titi.m tata.m
  668.     gencat -new tttt.cat $(MESSAGEFILES)
  669.  
  670.  
  671.  
  672. III     Ecrire des programmes avec "Locale".
  673. --------------------------------------------
  674.  
  675. III.1   Ecrire et modifier des programmes pour qu'ils puissent utiliser le 
  676.         catalogue des messages.
  677.  
  678.     Le probleme est donc de savoir comment modifier ou ecrire un nouveau 
  679. programme qui utilise les catalogues de messages.  Voici les etapes 
  680. necessaires :
  681.  
  682. 1ere etape : (Modification d'un programme existant)
  683.  
  684.     La premiere chose a faire est d'extraire tous les messages du 
  685. programme existant et de les placer dans un fichier de messages. Le 
  686. programme xtract a ete concu pour cela. Cette operation est expliquee 
  687. ailleur dans ce document mais en voici un petit resume :
  688.  
  689.     Code source == toto.c
  690.     Fichier de messages == toto.m
  691.  
  692.     xtract < toto.c > toto.m 
  693.  
  694. Il suffit d'inserer le numero du module approprie dans le fichier toto.m :
  695.     $set X #n
  696.  
  697.     ou X est le numero du module 
  698.     et n est le nom de la variable utilise pour acceder a ce fichier.
  699.  
  700. 2eme etape : (Creation d'un nouveau fichier de messages)
  701.  
  702.     Si vous debutez un nouveau fichier de messages, il est utile de 
  703. rappeler  l'ordre et la structure du fichier de messages . Il est compose 
  704. de trois elements :
  705.     - L'identificateur du module
  706.     - l'identificateur du message
  707.     - le texte de chaque identifiaceur des messages
  708.  
  709.     Le format a ete detaille dans un paragraphe precedent. Ce format de 
  710. fichier doit permettre de resoudre tout probleme de compilation du 
  711. catalogue de messages.
  712.  
  713.     Brievement, en voici la structure :
  714.       $set 2 #chmod
  715.       $       #Invalid_Mode   Message Initial : (Mode Invalide)
  716.       # Mode Invalide 
  717.       $       #VM_exhausted Message Initial : (Plus de Memoire Virtuelle)
  718.       # Plus de memoire virtuelle
  719.       ...
  720.  
  721.     La premiere ligne est l'identificateur du module. Toutes les autres 
  722. lignes debutant par le caractere $ sont les identificateurs de message. Les 
  723. lignes suivantes sont les messages a afficher.
  724.  
  725. 3eme Etape :
  726.  
  727.     Pendant que vous etes en train de modifier un fichier de message 
  728. genere par la premiere etape, ou que vous etes en train de creer un nouveau 
  729. fichier, il est plus facile d'utiliser des noms pour se referencer aux 
  730. messages et aux modules plutot qu'aux nombres. Pour utiliser des noms, nous 
  731. avons besoin d'assigner un nom unique a chacun des modules, et des noms 
  732. uniques pour chacun des messages par modules.
  733.  
  734.     La premiere ligne de chacun des fichiers de messages est 
  735. l'identificateur du module :
  736.     $set X #Mon_Module
  737.     
  738.     X : numero du module pour ce fichier de messages
  739.     Mon_Module : Le nom utilise
  740.  
  741.     X doit etre un nombre unique pour ce module. Il en va de meme pour le 
  742. nom du module. On peut alors acceder a ce module d'une maniere indiferente : 
  743. soit par le nombre, soit par le nom. C'est a vous de choisir. Toutefois, si 
  744. vous vous decidez a utiliser le nom pour acceder au module, pensez a rajouter 
  745. le mot "Set" : le mot complet devient alors : Mon_ModuleSet.
  746.  
  747. 4eme Etape :
  748.     Maintenant que nous utilisons des noms comme identificateurs de 
  749. modules et de messages, nous devons creer le fichier d'entete qui va faire 
  750. correspondre les numeros avec ces noms. Le programme gencat peut etre 
  751. utilise pour generer le fichier d'entete a partir d'un fichier de message. 
  752. Cette operation a ete expliquee precedemment dans le document. Brievement, 
  753. non executons la commande suivante :     
  754.         gencat -new /dev/null foobar.m -h foobar-nls.h
  755.  
  756.     Gencat va donc generer le fichier d'entete. Ce fichier doit etre inclue 
  757. dans notre programme.
  758. Il vaut mieux prendre l'habitude de nommer ses fichiers d'entete "xxx-nls.h". 
  759. Le "-nls" permet de mieux distinguer les fichier d'entete pour les messages. 
  760.  
  761. 5eme Etape :
  762.     Nous sommes maintenant prets a modifier le code source. La premiere 
  763. chose a faire est d'inclure les fichiers d'entete. Nous avons besoin de 
  764. trois fichiers :
  765.     #include <locale.h>
  766.     #include <nl_types.h>
  767.     #include <foobar-nls.h>
  768.  
  769.     Le premier fichier (locale.h) contient plusieurs constantes 
  770. utilisees par setlocale et par d'autres fonctions : LC_*, etc...
  771.  
  772.     Le second fichier contient les constantes et les prototypes pour 
  773. les fonctions catopen, catclose, etc...
  774.  
  775.     Le dernier contient toutes les declarations des messages et des 
  776. modules utilises, ce qui va nous permettre d'utiliser les noms dans les 
  777. fonctions.
  778.  
  779. 6eme Etape :
  780.     
  781.     La prochaine etape constiste a declare une ou plusieures variables 
  782. globales pour les catalogues. Nous avons besoin d'un descripteur de 
  783. catalogue uniquement lorsque nous accedons a un catalogue de messages. 
  784. Normalement, un programme n'aura besoin d'acceder qu'a ses propres messages 
  785. de catalogue et donc, nous n'aurons besoin de definir qu'un seul descripteur 
  786. de catalogue de messages. Cela doit etre defini avant le main() :
  787.  
  788.     /* Variable Globale au module : descripteur de catalogue */
  789.     static nl_catd catfd = -1;
  790.  
  791.     Pour acceder au catalogue de messages nous utiliserons maintenant 
  792. la varibale catfd.
  793.  
  794. 7eme Etape :
  795.     A l'interieur de la fonction main, la premiere chose a faire est de 
  796. positionner le milieu dans lequel le programme va evoluer. Cette operation 
  797. est realisee en utilisant la fonction setlocale() :
  798.     setlocale( LC_MESSAGE , "");
  799.  
  800.     (Voir plus haut pour la description de la fonction setlocale)
  801.  
  802. 8eme Etape :
  803.     Notre programme peut donc acceder au bon repertoire lorsqu'il a 
  804. besoin d'acceder au catalogue des messages ou a d'autre informations sur 
  805. le milieu. Nous devons maintenant ouvrir le catalogue des messages utilise 
  806. par notre programme :
  807.     catfd = catopen("foobar",MCLoadBySet);
  808.  
  809.     Cette operation va ouvrir le fichier de messages foobar.cat (Rq: Ne pas 
  810. specifier .cat). Le type de chargement est specifie dans le deuxieme 
  811. arguement : chargement global en memoire ou chargement module par module.  
  812. Cette derniere option utilise moins de memoire mais elle est plus couteuse 
  813. en temps. Le choix est laisse au programmeur. 
  814.  
  815.     Une solution plus solide pour ouvrir et initialiser le catalogue des 
  816. messages est presentee ci-dessous. Le programme risque devoir ouvrir, fermer, 
  817. manipuler le catalogue des messages a de nombreux endroits dans le programme. 
  818. Il est donc utilise d'utiliser une fonction d'initialisation qui ouvre le 
  819. catalogue de message s'il ne l'est pas deja :
  820.  
  821.     catinit()
  822.     {
  823.         if (catfd == (nl_catd) -1)
  824.             catfd = catopen("foobar", MCLoadBySet);
  825.     }
  826.     La routine verifie que le catalogue est ferme. Si c'est le cas, elle 
  827. l'ouvre. Il vous est tres facile de rajouter des fonctionnalites a cette 
  828. routine. Le premier appel a cette fonction doit etre fait apres l'appel a 
  829. setlocale() dans la fonction main(). Apres cela, vous pouvez l'appler autant 
  830. de fois que vous voulez, si vous n'etes pas sur que le catalogue soit ouvert 
  831. ou ferme.
  832.  
  833. 9eme Etape 
  834.     Nous sommes desormais pret pour utiliser le catalogue des messages. Nous
  835. allons utiliser la fonction catgets.
  836.  
  837.     Cette fonction possede quatre arguments :
  838.         catgets(catfd, Id_Module, Id_Message, *message);
  839.  
  840.     La variable catfd represente le descripteur de catalogue retourne par la 
  841. fonction catinit ou catopen. C'est utilise par catgets pour determiner le
  842. catalogue a utiliser(plusieurs catalogues peuvent etre ouverts en meme temps
  843. dans un programme).
  844.  
  845.     Id_Module represente le module a manipuler. Cela peut etre soit un entier,
  846. soit le nom du module (+"Set").
  847.  
  848.     Id_Message represente le numero ou le nom du message situe dans Id_Module.
  849. Si le nom est utilise, souvenez vous que le nom du module doit etre accole au
  850. nom du message.
  851.  
  852.     *message est la chaine par defaut qui sera utilisee s'il n'est pas possible
  853. d'acceder au message, etc.
  854.  
  855.     exemple :
  856.   catgets(catfd, erreursSet, erreursVM_Exhausted, "Plus de memoire virtuelle");
  857.  
  858.     Cette operation va recuperer le message VM_Exhausted dans le module erreurs
  859. du catalogue. Dans le cas d'une erreur, la chaine "Plus de memoire virtuelle" 
  860. sera utilisee.
  861.  
  862.     Nous vous recommandons de prendre l'habitude de toujours utiliser la chaine
  863. anglaise par defaut (Note Traducteur : Bof,...pourquoi pas le francais !). 
  864.  
  865.     La routine catgets() retourne un pointeur sur un tampon interne termine 
  866. par un caractere NULL (\0). Nous avons besoin d'afficher la chaine :
  867.  
  868.   printf("%s\n",  catgets(catfd, erreursSet, erreursVM_Exhausted, 
  869.                                                 "Plus de memoire virtuelle");
  870.  
  871.     Voici quelques exemples de l'ancienne approche (codage en dur), a opposer
  872. avec la nouvelle methode :
  873.     
  874.     Exemple 1  :
  875.         Avant :
  876.             printf("Incorrect read permission");
  877.  
  878.         Apres :
  879.         printf("%s\n", catgets(catfd, errorsSet, errorsIncorrect_Perm, 
  880.                                             "incorrect read permission");
  881.  
  882.  
  883.     Exemple 2:
  884.         Avant :
  885.             printf("Cannot change to directory %s", dir_name);
  886.  
  887.         Apres :
  888.             (Extrait du catalogue des messages)
  889.             ...
  890.             $ #Cant_chdir
  891.             # Cannot change to directory %s
  892.             ...
  893.  
  894.         printf("%s \n", 
  895.             catgets(catfd, errorsSet, errorsCant_chdir, 
  896.                                   "Cannot change to directory %s"), dir_name);
  897.  
  898.  
  899. 10eme Etape :
  900.     Juste avant que le programme ne se termine, nous devons fermer le catalogue
  901. des messages. Il suffit d'utiliser la ligne suivante : 
  902.         catclose(catfd);
  903.  
  904.     Il est necessaire de faire quelques verifications d'erreurs. Si le 
  905. catalogue des messages ne peut etre ouvert pour n'importe quelle raison,
  906. alors le programme utilise les messages par defauts, dans le code source. 
  907. Cela peut etre une bonne idee de reperer les erreurs pendant le debogage du
  908. progamme. Il peut y avoir un bon nombre de raisons pour lesquelles le catalogue
  909. ne peut etre ouvert par le systeme d'exploitation. (Repertoire incorrect, 
  910. mauvais nom, mauvais droits de fichiers, module incorrect, etc).
  911.  
  912. Voici un exemple de programme utilisant toutes les fonctionalites :
  913.  
  914. ---
  915. #include <stdio.h>
  916. #include <nl_types.h>
  917. #include <locale.h>
  918. #include "foobar-nls.h"
  919.  
  920. static nl_catd catfd = -1;
  921.  
  922. void main()
  923. {
  924.     char temp_name;
  925.  
  926.     setlocale(LC_MESSAGES,"");
  927.     catinit ();
  928.  
  929.     printf(catgets(catfd, foobarSet, foobarRandom_Name, 
  930.                         "Random text with string %s"), temp_name);
  931.     catclose(catfd);
  932.     exit(0);
  933. }
  934.  
  935. catinit ()
  936. {
  937.     if (catfd != (nl_catd)-1)
  938.         catfd = catopen("foobar",MCLoadBySet);
  939. }
  940. ---
  941.  
  942. Un fichier Makefile :
  943.  
  944. -------
  945. all: foobar catalog
  946.  
  947. foobar: foobar.o
  948.     gcc -o foobar -O2 foobar.c
  949.  
  950. foobar.o: foobar-nls.h
  951.  
  952. foobar-nls.h: foobar-nls.m
  953.     gencat -new /dev/null foobar-nls.m -h foobar-nls.h
  954.  
  955. catalog:
  956.     gencat -new foobar.cat foobar.m
  957.  
  958.  
  959. install: all
  960.     install -o root -m 0755 foobar /usr/local/bin
  961.     install -o root -m 0755 foobar.cat /etc/locale/C
  962.  
  963. clean:
  964.     /bin/rm -f foobar *.o foobar-nls.h foobar.cat core
  965.  
  966. -------
  967.     C'est a vous de choisir l'endroit ou vous aller mettre les catalogues 
  968. des messages. Il est surement plus facile de les regrouper dans un repertoire
  969. different du code source de votre programme.
  970.  
  971.  
  972. III.2     Ecrire des programmes qui doivent etre utilises sur des 
  973.          systemes se servant de "Locale" ou non.
  974.  
  975.     Il est relativement facile soustraire les fonctions de specification
  976. du milieu au reste du code. La methode habituelle est de definir un DEFINE :
  977.  
  978. Dans le fichier Makefile, rajoutez les lignes suivantes :
  979.  
  980.                 DEFINES = -DNLS
  981.                 foobar.o:   foobar.c
  982.                            gcc $(DEFINES) foobar.c
  983.  
  984.         Maintenant, dans foobar.c, nous avons :
  985.  
  986. #ifdef NLS
  987.     printf(catgets(catfd, chmodSet, chmodVM_Exausted, 
  988.                         "Virtual Memory Exausted");
  989. #else
  990.         printf("Virtual Memory Exausted");
  991. #endif
  992.  
  993.     Les instructions #ifdef, #endif devront entourer chacune des fonctions 
  994. specifiques a la gestion du milieu. De meme pour les fichiers <locale.h>,
  995. <nl_types.h>, les declaration des descripteurs de catalogues, etc
  996.  
  997. Exemple :
  998.  
  999. #ifdef NLS
  1000. #include <locale.h>
  1001. #include <nl_types.h>
  1002.  
  1003. extern nl_catd catfd;
  1004. void catinit ();
  1005. #endif
  1006.  
  1007. /* Definition des Macros utilisee */
  1008.  
  1009. #ifdef NLS
  1010. #define NLS_CATCLOSE(catfd) catclose (catfd);
  1011. #define NLS_CATINIT catinit ();
  1012. #define NLS_CATGETS(catfd, arg1, arg2, fmt) \
  1013.     catgets ((catfd), (arg1), (arg2), (fmt))
  1014. #else
  1015. #define NLS_CATCLOSE(catfd) /* vide */
  1016. #define NLS_CATINIT /* vide */
  1017. #define NLS_CATGETS(catfd, arg1, arg2, fmt) fmt
  1018. #endif
  1019. ---
  1020.  
  1021. Maintenant, au lieu d'ecrire cela,
  1022.     #ifdef NLS
  1023.         printf(catgets(catfd, chmodSet, chmodVM_exhausted, "Virtual Memory
  1024. exhausted"));
  1025.     #else
  1026.         printf("Virtual Memory exhausted");
  1027.     #endif
  1028.  
  1029. on peut ecrire ceci :
  1030.  
  1031.     printf(NLS_CATGETS(catfd, chmodSet, chmodVM_exhausted, "Virtual Memory
  1032. exhausted"));
  1033.  
  1034.     Cela simplifie enormement les choses. Pour pouvoir supporter le milieu, 
  1035. ou au contraire ne pas le supporter, il suffit de rajouter un -DNLS dans
  1036. le fichier Makefile, rajouter un #include pour le fichier des macros,
  1037. et enfin, entourer chacun des #include "xxxx-nls.h" par des #ifdef, #endif.
  1038.  
  1039.  
  1040. IV      Ou sont stockes mes messages ?
  1041. --------------------------------------
  1042.    Cette section peut etre consideree comme une section d'information. Elle
  1043. ne devrait etre consideree que comme etant un guide approximatif en attendant
  1044. que j'ai le temps de regarder le quatres guides standards de Portabilite 
  1045. d'XOpen. 
  1046.  
  1047.    Les catalogues de messages ainsi que d'autres composantes du milieu sont
  1048. stockes dans deux repertoires :
  1049.             /usr/lib/locale
  1050.             /usr/local/lib/locale
  1051.  
  1052.    Le premier est utilise par les programmes faisant partie du systeme 
  1053. d'exploitation(programmes standards Unix). Le second est utilise pour des 
  1054. programmes personnels, qui ne font pas partit de la distribution standard. 
  1055.  
  1056. On peut trouver des sous-repertoires :
  1057.            LC_COLLATE
  1058.            LC_CTYPE
  1059.            LC_MESSAGES
  1060.            LC_MONETARY
  1061.            LC_NUMERIC
  1062.            LC_TIME
  1063.  
  1064. NB : Ils ne doivent pas etre confondus avec les variables du meme nom. Ce 
  1065. sont les noms actuels de ces repertoires et ne risquent pas de changer. 
  1066. Pour eviter les confusions, nous nous refererons a $(LC_MESSAGES), etc...
  1067.  
  1068.     A l'interieur de ces sous repertoires, on peut y trouver les 
  1069. sous-repertoires pour les pays. Par exemple, sous /usr/lib/locale/LC_MESSAGES, 
  1070. on peut y trouver les repertoires suivants :
  1071.     C
  1072.     POSIX       ->   C
  1073.     en_US.88591
  1074.     de_DE.88591
  1075.     fr_BE.88591
  1076.  
  1077.     Dans chacun de ces sous-repertoires se trouvent les messages 
  1078. specifiques a la langue. Par exemple, les messages en anglais pour 
  1079. l'executable "ls" serait :
  1080.     /usr/lib/locale/LC_MESSAGES/en_US.88591/ls.cat
  1081.  
  1082. Le format est le suivant :
  1083.     /usr/lib/locale/LC_MESSAGES/xx_YY.ZZZ/mm.cat
  1084.     ^^^^^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^ ^^^^^^
  1085.          racine      categorie   langue   catalogue
  1086.  
  1087.     La racine ne change pas : c'est soit /usr/lib/locale pour les programmes
  1088. systemes soit /usr/local/lib/locale pour les autres programmes.
  1089.  
  1090.     La categorie depend seulement des fonctions auxquelles le programmes va
  1091. faire appel. Si le programme a besoin d'informations sur la monaie, il va
  1092. chercher les informations dans :
  1093.                /usr/lib/locale/LC_MONETARY/xx_YY.ZZZ/
  1094.  
  1095.     L'attribut de la langue est probablement le plus important car il 
  1096. determine quelles variables et quels repertoires vont etre utilises. Le format 
  1097. de la langue est le suivant :
  1098.     Langue_Pays.TypeDeCaracteres 
  1099.  
  1100. Voici un exemple :
  1101. en_US.88591    Anglais(USA), utilisation du type de caracteres ISO 88591
  1102. de_DE.88591    Allemand(Allemagne), utilisation du type de caracteres ISO 88591
  1103. fr_BE.88591    Francais(Belgique), utilisation du type de caracteres ISO 88591
  1104.  
  1105.     Le langue est positionnee par la variable d'environement $(LANG). 
  1106. L'utilisateur devra positioner la langue, le pays et le type de caractere d'une
  1107. maniere correcte. Ainsi, le systeme d'exploitation utilisera la variable
  1108. lorsqu'il cherchera le sous-repertoire approprie pour trouver les informations
  1109. ou les catalogues de messages dont il a besoin.
  1110.  
  1111.   Nous avons mis en evidence les deux endroits par defaut que le systeme
  1112. utilise pour stocker ses catalogues de messages et les autres attributs.
  1113. Toutefois, le systeme doit aussi etre capable de gerer les utilisateurs 
  1114. qui ne peuvent installer les catalogues dans ces repertoires (Pour le faire,
  1115. ils devraient avoir les droits du super-utilisateur). Donc, il doivent 
  1116. installer leurs propres catalogues dans leur repertoire personnel. 
  1117. Le systeme peut gerer cette situation : il suffut d'utiliser la variable
  1118. d'environnement NLSPATH.
  1119.  
  1120.   Cette variable contient la liste des repertoires dans lesquels le systeme
  1121. d'exploitation va rechercher les catalogues des messages.
  1122. Exemple :
  1123. NLSPATH=/usr/lib/locale/LC_MESSAGES/%L/%N:/usr/local/lib/locale/LC_MESSAGES/%L
  1124. /%N:~/messages/%N
  1125.         %L => Valeur de la variable LANG
  1126.         %N => Nom du catalogue
  1127.  
  1128.     Ces deux valeurs sont substituees par le systeme d'exploitation (Note 
  1129. traducteur : en fait, c'est le shell...) lors de l'evaluation. L'utilsateur
  1130. peut alors ranger ses catalogues de messages dans ses repertoires personnels.
  1131.  
  1132.     Il peux meme courcicuiter les repertoires pat defaut en changeant 
  1133. l'ordre des repertoires dans la variable d'environement NLSPATH.
  1134.  
  1135. V       Questions les plus frequemment posees. (F.A.Q.)
  1136. -------------------------------------------------------
  1137.  
  1138. Question : Comment puis-je savoir si mon systeme Unix supporte l'utilisation 
  1139. des fonctions de gestion du milieu ?
  1140.  
  1141. Reponse : Un systeme Unix qui supporte toutes les fonctionnalites de ces 
  1142. fonctions doit avoir ces fichiers d'entete :
  1143.         locale.h et nl_types.h
  1144. Il sont en general situes dans le repertoire /usr/include. Si un de ces 
  1145. fichiers est absent, alors votre systeme risque de ne supporter qu'une 
  1146. partie de ces fonctions. Ces deux fichiers sont inclus dans Linux.
  1147.  
  1148. ============================================================================
  1149. Le sujet traite dans ce document possede plusieurs copyrights :
  1150. Alfalfa Software, Mitchum DSouza et Patrick D'Cruze -  1989-1994.
  1151.  
  1152. Envoyez vos suggestions, vos remarques a l'auteur de ce document a 
  1153.         pdcruze@orac.iinet.com.au
  1154.         pdcruze@li.org
  1155.  
  1156. Si jamais des erreurs se sont glissees dans ce documents, envoyez un mail :
  1157.         dumas@emi.u-bordeaux.fr
  1158. ============================================================================
  1159.  
  1160.