Esta sección describe cómo implementar el soporte de idioma nativo en un programa o biblioteca que forma parte de la distribución de PostgreSQL. Actualmente, solo se aplica a programas en C.
Cómo añadir soporte NLS a un programa
Inserta este código en la secuencia de inicio del programa:
#ifdef ENABLE_NLS
#include <locale.h>
#endif
...
#ifdef ENABLE_NLS
setlocale(LC_ALL, "");
bindtextdomain("nombre_programa", LOCALEDIR);
textdomain("nombre_programa");
#endif
(El nombre_programa en realidad se puede elegir libremente).
Dondequiera que se encuentre un mensaje que sea candidato para traducción,
se debe insertar una llamada a gettext(). Por ejemplo:
fprintf(stderr, "panic level %d\n", lvl);
se cambiaría a:
fprintf(stderr, gettext("panic level %d\n"), lvl);
(gettext se define como una operación sin efecto si el soporte NLS
no está configurado).
Esto suele añadir mucho ruido visual. Un atajo común es usar:
#define _(x) gettext(x)
Otra solución es factible si el programa realiza gran parte de su comunicación a través
de una o unas pocas funciones, como ereport() en el backend.
En ese caso, haces que esta función llame a gettext internamente
para todas las cadenas de entrada.
Añade un archivo nls.mk en el directorio con las fuentes
del programa. Este archivo se leerá como un makefile. Aquí se deben realizar las
siguientes asignaciones de variables:
CATALOG_NAME
El nombre del programa, tal como se proporciona en la llamada a
textdomain().
GETTEXT_FILES
Lista de archivos que contienen cadenas traducibles, es decir, aquellos
marcados con gettext o una solución alternativa.
Con el tiempo, esto incluirá casi todos los archivos fuente del programa.
Si esta lista se vuelve demasiado larga, puedes hacer que el primer
“archivo” sea un + y la segunda palabra
sea un archivo que contenga un nombre de archivo por línea.
GETTEXT_TRIGGERS
Las herramientas que generan catálogos de mensajes para que trabajen los
traductores necesitan saber qué llamadas a funciones contienen cadenas
traducibles. Por defecto, solo se conocen las llamadas a
gettext(). Si utilizas _ u otros
identificadores, debes enumerarlos aquí. Si la cadena traducible no es el primer
argumento, el elemento debe tener la forma func:2 (para el
segundo argumento). Si tienes una función que admite mensajes en plural, el
elemento debe verse como func:1,2 (identificando los argumentos
de mensaje en singular y plural).
Añade un archivo po/LINGUAS, que contendrá la lista de
traducciones proporcionadas; inicialmente estará vacío.
El sistema de construcción se encargará automáticamente de compilar e instalar los catálogos de mensajes.
Aquí tienes algunas directrices para escribir mensajes que sean fáciles de traducir.
No construyas oraciones en tiempo de ejecución, como:
printf("Files were %s.\n", flag ? "copied" : "removed");
El orden de las palabras dentro de la oración puede ser diferente en otros idiomas.
Además, incluso si recuerdas llamar a gettext() en cada
fragmento, es posible que los fragmentos no se traduzcan bien por separado. Es mejor
duplicar un poco de código para que cada mensaje a traducir sea un todo coherente.
Solo los números, nombres de archivos y variables similares en tiempo de ejecución
deben insertarse en tiempo de ejecución en el texto de un mensaje.
Por razones similares, esto no funcionará:
printf("copied %d file%s", n, n!=1 ? "s" : "");
porque asume cómo se forma el plural. Si pensabas que podías solucionarlo de esta manera:
if (n==1)
printf("copied 1 file");
else
printf("copied %d files", n):
entonces te llevarás una decepción. Algunos idiomas tienen más de dos formas, con algunas reglas peculiares. A menudo es mejor diseñar el mensaje para evitar el problema por completo, por ejemplo de esta manera:
printf("number of copied files: %d", n);
Si realmente quieres construir un mensaje correctamente pluralizado, existe soporte
para esto, pero es un poco complejo. Al generar un mensaje de error principal o de
detalle en ereport(), puedes escribir algo como esto:
errmsg_plural("copied %d file",
"copied %d files",
n,
n)
El primer argumento es la cadena de formato adecuada para la forma singular en inglés,
el segundo es la cadena de formato adecuada para la forma plural en inglés, y el
tercero es el valor de control entero que determina qué forma de plural usar. Los
argumentos siguientes se formatean según la cadena de formato como de costumbre.
(Normalmente, el valor de control de pluralización también será uno de los valores a
formatear, por lo que tiene que escribirse dos veces). En inglés solo importa si
n es 1 o no es 1, pero en otros idiomas puede haber muchas
formas de plural diferentes. El traductor ve las dos formas en inglés como un grupo y
tiene la oportunidad de proporcionar múltiples cadenas sustitutas, seleccionándose la
adecuada en función del valor en tiempo de ejecución de n.
Si necesitas pluralizar un mensaje que no va directamente a un informe
errmsg o errdetail, tienes que usar la
función subyacente ngettext. Consulta la documentación de gettext.
Si quieres comunicar algo al traductor, como por ejemplo sobre cómo se pretende que
se alinee un mensaje con otra salida, precede la aparición de la cadena con un comentario
que comience con translator, por ejemplo:
/* translator: This message is not what it seems to be. */
Estos comentarios se copian a los archivos de catálogo de mensajes para que los traductores puedan verlos.