<!doctype linuxdoc system>

<article>
<!-- Notas: 
- 1 pagina de articulo, aprox. 6000 caracteres
- Un cuadro al menos cada dos paginas, o un cuadro y una captura
- Capturas con pie de foto
- Para incluir imagen ********* IMAGEN **********+
- 1 sumario por pagina 
-->


<title>Artículo para la revista Linux Actual número 18: Internacionalización de programas en GNU/Linux
<author>Javier Fernández-Sanguino Peña 
<date>10 junio 2001

<abstract>
La internacionalización es el proceso que permite que un programa
ofrezca a un usuario un entorno de computación adaptado a su
propio país: lenguaje, símbolos monetarios, formatos de fecha y
hora...  En éste artículo se verán los distintos esfuerzos que se
están llevando a cabo para hacer al SO GNU/Linux internacional,
centrándose en la internacionalización de programas.
</abstract>

<sect>El inglés como idioma universal

<p>El inglés es el idioma oficial por regla general en la práctica
totalidad de proyectos de software libre en la actualidad. Este idioma
se ha convertido en este siglo en el idioma internacional por
excelencia, y es una realidad que afecta, no sólo a los usuarios
dentro del mundo GNU/Linux sino a cualquier usuario de los sistemas de
la información. Es por esto que el inglés es el idioma en el que
habitualmente los programas presentan sus mensajes, y la mayoría de la
documentación está realizada en inglés.

<p>No cabe duda que el uso de un único lenguaje facilita la coordinación
	del trabajo de los desarrolladores, a la hora de intercambiar
	ideas, y la difusión de un proyecto, pero los usuarios desean
	más, desean que los entornos en los que trabajen estén
	adaptados a sus entornos específicos.

<p>Esta adaptación no es exclusivamente, aunque sí es la primera
	evidencia, la traducción de todos y cada uno de los mensajes,
	menús, botones, etc. que muestra el programa al
	usuario. También incluye la adaptación del programa para que
	al utilizar otras características eminentemente locales, se
	"adapte" al entorno. Por ejemplo, al utilizar unidades
	monetarias muestre preferentemente las unidades locales con
	las expresiones habituales de separación de decimales,
	nomenclatura, etc. o que la representación de fechas y horas
	se haga en la manera acostumbrada al usuario (día-mes-año en
	lugar de mes-día-año por ejemplo), o incluso que las unidades
	métricas utilizadas para la representación de distancias,
	pesos, etc. sean las utilizadas por el usuario.

<p>La modificación de un software para que sea capaz de ofrecer estas
	funciones es lo que se conoce como internacionalización
	(muchas veces se reduce al acrónimo 'i18n'). Mientras que la
	modificación de estas funciones para adaptar un programa a un
	determinado entorno se conoce como localización (muchas veces
	reducido a 'l10n'). Explicándolo en forma breve, los
	programadores internacionalizan y los traductores localizan.


<sect>Internacionalización de mensajes: gettext
<p>Dentro de la internacionalización de programas, uno de los aspectos
	más críticos es la posibilidad de traducir los mensajes que
	presenta el programa al usuario. No sólo los mensajes que
	puedan aparecer en el interfaz gráfico, por ejemplo, sino todo
	tipo de mensajes de error que genere el programa, ayuda en las
	opciones al ejecutarse, etc.

<p>La herramienta GNU para la internacionalización de mensajes en
	programas es Gettext. Esta herramienta, desarrollada entre
	1994 y 1995 por un grupo variado de programadores, facilita la
	creación de programas que pueden distribuirse con múltiples
	catálogos de mensajes en distintos idiomas. Posteriormente, en
	entornos localizados, los programas pueden presentar los
	mensajes correspondientes al entorno declarado por el usuario.

<p>Esta herramienta es relativamente transparente al programador, ya
	que sólo tiene que marcar los mensajes que cree que deben
	traducirse. Asimismo, la modificación del código fuente y
	reubicación de los mensajes es relativamente transparente al
	traductor, que sólo tiene que mantener actualizado un listado
	de traducciones de los mensajes. Las herramientas de gettext
	se encargan, por debajo, de homogeneizar los catálogos y
	modificar éstos cuando las fuentes cambian, pero preservando
	las traducciones ya realizadas.

