Free Sofware - Copertina - Creare CD |
Articoli
Un modo per rendere un programma più user-friendly è quello di usare messaggi nella lingua dell'utente. Per implementare questa possibiltà ci sono vari metodi. Si potrebbe scrivere una versione del programma per ogni lingua, anche se ciò implica un una crescita del sorgente ed una difficile manutenzione dello stesso (se si apporta una modifica, bisogna farlo per tutte le lingue).
Un altro metodo è quello di avere il programma e il file dei messaggi separati. Per esempio se scrivo un programma in inglese, una persona italina deve solo modificare il file dei messaggi, senza modificare il sorgente, in questo modo anche se non conosce si il linguaggio in cui è scritto il programma può avere i messaggi nella propria lingua o anche se si vuole nel proprio dialetto.
La GLIBC2 ha due differenti modi per implementare ciò,
catgets
(X/Open standard) ed gettext
(Uniforum, definito da SUN); anche se nessuno di questi due
modi è uno standard POSIX. Il catgets
proviene
da decisioni industriali e non ``ragionate''. Bisogna anche dire che
il catgets
ha avuto molte versioni, e quindi ci sono anche
delle incompatibiltà. Diciamo che la GNU usa, almeno per i
pacchetti che ho visto io, il gettext
Uniforum (che dal punto
di vista del programmatore è piu semplice, almeno per me).
Per poter decidere in quale lingua vogliamo vedere visualizzati i messaggi (e non solo) del sistema si sono delle variabili di ambiente:
LANG
è una variabile che definisce il paese, settando
questa le altri variabili ne prendono la stessa definizone, salvo
definirle diversamente. Questa variabile influenza anche il programma
man
, per esempio va a cercare le manpages nella dir
$MANPATH/$LANG
.
LC_COLLATE
definisce il modo di operare il sorting di alcne
funzioni del C (sort
, strcoll
e
strxfrm
).
LC_TYPE
si applica per la classificazionee conversione dei
caretteri.
LC_MONETARY
definisce il modo di scrivere le valute.
LC_NUMERIC
definisce il modo di scrivere i numeri che non
sono valute.
LC_TIME
definisce comeil modo di scrivere la data e l'ora.
LC_MESSAGES
seleziona il linguaggio da usare per i
messaggi.
Queste variabili possono essere modificate con il comando:
LC_MESSAGES=it;export LC_MESSAGES
(per bash)
setenv LC_MESSAGES it
(per [t]csh).
Vediamo più da vicino queste implemenatazioni.
Le funzioni definite in questo standard sono: catopen()
,
catgets()
, catclose()
. La prima serve per aprire
il file dove sono definiti i messaggi, catgets
serve per
accedere ai messaggi aperti precedentemente, mentre l'ultima chiude il
file. Vediamo l'header di queste funzioni, come creare un file di messaggi
e un esempio esemplicativo.
nl_catd catopen ( const char *cat_name, int flag) char * catgets (nl_catd catalog_desc, int set, int message, const char *string) int catclose(nl_catd catalog_desc)
La variabile cat_name
è il nome del file che contiene i
messaggi, il quale viene cercato nelle directory specificate da
NLSPATH
, il quale ha il seguente formato:
prefix/share/locale/%L/%N:prefix/share/locale/%L/LC_MESSAGES/%N
prefix
viene configurato quando si compila ed installa la
GNU LIBC2, in genere o /usr
o
/usr/local
, comunque può essere anche modificato. Comunque
nella variabile cat_name
si può anche specificare tutto il
percorso.
Il simbolo %N
sta a definire il nome del file dei messaggi,
mentre %L
definisce la lingua (it
, de
ecc).
L'X/Open definisce il formato del file dei messaggi nel modo seguente:
$
, senza
caratteri di spazi vuoti, seguito da uno spazio sono considerati commenti;
$set
seguito
da un argomento che può essere:
$delset
seguita da uno sapzio vuoto è richiesto un argomento che può essere:
$quote
, viene usato come carattere di input il primo carattere,
senza contare gli spazi vuoti. In genere viene usato il carattere
"
;
Vediamo adesso un esempio esplicativo in cui viene descritto come creare il programma, il file dei messaggi ed come si utilizzano.
Un classico esempio di programma in C è hello.c
, il quale
stampa su video la frase ``hello, world'':
#include#include #include "msgnr.h" int main() { nl_catd catdesc; catdesc = catopen("hello.dat",NL_CAT_LOCALE); printf(catgets(catdesc,MainSet,MainHello,"Hello, world!\n")); catclose(catdesc); return 0; }
Come avete notato si include un file msgnr.h
il quale viene
creato dal file dei messaggi hello.msg
:
$quote " $set MainHello "Ciao, Mondo!\n"
Adesso si deve usare il programma gencat
per poter creare
dal file hello.msg
il file hello.cat
, che è quello
che legge il programma mediante la funzione catopen()
, ed il
file msgnrs.h
per poter compilare correttamente il file
hello.c
.
% gencat -H msgnrs.h -o hello.cat hello.msg % gcc -o hello hello.c % cp hello.cat /usr/share/locale/it/LC_MESSAGES
Settate la variabile LC_MESSAGES
per i messaggi in italiano:
% LC_MESSAGES=it;export LC_MESSAGES
Ciao, Mondo!
Vediamo invece adesso come avere il supporto per la propria lingua con l'Uniform.
L'approccio con gettex
è completamente diverso, non bisogna
creare nessun file dei messaggi, né seguire le regole a riguardo la
numerazione dei messaggi, basta solo usare la funzione
gettext()
quando si vuole visualizzare un messagio.
Per specificare il nome del file con i messaggi, ed dove si trova
quest'ultimo ci sono due funzioni: textdomain()
e
bindtextdomain()
.
Vediamo come si modifica il programma hello.c
:
#include#include int main() { textdomain("hello"); bindtextdomain("hello","/home/arete/devel/locale"); printf(gettext("Hello, world!\n")); return 0; }
Adesso per creare il file dei messaggi basta dare il comando:
% xgettext hello.c
Il programma crea un file messages.po
il cui contenuto è il
seguente:
msgid "" msgstr "" "Date: 1998-06-24 23:11:40+0000\n" "From: Di Iorio Gerardo \n" "Content-Type: text/plain; charset=\n" "Xgettext-Options: \n" "Files: hello.c\n" #: hello.c:11 msgid "Hello,world!\n" msgstr ""
Come si vede è più umanamente leggibile rispetto a quello del catgets e basta inserire nella riga sotto al messagio la traduzione per la particolare lingua. Vorrei far notare come sia più semplice da parte di terzi che non sanno niente di programmazione ed altro di tradurre questi file di messaggi; nel nostro caso il file dei messaggi, it.po, diventa:
msgid "" msgstr "" "Date: 1998-06-24 23:11:40+0000\n" "From: Di Iorio Gerardo \n" "Content-Type: text/plain; charset=\n" "Xgettext-Options: \n" "Files: hello.c\n" #: hello.c:11 msgid "Hello,world!\n" msgstr "Ciao, mondo!\n"
In genere questi file dei messaggi hanno l'estensione .po
,
mentre il file che il programma andrà a leggere, in genere ha l'estensione
.mo
, il quale viene creato mediante il comando:
% msgfmt it .po -o hello.mo
Copiatelo nel PATH
definito in
bindtextdomain()
, ed il gioco è fatto. Il PATH
può
essere anche definito al momento della compilazione, ad esempio:
#include#include int main() { textdomain("hello"); bindtextdomain("hello",LOCALEDIR); printf(gettext("Hello, world!\n")); return 0; }
e copilato con il comando:
% gcc -o hello -DLOCALEDIR=\"/dove/si/trova\" hello.c
Devo ricordare che il file .mo
, ad esempio
hello.mo
, si deve trovare nella directory
/dove/si/trova/it/hello.mo
.
I programmi xgettext
e msgfmt
si trovano nel
pacchetto gettext
, in qualsiasi sito che faccia il mirror di
GNU.
Questo articolo vuol dare un esempio su come scrivere programmi con il
supporto per il locale, maggiori informazioni si possono trvare nel
pacchetto gettext
, oppure nel manuale della
GLIBC2 (nella versione 2.0.6, nel manuale questa parte non
c'era, mentre c'è sicuramente nella 2.0.94, nelle altre non ne sono
sicuro, controllate...).
Free Sofware - Copertina - Creare CD |