i18n
Soporte de internacionalización (i18n) y localización (i10n) en adJ
Comparación con OpenBSD
- Desde adJ 5.5 la librería de C soporta formatos para fecha y hora
particulares para cada país (categoria
LC_TIME
del locale) y tablas para todos los países de latinoamérica y otros soportados por OpenBSD. También soporta xlocale completo. La mejora deLC_TIME
se aportó a OpenBSD desde que preparaba la versión 5.6, pero no ha sido integrada. - Desde adJ 5.4 la librería de C soporta formatos numéricos particulares de
cada país (categoria
LC_NUMERIC
del locale) y tablas para todos los países de latinoamérica y otros soportados por OpenBSD. También soporta las funciones de xlocale relacionadas. Esta mejora se aportó a OpenBSD desde que preparaba la versión 5.5, pero no ha sido integrada. - Desde adJ 5.4 la librería de C soporta cantidades monetarias particulares
de cada país (categoria
LC_MONETARY
del locale) y tablas para todos los países de latinoamérica y otros soportados por OpenBSD. También soporta las funciones de xlocale relacionadas. Esta mejora se aportó a OpenBSD desde cuando se preparaba la versión 5.5, pero no ha sido integrada. - Desde adJ 5.2 la librería de C soporta cotejación (collation o categoria
LC_COLLATE
) o ordenamiento alfabético en el idioma nativo con base en la implementación de FreeBSD, así como el programacolldef
para generar tablas de cotejación. Esta mejora se ha aportado a OpenBSD y se espera que en futuras versiones la integre (desde OpenBSD 5.3 no la incluyen aunque ayudamos desde esa versión y algunas posteriores para que las incluyeran).
Agradecemos una revisión para OpenBSD por parte de Stephan Sperling –todas sus sugerencias se incluyeron desde adJ 5.3. - Desde adJ 5.5 implementa todas las funciones del API xlocale para la librería de C. Esta mejora se ha aportado a cada versión que se prepara de OpenBSD.
- Desde adJ 5.2 en las funciones
strcasecmp
ywcscasecmp
emplea la categoriaLC_CTYPE
del locale actual (como POSIX 2008 lo requiere aunque de forma ambigua), por lo que operan mejor para español y otros idiomas diferente al inglés –por ejemplo ñ y Ñ con estas funciones son equivalentes en adJ 5.2 mientras que no lo son en OpenBSD 5.4. Agradecemos una revisión por parte de Stephan Sperling y Matthew Dempsky, desarrolladores de OpenBSD. - Desde adJ 5.2 replica el locale (identificaciones culturales y de idioma
para un área geográfica) para España de OpenBSD y la tabla de cotejación
para España de FreeBSD para todos los paises de Latinoamérica y de habla
hispana. Esta mejora se aportó a OpenBSD y generó expectativa de la
comunidad que trajo solución en OpenBSD 5.4 (con especial atención a paises
hispanohablantes en la utilidad
locale
). - Desde adJ 5.2 está configurado por defecto para emplear el locale
es_CO.UTF-8
y la zona horaria America/Bogota, e incluye zonas horarias más recientes. - Desde adJ 5.2 incluye un porte de PostgreSQL que soporta cotejaciones en idioma nativo, con este por ejemplo sus consultas a la base de datos ordenando por nombre podrán estar ordenadas en español (y no con las palabras que comienzan con tilde o ñ al final que ocurre si usa cotejación en inglés). Esta mejora podrá aportarse al porte oficial una vez OpenBSD incluya cotejación (podría ser en 5.6 o posterior).
- Desde adJ 5.2 incluye un porte de xfe modificado para soportar cotejación en el idioma nativo (y mostrar listados de archivos en el orden correcto de acuerdo al locale), así como una nueva traducción a es_CO. Esta mejora se ha aportado a xfe y fue integrada en 1.37.
- Desde adJ 5.3 incluye tablas ctype actualizadas de NetBSD para varios locales (incluyendo los basados en UTF-8) –no ha sido posible la integración de esta mejora en OpenBSD propuesta desde que se preparaba la versión 5.4.
- Hemos aportados correcciones a fallas relacionadas con el locale a OpenBSD,
por ejemplo
!MB_CUR_MAX
en OpenBSD 5.4 (resuelta en adJ 5.3).
Comparación con FreeBSD
- La implementación de xlocale de FreeBSD es segura en programas con hilos –multi-thread–, esto debido a que la implementación de pthreads en OpenBSD no soporta _Thread_local.
- La implementación de xlocale en FreeBSD no soporta en strcoll ni en
strxfrm
codificaciones multibyte, mientras que la implementación en adJ 5.2 parcialmente (por ahora UTF-8 cuando se codifica ISO-8859-1). Esta mejora se aportó a OpenBSD desde que se preparaba la versión 5.4 - La implementación de cotejación basada en la de FreeBSD fue enviada y auditada en la lista de OpenBSD. Agradecemos a Stephan Sperling con cuya ayuda prácticamente se reescribió. adJ emplea las tablas de cotejación de FreeBSD, pero la de español es mejorada pues en FreeBSD la ñ y la n son equivalentes, mientras que en adJ la ñ está entre la n y la o.
- Desde adJ 5.2 se prepararon pruebas de regresión para las implementaciones
de LC_COLLATE y de
xlocale
, y desde adJ 5.4 para `LC_MONETARY y LC_NUMERIC. Esta mejora se aportó a OpenBSD desde que se preparaba la versión 5.4. - FreeBSD sólo incluye tablas con formatos monetarios, numéricos y de tiempo
para España pero no para los demás países de habla hispana.
En adJ hemos incluido estos datos para todos los paises de habla hispana con base en Unicode ( http://unicode.org/cldr/trac/browser/tags/release-1-9/posix/ ) , Wikipedia, glibc (particularmente el locale de Cuba que no está en POSIX), y hemos hecho consultas privadas a personas de otros paises y públicas en listas de correo de Internet. - En OpenBSD cada categoria para un locale de la forma
idioma_territorio.codificacion
(e.ges_CO.UTF-8
) se busca primero comoidioma_territorio.codificacion
, después comoidioma.codificación
y después comocodificacion
. En FreeBSD sólo se buscaidioma_territorio.codificacion
. Esto permite que adJ (y OpenBSD en el caso deLC_CTYPE
) tengan menos enlaces entre locales iguales y de valores por defecto más aproximados cuando no cuenta con datos de algún territorio o idioma. - FreeBSD incluye una extensión en
nl_langinfo
!D_MD_ORDER
que retorna"dm"
si en el locale el día va antes del mes o"md"
si primero va el mes. Para soportarla incluye en las tablas deLC_TIME
y en la estructuralc_time_T
de libc un campomd_order
que incluye esta cadena.
Consideramos que esto es redundante por cuanto las mismas tablas incluyenx_fmt
que para todo locale tiene%d
(o%e
) y%m
(o%b
) y el orden en el que aparecen definen si va primero el dia o el mes.
En esta lógica consideramos que hay errores en las tablas de FreeBSD parahe_IL.UTF-8.src
ylv_LV.UTF-8.src
que definenx_fmt
en%d/%m/%y
pero definenmd_order
enmd
. Aunque nos parece buena la extensión!D_MD_ORDER
ennl_langinfo
, para evitar redundancia y errores en adJ preferimos eliminar de las tablas deLC_TIME
el campomd_order
.
Otras Innovaciones
- Desde adJ 5.3 se incluyen las funciones
strcasecoll
,strcasecoll_l
,wcscasecoll
ywcscasecoll_l
para comparar con cotejación de acuerdo al locale e ignorando mayúsculas y minúsculas. Se trata de una extensión a POSIX 2008, incluida con otros nombres en otros sistemas operativos, aunque se propuso para OpenBSD no fue aceptada.
En adJ muchos programas populares (e.g. chrome
, pidgin
, libreoffice
)
emplean el locale que haya configurado para presentar información ordenada,
así que notará la diferencia. Por ejemplo en la captura de pantalla
siguiente puede ver el ordenamiento correcto en canales de Pidgin (note
primero á), en el diálogo para guardar una página de chrome (note la á
antes de la D) y en el PostgreSQL incluido en adJ 5.2 (note ACHÍ antes de
ACHIOTE). En las otras 2 terminales notará caracteres en griego en
vim y una forma fresca de ver el spam desde mutt :)
[http://aprendiendo.pasosdejesus.org/sites/APRENDIENDO.PASOSDEJESUS.ORG/spages/cotejaci%C3%B3n.png]
Así como se adaptó el porte de PostgreSQL, otros portes pueden requerir
activar el soporte de locale_t
, así mismo muchas utilidades del sistema
base (empezando por ls
) aún no emplean las funciones de cotejación.
Puede ayudar aportando parches para las fuentes y dialogando en
https://groups.google.com/forum/?fromgroups#!forum/OpenBSD-Colombia
Resumen del Uso
Un locale define una codificación y formas de presentar información
típicas de una región geográfica (números, valores monetarios, fechas,
horas, idioma y cotejación u ordenamiento lexicográfico del mismo).
adJ viene configurado por defecto con el locale es-CO.UTF-8
es decir en
español, para Colombia y con codificación UTF-8.
Puede examinar otros locales con
% locale -a
Los paises iberoaméricanos y sus respectivos locale que opera en adJ son (en lugar de UTF-8 también puede usar ISO-8859-1 e ISO-8859-15).
País | locale |
Argentina | es_AR.UTF-8 |
Brazil | pt_BR.UTF-8 |
Bolivia | es_BO.UTF-8 |
Chile | es_CL.UTF-8 |
Colombia | es_CO.UTF-8 |
Costa Rica | es_CR.UTF-8 |
Ecuador | es_EC.UTF-8 |
El Salvador | es_SV.UTF-8 |
España | es_ES.UTF-8 |
Guinea Ecuatorial | es_GQ.UTF-8 |
Guatemala | es_GT.UTF-8 |
Hispanohablantes de Estados Unidos | es_US.UTF-8 |
Honduras | es_HN.UTF-8 |
México | es_MX.UTF-8 |
Nicaragua | es_NI.UTF-8 |
Panama | es_PA.UTF-8 |
Perú | es_PE.UTF-8 |
Puerto Rico | es_PR.UTF-8 |
Paraguay | es_PY.UTF-8 |
República Dominicana | es_DO.UTF-8 |
Uruguay | es_UY.UTF-8 |
Venezuela | es_VE.UTF-8 |
En UTF-8 puede codificarse UNICODE, que a su vez permite representar todos los
lenguajes escritos –la mayoría de lenguajes occidentales, incluyendo el
español, también puede codificarse con ISO8859-1, ISO8859-15 (con euro).
Elija el locale más apropiado para su país. Recomendamos que emplee
codificación UTF-8 y que establezca el locale en sus archivos
~/.fluxbox/startup
y ~/.profile
agregando o cambiando la línea:
export LANG=es_CO.UTF-8
Los programas estándares emplearan esta variable (y otras asociadas) para determinar el locale y modificaran la forma de presentar:
- Los mensajes, menús y ayudas para que sean en su idioma.
En adJ esto se soporta via el portegettext
. - La codificación de caracteres para que sea la que prefiere.
En adJ se emplea el soporte de
LC_CTYPE
de OpenBSD que entre otros es suficiente para ISO-8859-1/15 y UTF-8. - Los ordenamientos alfabéticos serán apropiados para su idioma (por ejemplo
en español la
á
lexicograficamente equivale a laa
, y lañ
está entre lan
y lao
). En adJ se emplea una implementación mejorada sobre la de FreeBSD que es suficiente para el español en codificaciones ISO-8859-1, ISO-8859-15 y UTF-8 (aunque no basta para otros lenguajes soportados por UNICODE). - La forma de presentar números será la particular de la región geográfica elegida. Por ejemplo el número 1000000.2 de acuerdo al país se presenta así:
Países | Número |
Argentina, Bolivia, Brazil, Chile, Colombia, Ecuador, España, Guatemala, Honduras, Nicaragua, Panama, Paraguay, Peru, Republica Dominicana, Uruguay, Venezuela | 1.000.000,2 |
Costa Rica, El Salvador, Honduras, México, Puerto Rico e hispanohablantes de Estados Unidos | 1,000,000.2 |
Cuba | 1 000 000,2 |
- Los valores monetarios se presentan con las convenciones de la categoría
LC_MONETARY
del locale desde adJ 5.4. Por ejemplo el número -3456.78 como cantidad monetaria en cada locale de iberoamérica es:
locale | Cantidad | Observaciones |
es_AR | -$ 3.456,78 | |
es_BO | -$b 3.456,78 | |
es_CL | -$ 3.456,78 | |
es_CO | -$ 3.456,78 | |
es_CR | -₡ 3 456,78 | Con ISO8859-1 se usa ¢ en lugar de ₡ |
es_DO | -RD$ 3,456.78 | |
es_EC | -$ 3.456,78 | |
es_ES | -3.456,78 € | Con ISO8859-1 se usa Eu en lugar de € |
es_GQ | -FCFA 3.457 | |
es_GT | -Q 3,456.78 | |
es_HN | -L 3,456.78 | |
es_MX | -$ 3,456.78 | |
es_NI | -C$ 3,456.78 | |
es_PA | -B/. 3,456.78 | |
es_PE | -S/. 3,456.78 | |
es_PR | -$ 3,456.78 | |
es_PY | -Gs 3.456,78 | |
es_SV | -US$ 3,456.78 | |
es_UY | -$ 3.456,78 | |
es_US | -$3,456.78 | |
es_VE | -Bs 3.456,78 | |
pt_BR | -R$3.456,78 |
- También la forma de presentar fecha y hora se ve afectada por el locale así
como por la zona horaria. La zona horaria se establece enlazando
/etc/localtime
con una de las zonas del directorio/usr/share/zoneinfo
, en adJ se establece por defecto enAmerica/Bogota
. El formato de fecha presentado por el comandodate
varía al cambiar el locale –aunque es común para todos los países de habla hispana:
locale | date |
es | mié oct 1 18:17:34 COT 2014 |
pt_BR | Qua Out 1 18:18:54 COT 2014 |
zh | 三 10 1 18:19:38 COT 2014 |
ja | 水 10月 1 18:20:25 COT 2014 |
ru | ср окт 1 18:20:45 COT 2014 |
he | ד’ אוק 1 18:21:11 COT 2014 |
xterm
Puede iniciar una terminal que soporte codificación UTF-8 y que lea la
configuración de .profile
con:
xterm -en utf8 -e /bin/ksh -l
tmux
Soporta la codificación de la terminal.
vim
Puede establecerse el idioma de los mensajes que vim presenta con el comando
:language
, por ejemplo para establecer español de Colombia:
:language es_CO
Puede establecer esta configuración por defecto agregando el comando al
archivo ~/.vimrc
.
vim
puede emplear codificaciones diferentes para la terminal y para los
archivos, ambos se establecen con la variable encoding
(o enc
) y cada
uno en particular con termencoding
(o tenc
) y fileencoding
(o fenc
).
La forma recomendada es hacer que vim emplee la variable de ambiente
LANG
(o LC_ALL
y los tipos particulares), agregando esta configuración a
su archivo ~/.vimrc
:
set encoding& " terminal charset: follows current locale but still not working so:
set termencoding=
set fileencodings= " charset auto-sensing: disabled
set fileencoding& " auto-sensed charset of current buffer
mutt
Si la terminal lo soporta, mutt
puede emplear codificación UTF-8, y
enviar correos con esta codificación, agregando las siguientes líneas a
su archivo ~/.muttrc
(que se espera codificado en UTF-8):
set config_charset=utf-8
set locale=es_CO.UTF-8
my_hdr Content-Type: text/plain\; charset=UTF-8\; format=flowed
my_hdr Content-Transfer-Encoding: 8bit
PostgreSQL
En la versión 9.1, puede examinar las cotejaciones disponibles ingresando al interprete psql
y ejecutando:
SELECT * FROM pg_collation;
Puede crear una cotejación (digamos es_co_utf_8
pues deben ser nombres en
minúsculas) para un locale soportado por el sistema operativo (digamos
es_CO.UTF-8
) con:
CREATE COLLATION es_co_utf_8 (LOCALE='es_CO.UTF-8');
Una vez creada puede realizar operaciones empleándola por ejemplo:
SELECT 'Á' < 'B' COLLATE "es_co_utf_8";
?column?
----------
t
(1 row)
...
SELECT nombre FROM clase ORDER BY nombre COLLATE "es_co_utf_8";
...
Puede crear columnas de tablas especificando el tipo de cotejación por defecto para operaciones con esa columna.
CREATE TABLE ejc (
nombre VARCHAR(100) COLLATE "es_co_utf_8"
);
o cambiar las existentes:
ALTER TABLE clase ALTER nombre TYPE VARCHAR(500) COLLATE "es_co_utf_8";
También podrá renombrar cotejaciones que haya creado asi como borrarlas, ver más en http://www.postgresql.org/docs/9.1/static/collation.html
Variables de entorno relacionadas con el locale
El locale consta de varias categorias, todas ellas se establecen en conjunto
con la variable de entorno LANG
o bien con LC_ALL
. Puede establecer unas
particulares con:
LC_MESSAGE
idioma y codificación de mensajes, menús y en general todo escrito que un programa presente al usuarioLC_NUMERIC
valores numéricosLC_MONETARY
valores monetariosLC_COLLATE
cotejamientoLC_CTYPE
Codificación y clasificación (e.g minúsuclas, mayúsculas)LC_TIME
hora y fecha
En lenguaje de programación C
LC_NUMERIC
: La bandera ‘ de la función printf
presentará valores numéricos
de acuerdo a la categoria LC_NUMERIC del locale. Por ejemplo
setlocale(LC_ALL, "es_CO.UTF-8");
printf("%'f", 1000000.2)
Establece todas las categorias de locale, incluyendo LC_NUMERIC
en
es_CO.UTF-8
e imprime el número como: 1.000.000,200000
.
Puede examinar el locale numérico con la función localeconv
y nl_langinfo
.
LC_MONETARY
: La función strfmon
dará formato a un número como cantidad
monetaria de acuerdo a la categoria LC_MONETARY
del locale. Por ejemplo
llamando el siguiente programa como ejfmon.c
:
#include <locale.h>
#include <monetary.h>
#include <stdio.h>
int main() {
char col![512];
setlocale(LC_ALL, "es_CO.UTF-8");
strfmon(col, sizeof(col), "%n", -3456.781);
printf("%s\n", col);
return 0;
}
Y compilando con
% cc -o ejfmon ejfmon.c
Al ejecutarlo con ./ejfmon
establecerá todas las categorias de locales,
incluyendo LC_MONETARY
, en es_CO.UTF-8
e imprimirá -$ 3.456,78
.
Puede examinar el locale monetario con la función localeconv
.
LC_TIME
: define como la función date
interpreta sus especificadores de
conversión, así como la operación de las funciones strftime
, wcsftime
,
strptime
y nl_langinfo
.
Su operación puede verificarse con el comando date
.