<p>De esta forma, el trabajo de traducción de los mensajes de un
	programa se reduce a una traducción inicial de todos los
	mensajes y al mantenimiento de los pequeños (o grandes)
	cambios en el código que puedan suponer la introducción (o
	desaparición) de mensajes. Y el trabajo del programador se
	limita a incorporar las funciones necesarias en su
	programa. Una vez hecho esto, el trabajo de ambos grupos puede
	proceder por separado, lo cual facilita el desarrollo en ambos
	sentidos. Es decir, un traductor no tiene que depender del
	programador para incorporar un nuevo idioma y un programador
	no depende del esfuerzo de traducción para la generación de
	nuevas versiones de su programa.

<sect>Preparar un programa para internacionalización

<p>Lo primero que debe hacer un programador para internacionalizar su
	software es detectar en qué puntos de éste se introducen
	mensajes que van destinados al usuario (bien porque sean
	mensajes que aparezcan en pantalla durante el uso del programa
	o porque se envíen en determinadas circunstancias de
	error). Estos mensajes (cadenas de caracteres) tienen que ser
	marcados de forma que pueda extraerse esta información.


<p>Algunos de los cambios que son necesarios hacer a las fuentes del
	programa las realiza el programa <em>gettextize</em>. Este
	programa, invocado directamente en el directorio raíz de las
	fuentes realiza las siguientes funciones:

<itemize>
<item>copia el fichero <tt>ABOUT-NLS</tt> que describe el entorno de
	    internacionalización utilizado.
<item>crea el directorio <tt>intl/</tt> y pone allí todos los ficheros
	    que se distribuyen con <em>gettext</em>, estos ficheros
	    son los ficheros de cabecera de la librería
	    <em>libintl</em> y deben ser idénticos entre distintos
	    proyectos de software internacionalizados.
<item>crea el directorio <tt>po/</tt> y el fichero
	    <tt>Makefile.in.in</tt> dentro de éste. Este directorio
	    será el repositorio de la traducción de mensajes que se
	    incluirá con la distribución del programa.
</itemize>

Sin embargo, aunque se hayan realizado estos cambios a las fuentes, el
	desarrollador tiene que realizar otros de forma manual para
	asegurar que la internacionalización pueda llevarse fácilmente
	a cabo:

<itemize>
<item>crear el fichero <tt>po/POTFILES.in</tt> e introducir en él una
	    lista (un fichero por línea) con los ficheros que
	    contienen mensajes marcados para traducción.

	    <item>modificar el fichero <tt>configure.in</tt> (del
	    sistema de auto configuración) para:

<itemize>
<item> introducir los cambios
	    necesarios para que el sistema de auto-configuración
	    busque las librerías de internacionalización (con la macro
	    AM_GNU_GETTEXT).
<item>indicar los idiomas a los que está traducido el programa
	    (ficheros .po con traducciones) con la definición de
	    ALL_LINGUAS.
<item>declarar el nombre del paquete y versión. Generalmente se hará
	    con las siguientes líneas, y esto permitirá a
	    <em>gettext</em> el hacer un seguimiento de las fuentes de
	    código frente a las traducciones de mensajes. Como se verá
	    más adelante podrán variar de forma independiente:

<tscreen>
<verb>
PACKAGE=programa
VERSION=X.Y.Z
AC_DEFINE_UNQUOTED(PACKAGE, "$PACKAGE")
AC_DEFINE_UNQUOTED(VERSION, "$VERSION")
AC_SUBST(PACKAGE)
AC_SUBST(VERSION)
</verb>
</tscreen>

<item>incorporar nuevos ficheros a los  que se modifican con el guión
		<em>configure</em>, cambiando  la macro
		AC_OUTPUT, para
		incluir a <tt>intl/Makefile</tt> y <tt>po/Makefile.in</tt>.
</itemize>

