viernes, 1 de abril de 2011

Internacionalizando un programa

Hoy veremos como hacer posible que se traduzca un programa a distintas lenguas ( internacionalización ), esto lo haremos con la librería gettext de GNU, para las pruebas usaré este hola mundo {hw.c}

#include <stdio.h>

int main(void){
    printf("Hola, mundo!\n");
    return 0;
}



Primero hay que incluir <libintl.h> <locale.h> y añadir esto en el main

setlocale(LC_ALL, "");
bindtextdomain("helloworld", ".");
textdomain( "helloworld");


Hecho esto, buscamos todas las cadenas a traducira gettext  mandandolas como parámetro (para proyectos grandes se suele usar _ como alias gettext ). Por ahora va más o menos así:

#include <stdio.h>
#include <libintl.h>
#include <locale.h>

int main(void){
    setlocale(LC_ALL, "");
    bindtextdomain("helloworld", ".");
    textdomain( "helloworld");

    printf(gettext("Hola, mundo!\n"));
    return 0;
}


Ahora una de dos, nos ponemos a lanzar comandos o automatizamos, optaremos por la segunda, así que a hacer un script:

src=hw.c
binary=hw
pot=hw.pot
package_name=helloworld
mo=$package_name.mo
domain=helloworld
if [ -z "$1" ];then
    gcc -o $binary $src
    xgettext --package-name $package_name --package-version 1 --default-domain $domain --output $pot $src
elif [ "$1" = "gettrad" ];then
    if [ -z "$2" ];then
        echo "No me has indicado el codigo de idioma { ej: es_ES }"
    elif [ -z "$3" ];then
        echo "No me has indicado el archivo"
    else
        msginit --no-translator --locale $2 --output-file $3 --input $pot
    fi
elif [ "$1" = "addtrad" ];then
    if [ -z "$2" ];then
        echo "No me has indicado el codigo de idioma { ej: es_ES }"
    elif [ -z "$3" ];then
        echo "No me has indicado el archivo"
    else
        mkdir --parents ./$2.utf8/LC_MESSAGES
        msgfmt --check --verbose --output-file ./$2.utf8/LC_MESSAGES/$mo $3
    fi
fi


Tiene tres partes, la que se ejecuta cuando no recibe parámetros

gcc -o $binary $src
xgettext --package-name $package_name --package-version 1 --default-domain $domain --output $pot $src

Compila el programa y lanza xgettext, que extrae las cadenas gettext, del código fuente y lo guarda en un archivo .pot

La segunda, cuando recibe como primer parámetro gettrad, (y el código del idioma a traducir y el archivo donde se guardará)

msginit --no-translator --locale $2 --output-file $3 --input $pot


Crea el archivo .pot, donde se realizará la traducción.

Y la tercera, que añadirá la traducción, recibiendo como primer parámetro addtrad (y el código de idioma traducido y el archivo de traducción )

mkdir --parents ./$2.utf8/LC_MESSAGES
msgfmt --check --verbose --output-file ./$2.utf8/LC_MESSAGES/$mo $3


Comprueba que haya un directorio para las traducciones y compila el archivo.

Y ya está, para probarlo podemos hacer

LANGUAGE=es_ES.utf8 ./hw


En esta parte hay que tener en cuenta que hasta ahora el código de lenguage sería es_ES, pero en este último paso se añadiría utf8 al final.


Por último hacer notar que el directorio de traducciones puede estar en . o en /usr/share/locale-langpack/ , esto último es lo que se hace normalmente

Hasta otra

[Referencias]
http://www.gnu.org/software/gettext/FAQ.html
http://www.gnu.org/software/gettext/manual/gettext.html
http://stackoverflow.com/questions/1003360/complete-c-i18n-gettext-hello-world-example/1033337#1033337

No hay comentarios:

Publicar un comentario