<item>modificar los ficheros <tt>acconfig.h</tt> y <tt>aclocal.m4</tt>
	    (si existen) para incluir las funciones necesarias para
	    que se detecte el soporte de internacionalización al
	    configurar las fuentes.

<item>modificar el fichero <tt>Makefile.in</tt> en el directorio raíz
	    y en los de las fuentes de forma que se incluyan las
	    librerías de internacionalización al compilar (tanto al
	    generar los ficheros objeto como al enlazar
	    dinámicamente), y para que se instalen los ficheros po en
	    el sistema al ejecutar a <em>make install</em>. 

</itemize>

Con estos cambios, el desarrollador se asegura que, al configurar el
	programa se detecte el soporte (o no) de internacionalización
	del sistema y que, tras esto, se compilen las fuentes de la
	manera adecuada y se instalen con soporte de
	internacionalización (incluyendo todos los ficheros de las
	traducciones) si el sistema no carece de soporte para éste.


Una vez realizado estos cambios es necesario cambiar las fuentes C en
	sí del programa, para marcar los mensajes que se deban
	traducir. La búsqueda de estos mensajes puede ser algo
	tediosa, aunque dependerá del programa en sí. Se puede seguir
	la máxima de "todo aquello que se presenta al usuario debe ser
	internacionalizado" y así buscar mensajes que se presenten a
	este (mediante funciones de salida como printf) o cadenas que
	se utilicen para generar salidas (como botones o menús). Una
	vez localizadas, estos mensajes deben rodearse con una llamada
	a gettext. Así, una línea de código del estilo de 
<tscreen>
<verb>
printf("Hola, mundo\n");
</verb>
</tscreen> 
	se convertirá a
<tscreen>
<verb>
printf(gettext("Hola, mundo\n"));
</verb>
</tscreen> 
	También es común utilizar la forma abreviada <em>_()</em> con
	un #DEFINE previo, en lugar de la llamada a gettext. En la
	mayoría de estos casos estos cambios no afectan mucho al
	código así, sin embargo habrá casos en los que sea necesario
	modificar ligeramente el código. Por ejemplo, cuando la cadena
	de caracteres a traducir se había supuesto de un tamaño fijo
	de caracteres. No olvidemos que lo que hará la función
	<em>gettext</em> en tiempo de ejecución será sustituir esta
	cadena por el equivalente traducido dentro de la ejecución del
	programa.

En muchos casos, esta modificación de las fuentes, cuando los mensajes
	de salida están definidos claramente, se puede hacer incluso
	de forma directa mediante la sustitución de expresiones
	regulares con un sencillo programa en PERL o awk.


En cualquier caso, la documentación de <em>gettext</em> incluye
	precisas explicaciones de cómo modificar convenientemente las
	fuentes para que tengan soporte de internacionalización.


En el listado 1 se muestra un ejemplo de la internacionalización de un
programa. En este caso se trata del programa <em>hello</em>, un
programa de demostración de GNU que muestra el consabido "Hello,
world!" por pantalla al ejecutarse. Como puede verse (con '+' se
indican las líneas añadidas y con '-' las eliminadas) se han
modificado, rodeándolos con una llamada a la función <em>gettext</em>
todos los mensajes que se envían por pantalla. También se han añadido
las directivas de compilador necesarias para incluir las funciones de
internacionalización.

El resultado de ejecutar <em>xgettext hello.c</em> se muestra en el
listado 2. Como puede verse aquí, todas las cadenas marcadas con
<tt>gettext()</tt> han sido extraídas y el fichero resultante es una
plantilla que puede utilizarse para traducir directamente éstas.


<sect>Traducción de los mensajes

<p>Una vez que se han modificado de forma adecuada las fuentes, se
	utilizará la herramienta <em>xgettext</em> para extraer de
	éstas las cadenas que pueden ser traducidas. Estas cadenas se
	extraen todas juntas a un sólo fichero
	<em>po/messages.pot</em>. Este fichero será el que se pueda
	utilizar como plantilla posteriormente por los traductores
	para generar los ficheros <em>LENGUAJE.po</em>.

<p>Este proceso se muestra de forma completa en la figura 1. Como
puede verse allí éste fichero se obtiene a través de las fuentes ya
preparadas para internacionalizarse. Si se dispone de una traducción
de una versión previa del programa, podrá utilizarse el programa
<em>msgmerge</em> para utilizar las traducciones ya realizadas de
	mensajes en la generación del fichero a
	traducir. <em>Msgmerge</em> tiene la ventaja de que es capaz
	de juntar ficheros <tt>.po</tt> de forma <em>difusa</em>. Es
	decir, aunque las fuentes hayan modificado la localización de
	los mensajes a internacionalizar, es capaz de encontrar dónde
	debería incluir un texto ya traducido.

<p>Con el fichero <tt>.po</tt> generado, con o sin traducciones
	  previas, éste puede ser ya distribuido a los responsables de
	  las traducciones para que incorporen a éste la traducción de
	  los mensajes existentes. Si nos encontramos ante un programa
	  que se va a internacionalizar en este momento a un nuevo
	  idioma, el fichero <tt>.po</tt> tendrá un aspecto similar al
	  del Listado 2. Sin embargo, si el programa ya ha sido
	  internacionalizado previamente, el fichero tendrá cadenas
	  traducidas y cadenas sin traducir, o incluso cadenas que han
	  sido modificadas en la última versión del programa y
	  necesitan ser revisadas.

<sect>La evolución en ficheros po

<p>¿Cómo evolucionan los ficheros <tt>.po</tt>? Uno podría pensar que
	una vez realizada la traducción de los mensajes a un
	determinado idioma para un programa no es necesario realizar
	nada más. Sin embargo esto no es así, los programas son entes
	vivos, cambian, evolucionan, incorporan  nuevas
	funcionalidades, etc. Esto trae consigo, como uno pudiera
	esperar, que los mensajes que se ofrecen al usuario, los
	botones, los menús, etc. cambien también con el tiempo. Aunque
	el grueso de los mensajes pueda no variar, es necesario
	revisar, con cada nueva versión que se distribuye de un
	programa los mensajes internacionalizados.

<p>Pero sin embargo, y he aquí una de las maravillas de gettext, esta
	revisión no influye para nada la tarea del programador o
	programadores encargados de mejorar y distribuir las nuevas
	versiones del programa. Es decir, el hecho de que no haya una
	persona encargada de una determinada traducción no tiene por
	qué interrumpir la distribución de un programa. Sí, los
	mensajes no estarán todos traducidos, pero ésto "sólo" se
	traducirá en que un usuario verá los mensajes en dos
	idiomas. Los traducidos, en su idioma nativo, y los no
	traducidos en el idioma original.

<p>Evidentemente, esto es mucho mejor que no disponer de una nueva
	versión del programa por no poder contactar con los
	traductores cuando a lo mejor se está hablando de un programa
	internacionalizado a más de diez idiomas. También es mejor que
	ver los mensajes en el idioma original cuando no se ha podido
	llegar a traducir el 100% de los mensajes.

<p>Asisten en esta tarea las herramientas, <em>msgmerge</em> y
	<em>msgcmp</em>. La segunda permite determinar si se han
	traducido todos los mensajes con respecto a la última versión
	disponible del programa, y la primera permite distribuir una
	nueva versión de un fichero de mensajes "mezclando" los
	mensajes ya traducidos con los nuevos a traducir.

<sect>¿Quién traduce los programas?

<p>Como se puede ver en listado 2, la traducción de mensajes es muy
	sencilla, y cualquier usuario puede coger un fichero
	<tt>.po</tt> traducido parcialmente y rellenar los "huecos"
	que falten. Este hecho, en el mundo GNU lleno de personas de
	muchas capacidades distintas dispuestas a colaborar, garantiza
	la posibilidad de colaborar y de formar parte de un equipo de
	traducción a usuarios que no tengan ningún tipo de
	conocimiento de programación. Para mantener un fichero
	<tt>.po</tt> al día sólo es necesario conocer tanto el idioma
	original como el idioma final de la traducción.

<p>Así pues, uno de los objetivos logrados de la librería gettext es
	  que cualquier persona, con unos mínimos conocimientos, pueda
	  colaborar en la internacionalización de los programas
	  derivados del software libre. No siendo necesario ser un
	  desarrollador de programas, ni una persona experta en
	  programación para llevar estas tareas a cabo.

<p>En el proyecto GNU se dan soporte a distintos grupos de
      internacionalización que son las personas responsables de la
      traducción de los programas. Aún así no es necesario una
      dedicación permanente a estos grupos para internacionalizar un
      programa, como ya se ha visto, la internacionalización puede ser
      un esfuerzo puntual y concreto. La existencia de los grupos
      garantiza, sin embargo, la correcta revisión de estos trabajos
      puntuales que pueden realizar los usuarios, la elaboración de
      glosarios que den uniformidad a los programas traducidos y la
      actualización de las traduccioens en vistas de nuevas versiones
      de programas.


<sect>Distribución de los binarios
<p>Con las traducciones ya realizadas de los ficheros <tt>.po</tt> de
	los distintos lenguajes disponibles, ya sólo queda generar el
	formato necesario para su distribución. En la distribución de
	mensajes traducidos, se utilizan ficheros <tt>.mo</tt> que
	genera de forma automática la herramienta
	<em>msgftm</em>. Estos ficheros binarios se distribuyen de
	forma conjunta con el código fuente, instalándose en
	ubicaciones predefinidas.

<p>La librería gettext cargará dichos binarios cuando el entorno del
	usuario indique un idioma del que está disponible la
	correspondiente versión traducida.

<p>Esta ubicación suele ser
	<tt>/usr/share/locale/LENGUAJE/LC_MESSAGES</tt>, lo que
	permite que, el usuario que no desee mensajes en otros idiomas
	distintos del suyo, pueda eliminar aquellos que no considere
	importantes. En cualquier caso, los binarios del programa se
	distribuyen habitualmente con todos los mensajes traducidos a
	todos los idiomas, y tendrá que ser el sistema de instalación
	del sistema operativo del usuario el que le de la opción de
	eliminar dichos idiomas.


<sect>Herramientas de gettext
<p>Ya se han visto, en la descripción de las tareas de
	internacionalización, algunos de los programas que incorpora
	la librería de GNU gettext para ayudar a la tarea de
	internacionalización. La librería incorpora, en total, los
	siguientes programas:

<itemize>
<item>gettextize. Añade los ficheros necesarios al árbol de fuentes de
	    un programa para su internacionalización. Estos ficheros
	    son comunes a todos los programas con ésta característica.
<item>xgettext. Extrae los mensajes a traducir de unas fuentes
	    internacionalizadas, generando el fichero <tt>messages.po</tt>
	    correspondiente.
<item>msgmerge. De una serie de mensajes ya traducidos, dentro de un
	    catálogo, incorpora las traducciones a los
	    correspondientes ficheros de un programa
	    internacionalizado.
<item>msgfmt. Genera los ficheros binarios con los mensajes traducidos
	    para su distribución, es decir, los ficheros <tt>.mo</tt>
<item>msgunfmt. Realiza la operación inversa al programa anterior,
	    es decir, de un fichero <tt>.mo</tt> genera su equivalente <tt>.po</tt>

<item>msgcomm. Busca mensajes comunes entre dos o más ficheros <tt>.po</tt>.

<item>msgcmp. Compara dos ficheros <tt>.po</tt> para comprobar que
	    ambos contienen el mismo número de cadenas traducidas, con
	    lo que permite verificar si se han traducido todos y cada
	    uno de los mensajes del programa.

</itemize>




<!-- Hablar de pointerize? mirar.. -->
<!-- mirar entorno de internacionalización de KDE y GNOME -->
<sect>Conclusiones
<p>En este artículo se ha visto cómo se internacionaliza un programa,
	  y qué herramientas se pueden utilizar para ello,
	particularizando a la librería más utilizada del mundo de
	software libre, la librería Gettext. Aunque éste artículo se
	ha centrado en la internacionalización de fuentes en C/C++,
	también es posible internacionalizar fuentes escritas en otros
	lenguajes de programación. Por ejemplo, PERL cuenta con una
	librería de adaptación a gettext llamada Locale::gettext que
	permite la internacionalización de programas interpretados en
	este lenguaje.

<p>El usuario avanzado, que desee encontrar más información, puede
	acudir a  http://www.gnu.org/software/gettext/gettext.html (y
	gettext.gnu.org). Si tiene instalado el software de gettext,
	también dispondrá de la ayuda en línea, que podrá consultar
	ejecutando <tt>info gettext</tt>

<p>Si desea ayudar al esfuerzo de internacionalización de programas de
	GNU, contacte con su equipo local de trabajo. Puede contribuir
	sus trabajos a través del Proyecto de Traducciones Libres
	(<em>Free Translation Proyect</em>, n. del a.)  en
	http://www.iro.umontreal.ca/contrib/po/.  Si desea ver el
	estado de las traducciones existe una base de datos de
	traducciones y traductores que puede consultar en
	http://www2.iro.umontreal.ca/~pinard/po/registry.cgi?team=es.
	En cualquier caso, algunos programas internacionalizados
	pueden no haberse incluido en el proyecto GNU, para hacerse
	una idea de la internacionalización de programas en un sistema
	operativo GNU/Linux, pruebe a consultar, por ejemplo, el
	Monitor de traducciones de Debian en http://www.debian.org/intl/l10n/po-es


<sect>Sumarios
<p>
El inglés es el idioma oficial de la mayoría de los proyectos de
	software libre.

Los usuarios desean que sus entornos estén adaptados a ellos.

La modificación del software es parte de la internacionalización.

La librería gettext es el estándar para internacionalizar programas.

Para preparar un programa hay que detectar dónde se ofrecen mensajes
	al usuario.

Algunos cambios para la internacionalización se pueden hacer de forma
	automática.

El soporte de internacionalización se puede detectar al compilar el
	programa.

Es necesario marcar los mensajes en las fuentes en C.

La plantilla de mensajes está en el fichero messages.pot

Los mensajes se traducen en los ficheros .po

Los ficheros .po se pueden utilizar aunque estén parcialmente
	traducidos.

Gettext incorpora una variedad de herramientas para ayudar a la
	internacionalización.

La traducción de mensajes es tan sencilla que cualquier usuario puede
	colaborar.

PERL también incorpora una librería de adaptación a gettext.




<sect>Listados
<P>

LISTADO 1

<tscreen>
<verb>
$ diff -ur hello/hello-1.3/hello.c ./hello-int/hello-1.3/hello.c
--- hello/hello-1.3/hello.c	Sun Jun 10 18:30:47 2001
+++ ./hello.c	Tue May 16 21:49:28 2000
@@ -64,6 +64,12 @@
 #endif	/* HAVE_ALLOCA_H.  */
 #endif	/* GCC.  */
 
+#include &gt;libintl.h&lt;
+#define _(String) gettext (String)
+
+#include "config.h"
 
 #define the (1)
 
@@ -79,7 +85,7 @@
 
 extern char version[];
 
-char usage[] = "Usage: %s [-htvm] [--help] [--traditional] [--version] [--mail]\n";
+char usage[] = gettext("Usage: %s [-htvm] [--help] [--traditional] [--version] [--mail]\n");
 
 static char *progname;
 
@@ -91,6 +97,14 @@
   int optc;
   int h = 0, v = 0, t = 0, m = 0, lose = 0, z = 0;
 
+#ifdef ENABLE_NLS
+   setlocale (LC_ALL, "");
+   bindtextdomain (PACKAGE, LOCALEDIR);
+   textdomain (PACKAGE);
+#endif
+
+
+
   progname = argv[0];
 
 #define king
@@ -136,15 +150,15 @@
   if (h)
     {
       /* Print help info and exit.  */
-      fputs ("This is GNU Hello, THE greeting printing program.\n",
+      fputs (gettext("This is GNU Hello, THE greeting printing program.\n"),
 	     stderr);
       fprintf (stderr, usage, progname);
-      fputs ("  -h, --help\t\t\tPrint a summary of the options\n", stderr);
-      fputs ("  -t, --traditional\t\tUse traditional greeting format\n",
+      fputs (gettext("  -h, --help\t\t\tPrint a summary of the options\n"), stderr);
+      fputs (gettext("  -t, --traditional\t\tUse traditional greeting format\n"),
 	     
 	     stderr);
-      fputs ("  -v, --version\t\t\tPrint the version number\n", stderr);
-      fputs ("  -m, --mail\t\t\tPrint your mail\n", stderr);
+      fputs (gettext("  -v, --version\t\t\tPrint the version number\n"), stderr);
+      fputs (gettext("  -m, --mail\t\t\tPrint your mail\n"), stderr);
       exit (0);
     }
 
@@ -177,7 +191,7 @@
 	      struct passwd *pwd = getpwuid (getuid ());
 	      if (! pwd)
 		{
-		  fprintf (stderr, "%s: Who are you?\n", progname);
+		  fprintf (stderr, gettext("%s: Who are you?\n"), progname);
 		  exit (1);
 		}
 	      user = pwd->pw_name;
@@ -239,13 +253,13 @@
 	}
     }
   else if (z)
-    puts ("Nothing happens here.");
+    puts (gettext("Nothing happens here."));
   else
     {
       if (t)
-        printf ("hello, world\n");
+        printf (gettext("hello, world\n"));
       else
-        puts ("Hello, world!");
+        puts (gettext("Hello, world!"));
     }
 
   exit (0);
@@ -260,7 +274,7 @@
   char *ptr = malloc (size);
   if (! ptr)
     {
-      fprintf (stderr, "%s: virtual memory exhausted\n", progname);
+      fprintf (stderr, gettext("%s: virtual memory exhausted\n"), progname);
       exit (1);
     }
   return ptr;
</verb>
</tscreen>
PIE LISTADO 1: Modificaciones realizadas al código de hello.c para internacionalización

LISTADO 2
<tscreen>
<verb>
# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR Free Software Foundation, Inc.
# FIRST AUTHOR &gt;EMAIL@ADDRESS&lt;, YEAR.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2001-06-10 19:29+0200\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME &gt;EMAIL@ADDRESS&lt;\n"
"Language-Team: LANGUAGE &gt;LL@li.org&lt;\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: ENCODING\n"

#: hello.c:88
#, c-format
msgid "Usage: %s [-htvm] [--help] [--traditional] [--version] [--mail]\n"
msgstr ""

#: hello.c:153
msgid "This is GNU Hello, THE greeting printing program.\n"
msgstr ""

#: hello.c:156
msgid "  -h, --help\t\t\tPrint a summary of the options\n"
msgstr ""

#: hello.c:157
msgid "  -t, --traditional\t\tUse traditional greeting format\n"
msgstr ""

#: hello.c:160
msgid "  -v, --version\t\t\tPrint the version number\n"
msgstr ""

#: hello.c:161
msgid "  -m, --mail\t\t\tPrint your mail\n"
msgstr ""

#: hello.c:194
#, c-format
msgid "%s: Who are you?\n"
msgstr ""

#: hello.c:256
msgid "Nothing happens here."
msgstr ""

#: hello.c:260
msgid "hello, world\n"
msgstr ""

#: hello.c:262
msgid "Hello, world!"
msgstr ""

#: hello.c:277
#, c-format
msgid "%s: virtual memory exhausted\n"
msgstr ""
</verb>
</tscreen>

PIE LISTADO 2: Fichero po de hello.c
<!-- LISTADO x-


PIE LISTADO x: -->


<sect>Capturas
<p>Figura 1: El proceso completo de internacionalización con gettext


<sect>Notas de maquetación
<p>

<sect>Notas de coordinación
<p>

</article>
