domingo, 5 de noviembre de 2017

Internacionalización del código (y II)




Programas multilingües con gettext


El módulo gettext permite que un mismo programa Python pueda estar disponible en varios idiomas, es decir, favorece la internacionalización del código. Este módulo proporciona una implementación de Python compatible con la biblioteca GNU gettext que facilita la traducción de los mensajes de un programa y la gestión de los catálogos que contienen las traducciones.

Afortunadamente, existen herramientas de Python y de otras fuentes que permiten extraer los mensajes a traducir de los programas, crear los catálogos de traducciones y utilizar dichos catálogos durante la ejecución de un programa para mostrar los mensajes en el idioma de preferencia del usuario.


Construir un programa con sus mensajes traducidos a varios idiomas


1) Identificar los mensajes a traducir


La función _() se utiliza para identificar en el código fuente las cadenas de los mensajes a traducir durante la ejecución de un programa.

programa.py:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#

import gettext

idiomas = []

# Configurar el acceso al catálogo de mensajes
t = gettext.translation('programa', 
                        'locale', 
                        languages=idiomas,
                        fallback=True,)
_ = t.gettext

print(_('Ejecutando programa...'))
print(_('El programa ha finalizado correctamente.'))

Los textos que se incluyan en las funciones _() serán los mensajes a sustituir por los equivalentes en el idioma deseado, que se obtendrán del catálogo siempre que éste esté disponible. Si no existe el catálogo se imprimirá el mensaje original:

$ python3 programa.py

Ejecutando programa... 
El programa ha finalizado correctamente.


2) Crear una plantilla de traducción


Una plantilla de traducción es un archivo con la extensión .pot que se genera a partir de un programa fuente Python (.py). Consta de una cabecera con información relativa a su contenido y la recopilación de todos los mensajes a traducir del fuente, en crudo.

Una plantilla se utiliza para crear un archivo con las traducciones para un determinado idioma. Los archivos que se van creando con las traducciones compiladas en distintos idiomas que son leídos en tiempo de ejecución se denominan catálogos.

Para crear una plantilla se puede utilizar el script pygettext.py que proporciona Python, la herramienta xgettext de GNU, la aplicación Poedit de Václav Slavík o las utilidades po-utils de François Pinard, entre otros.

Ubuntu

En Ubuntu para crear la plantilla de traducción de programa.py, ejecutar:

$ pygettext -d programa programa.py

o bien,

$ xgettext -o programa.pot programa.py

Recuerda: con el comando which podemos ver la ubicación de estas herramientas en el sistema, si están instaladas.

$ which pygettext
/usr/bin/pygettext

$ which xgettext
/usr/bin/xgettext

Windows

En Windows para crear la plantilla con el script pygettext.py, ejecutar:

c:\> python3 pygettext.py -d programa programa.py


Examinando un archivo .pot

Una vez creado el archivo de plantilla .pot se puede examinar su contenido con un editor de textos. En el ejemplo siguiente podemos observar que después de las líneas comentadas del comienzo se sitúa la información de la cabecera, a las que siguen después las líneas con los mensajes de texto a traducir.

programa.pot:

# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR , YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: PACKAGE VERSION\n"
"POT-Creation-Date: 2017-11-02 13:27+CET\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME \n"
"Language-Team: LANGUAGE \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=CHARSET\n"
"Content-Transfer-Encoding: ENCODING\n"
"Generated-By: pygettext.py 1.5\n"


#: programa.py:13
msgid "Ejecutando programa..."
msgstr ""

#: programa.py:14
msgid "El programa ha finalizado correctamente."
msgstr ""


3) Traducir y compilar los mensajes


Para que el programa programa.py, además de en castellano/español, esté disponible en inglés y francés tendremos que crear dos copias de la plantilla .pot, una para cada idioma e incluir, en cada una de ellas, las traducciones correspondientes.

Cada copia de la plantilla se guardará cambiándole la extensión a .po en una carpeta dentro de una estructura de carpetas que sigue un orden preestablecido; en la que los archivos se organizan, básicamente, en carpetas de idiomas y por dominios. El dominio identifica las traducciones específicas de un programa. Por ello, suele tener la misma denominación. Una carpeta de un idioma concreto contiene las traducciones disponibles en ese idioma de múltiples programas multilingües.

Parar crear la estructura de carpetas necesaria al mismo nivel de los archivos .py y .pot y copiar las dos copias de la plantilla (para inglés de EE.UU. y francés de Francia), seguir los siguientes pasos:

Ubuntu

mkdir locale
mkdir locale/en_US
mkdir locale/en_US/LC_MESSAGES
mkdir locale/fr_FR
mkdir locale/fr_FR/LC_MESSAGES
cp programa.pot locale/en_US/LC_MESSAGES/programa.po
cp programa.pot locale/fr_FR/LC_MESSAGES/programa.po

Windows

md locale
md locale\en_US
md locale\en_US\LC_MESSAGES
md locale\fr_FR
md locale\fr_FR\LC_MESSAGES
copy programa.pot locale\en_US\LC_MESSAGES\programa.po
copy programa.pot locale\fr_FR\LC_MESSAGES\programa.po

A continuación, abrir con un editor de textos el archivo locale/en_US/LC_MESSAGES/programa.po que contendrá las traducciones en inglés. Después, completar la información de la cabecera e insertar los mensajes de texto traducidos entre las comillas en cada línea donde aparece msgstr (se encuentran debajo de cada mensaje de texto original). Una vez incorporadas las traducciones, guardar y repetir estos últimos pasos con el archivo locale/fr_FR/LC_MESSAGES/programa.po que contendrá las traducciones en francés.

Para las traducciones, si lo precisamos, utilizar un traductor como el de Google.

Al finalizar, la edición de los archivos .po su contenido debe parecerse a:

Traducciones en inglés en locale/en_US/LC_MESSAGES/programa.po:

# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR , YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: programa 1\n"
"POT-Creation-Date: 2017-11-02 13:27+CET\n"
"PO-Revision-Date: 2017-11-02 13:27+CET\n"
"Last-Translator: Python para impacientes \n"
"Language-Team: US English \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8-bit\n"
"Generated-By: pygettext.py 1.5\n"


#: programa.py:13
msgid "Ejecutando programa..."
msgstr "Running program..."

#: programa.py:14
msgid "El programa ha finalizado correctamente."
msgstr "The program has finished correctly."

Traducciones en francés en locale/fr_FR/LC_MESSAGES/programa.po:

# SOME DESCRIPTIVE TITLE.
# Copyright (C) YEAR ORGANIZATION
# FIRST AUTHOR , YEAR.
#
msgid ""
msgstr ""
"Project-Id-Version: programa 1\n"
"POT-Creation-Date: 2017-11-02 13:27+CET\n"
"PO-Revision-Date: 2017-11-02 13:27+CET\n"
"Last-Translator: Python para impacientes \n"
"Language-Team: FR French \n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=UTF-8\n"
"Content-Transfer-Encoding: 8-bit\n"
"Generated-By: pygettext.py 1.5\n"


#: programa.py:13
msgid "Ejecutando programa..."
msgstr "Programme en cours..."

#: programa.py:14
msgid "El programa ha finalizado correctamente."
msgstr "Le programme a bien fini."

El dominio es proporcionado por la aplicación o biblioteca y, generalmente, es un valor único que coincide con el nombre de la aplicación o biblioteca. En este caso, el dominio de programa.py es 'programa' porque en el código fuente así se establece en la siguiente línea:

t = gettext.translation('programa', 
                        'locale', 
                        languages=idiomas,
                        fallback=True,)

Por otro lado, el directorio de dicho dominio es 'locale', y aunque en el ejemplo lo hemos creado al mismo nivel que programa.py, lo recomendado es utilizar un directorio único accesible en el sistema para que todos los usuarios tengan disponibles los mismos catálogos de traducciones (Si no se proporciona el directorio del dominio se utilizará el directorio predetermnado del sistema). En Ubuntu, lo aconsejable es utilizar la ubicación: /usr/share/locale. Si accedemos a dicha ruta reconoceremos que la estructura de carpetas nos resulta familiar:


El valor del idioma lo proporciona el entorno del usuario en tiempo de ejecución a través de una de las variables de entorno LANGUAGE, LC_ALL, LC_MESSAGES o LANG, según configuración y plataforma. Su valor podría ser "es", "es_ES", "es_ES.UTF-8", "fr_FR", "en_US", etc. Nótese que hay lenguas como el español/castellano con sus variantes por países que para poder recoger en las traducciones las peculiaridades de cada uno de ellos se identifican de forma diferente: "es_ES" (Español de España), "es_AR" (Español de Argentina), "es_MX" (Español de México), etc.

Con los archivos .po terminados el siguiente paso es compilarlos, uno a uno, para crear los catálogos .mo, que son la versión legible por el módulo gettext.

Ubuntu

Para compilar, ejecutar:

cd locale/en_US/LC_MESSAGES
msgfmt -o programa.mo programa.po
cd ../../..
cd locale/fr_FR/LC_MESSAGES
msgfmt -o programa.mo programa.po
cd ../../..

Recuerda: con el comando which podemos ver la ubicación de esta herramienta, si está instalada.

$ which msgfmt /usr/bin/msgfmt

Windows

Para compilar con el script msgfmt.py (), ejecutar:

c:\> python3 msgfmt.py -o programa.mo programa.po


Traducir y compilar con Poedit

Para que todo sea más fácil podemos instalar la aplicación Poedit para traducir los mensajes automáticamente y compilar los catálogos.

Una vez instalado el programa, ejecutar y seguir los siguientes pasos:

1. Seleccionar el archivo programa.pot a generar en el Menú Archivo, Nuevo desde archivo / PO POT:


2. Seleccionar el idioma al que se van a traducir los mensajes:



3. Completar las traducciones seleccionado la sugerencia de traducción más idónea:



4. Para finalizar, guardar el archivo y la aplicación creará los archivos programa.po y programa.mo.


4) Cargar y usar el catálogo de mensajes apropiado


El último paso consiste en modificar el programa para que cargue y utilice el catálogo de mensajes de un idioma determinado:

Para cargar/usar el catálogo de inglés de Estados Unidos:

programa.py:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#

import gettext

idiomas = ['en_US']

# Configurar el acceso al catálogo de mensajes
t = gettext.translation('programa', 
                        'locale', 
                        languages=idiomas,
                        fallback=True,)
_ = t.gettext

print(_('Ejecutando programa...'))
print(_('El programa ha finalizado correctamente.'))

Ejecutar para comprobar el resultado:

$ python3 programa.py Running program... The program has finished correctly.

Para cargar/usar el catálogo de francés de Francia:

programa.py:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#

import gettext

idiomas = ['fr_FR']

# Configurar el acceso al catálogo de mensajes
t = gettext.translation('programa', 
                        'locale', 
                        languages=idiomas,
                        fallback=True,)
_ = t.gettext

print(_('Ejecutando programa...'))
print(_('El programa ha finalizado correctamente.'))

Ejecutar para comprobar el resultado:

$ python3 programa.py

Programme en cours... 
Le programme a bien fini.

Si se establece un idioma para el que no existe catálogo se obtendrá la salida en el lenguaje original.


Conocer la disponibilidad y usar catálogos


Con el método find() es posible conocer si uno o más catálogos de una lista están disponibles para un determinado programa. Con la función translation() quedará habilitado el primero de la lista que esté disponible; y asignando a la variable "_" la función lambda (retornando la misma cadena de entrada) se puede volver al idioma orignal del programa.

Utilizando install() en el archivo principal de una aplicación se instala globalmente la función _() en su espacio de nombres, permitiendo que todos los archivos de la aplicación puedan utilizar dicha función sin tener que "instalar" explicitamente en cada archivo:

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#

import gettext

idiomas = ['fr_CA', 'fr_FR']
catalogos = gettext.find('programa',
                         'locale',
                         languages=idiomas,
                         all=True)
print('Catálogo/s:', catalogos)

if catalogos:
    t = gettext.translation('programa', 'locale', languages=idiomas)
    t.install()
    print(_('Ejecutando programa...'))

_ = lambda a: a

print(_('El programa ha finalizado correctamente.'))

Al ejecutar el programa anterior obtendremos una salida que muestra la ubicación del catálogo disponible (francés de Francia), imprimiéndose el primer mensaje en dicho idioma. Después, se deshabilitará para volver al idioma original:

Catálogo/s: ['locale/fr_FR/LC_MESSAGES/programa.mo'] 
Programme en cours... 
El programa ha finalizado correctamente.


Usar el catálogo del entorno del usuario


En el siguiente ejemplo se carga y usa el catálogo del entorno del usuario, siempre que esté disponible. Em caso contrario se mostrarán los mensajes en el idioma original.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#

import gettext, locale

entorno_usu = locale.setlocale(locale.LC_ALL, '')
idiomas = [entorno_usu]

print('Entorno de Usuario:', entorno_usu)

# Configurar el acceso al catálogo de mensajes
t = gettext.translation('programa', 
                        'locale', 
                        languages=idiomas,
                        fallback=True,)
_ = t.gettext

print(_('Ejecutando programa...'))
print(_('El programa ha finalizado correctamente.'))


Usar el catálogo preferido de una lista de catálogos


En el siguiente ejemplo se prefiere cargar y usar el catálogo de francés de Canadá 'fr_CA' si existe (que no es el caso); o en otro caso el de francés de Francia 'fr_FR'. Si ninguno de los dos existieran los mensajes se mostrarían en el idioma original.

Se ofrecen dos versiones: en la primera se utiliza install() y en la siguiente, no.

Con install()


import gettext

idiomas = ['fr_CA', 'fr_FR']
gettext.install('programa', 'locale')
catalogos = gettext.find('programa', 
                         'locale',
                         languages=idiomas,
                         all=True)

if catalogos:
    t = gettext.translation('programa', 'locale', languages=idiomas)
    t.install()

print(_('Ejecutando programa...'))
print(_('El programa ha finalizado correctamente.'))



Sin install()


import gettext

idiomas = ['fr_CA', 'fr_FR']

# Configurar el acceso al catálogo de mensajes
t = gettext.translation('programa', 'locale', languages=idiomas,
    fallback=True,
)
_ = t.gettext

print(_('Ejecutando programa...'))
print(_('El programa ha finalizado correctamente.'))



Ir al índice del tutorial de Python

miércoles, 26 de abril de 2017

Internacionalización del código (I)

El módulo locale


Cuando se instala un sistema operativo una de las primeras opciones de configuración que se decide es la localización geográfica del equipo o dispositivo. Normalmente, el idioma del sistema operativo se corresponderá con el país seleccionado y dicha elección será también empleada para fijar una serie de convenciones que definen para ese lugar el modo de expresar los números, las cantidades monetarias, los números positivos y negativos, las fechas y horas, etc.

Estas convenciones establecen, entre otros, el carácter que se utiliza en los números para separar la parte entera de la decimal (",", ".", etc.); el carácter que se usa como separador de millares (".", ",", etc.), el símbolo monetario (€, £, $, ¥, etc.), el formato de las fechas y horas, etc.

Afortunadamente, estas definiciones pueden ser utilizadas (y cambiadas) por una aplicación para adaptar la forma en que presentan sus datos a cada territorio. Particularmente, en Python ese es el cometido principal que tiene el módulo locale, incluido en la librería estándar como parte del soporte que ofrece el lenguaje a la internacionalización de las aplicaciones.

Herramienta de Configuración Regional y de Idioma

Hoy, los distintos sistemas operativos proporcionan herramientas gráficas que permiten modificar de forma fácil las opciones comentadas. En Windows se utiliza la herramienta de "Configuración Regional y de Idioma" y en GNU/Linux ésta, a veces, se denomina de igual forma (como en Ubuntu GNOME) o puede estar integrada en otra herramienta como la de "Soporte de Idiomas" (como sucede en Xubuntu).

Configuración Regional en Registro de Windows
 
Según sea el caso, en Windows las definiciones vigentes del entorno de un usuario son almacenadas en el Registro de Windows (en la rama "HKEY_CURRENT_USER\Control Panel\International") y en un sistema GNU/Linux en los archivos donde se declaran las variables de entorno (LC_ALL, LC_CTYPE, LANG, LANGUAGE) que son ejecutados al iniciar un equipo. Cada plataforma tiene sus propios mecanismos.

En GNU/Linux para consultar desde la línea de comandos las variables de entorno utilizar los comandos env o printenv. En Windows, el comando systeminfo muestra información básica de la configuración regional.


Obtener/establecer la configuración regional: setlocate()


La función setlocate() devuelve o establece la configuración regional del entorno de un usuario. El argumento category representa una categoría determinada de configuración (una categoría agrupa un conjunto de definiciones de configuración). Y locale es una cadena que representa el idioma de una localización geográfica determinada:

locale.setlocale(category, locale=None)

Las definiciones de configuración se agrupan en las siguientes categorías:
  • locale.LC_ALL: combinación de todas las categorias.
  • locale.LC_NUMERIC: formatos de números.
  • locale.LC_TIME: formatos de fechas/horas.
  • locale.LC_MONETARY: formatos de valores monetarios.
  • locale.LC_COLLATE: para ordenación de cadenas.
  • locale.LC_CTYPE: para funciones de tipo de carácter.
  • locale.LC_MESSAGES: para visualización de mensajes. (Python no admite mensajes específicos)

Ver valores del argumento locale en Windows

En GNU/Linux Ubuntu se pueden consultar los idiomas disponibles con el comando locale -a.

También, se pueden instalar más idiomas con el comando sudo apt-get install language-pack-XXX. Por ejemplo, para instalar la especificación de Japón: sudo apt-get install language-pack-ja. (Es equivalente a utilizar la herramienta de "Soporte de Idiomas").

A continuación, varios ejemplos para fijar la configuración regional en todas las categorías (locale.LC_ALL). Si la cadena del idioma es incorrecta o el idioma no está disponible se producirá la siguiente excepción:

Error: unsupported locale setting.

Cuando se desarrolla una aplicación para que funcione en cualquier país teniendo en cuenta la configuración regional, después de importar el módulo locale se establecerá la configuración que tenga el entorno de trabajo del propio usuario. Para ello, el argumento locale de setlocate() debe ser una cadena vacía: ''

Así, si un usuario en España imprime importes utilizando la configuración regional, el símbolo monetario mostrado será el símbolo del euro '€'; si es un londinense, el símbolo de la libra '£'; un japonés, el símbolo del Yen '¥', etc.

import locale

# Establecer la configuración que tenga el entorno del usuario
locale.setlocale(locale.LC_ALL, '')  

# Establecer configuraciones de países concretos:

# Establecer configuración para España en un sistema Windows
locale.setlocale(locale.LC_ALL, 'esp')  

# Establecer configuración para España en Ubuntu
locale.setlocale(locale.LC_ALL, 'es_ES.utf8')  

# Establecer configuración para España en otros sistemas GNU/Linux
locale.setlocale(locale.LC_ALL, 'es_ES')  

# Establecer configuración para Japón en Ubuntu
locale.setlocale(locale.LC_ALL, 'ja_JP.utf8') 
 
# Establecer configuración para Japón en otros sistemas GNU/Linux 
locale.setlocale(locale.LC_ALL, 'ja_JP')  


Obtener diccionario con configuración actual: locale.localeconv()


La función localeconv() devuelve un diccionario con todas las definiciones de la configuración regional actual.

import locale
import pprint

# Establecer la configuración del entorno de usuario 
# En este ejemplo se corresponde con 'es_ES.utf8' (España)
locale.setlocale(locale.LC_ALL, '')

# Obtener definiciones de la configuración actual
configuracion = locale.localeconv()

# Imprimir definiciones con pprint para una
# lectura agradable:
imprimir = pprint.PrettyPrinter()
imprimir.pprint(configuracion)

'''
Salida para España:

{'currency_symbol': '€',
 'decimal_point': ',',
 'frac_digits': 2,
 'grouping': [3, 3, 0],
 'int_curr_symbol': 'EUR ',
 'int_frac_digits': 2,
 'mon_decimal_point': ',',
 'mon_grouping': [3, 3, 0],
 'mon_thousands_sep': '.',
 'n_cs_precedes': 0,
 'n_sep_by_space': 1,
 'n_sign_posn': 1,
 'negative_sign': '-',
 'p_cs_precedes': 0,
 'p_sep_by_space': 1,
 'p_sign_posn': 1,
 'positive_sign': '',
 'thousands_sep': '.'}
'''

# Establecer configuración para Japón
# en Ubuntu. 
locale.setlocale(locale.LC_ALL, 'ja_JP.utf8')
# (En Windows utilizar la cadena 'jpn')

# Obtener definiciones de Japón
configuracion = locale.localeconv()

# Imprimir definiciones con pprint para una
# lectura agradable
imprimir.pprint(configuracion)

'''
Salida para Japón:

{'currency_symbol': '¥',
 'decimal_point': '.',
 'frac_digits': 0,
 'grouping': [3, 0],
 'int_curr_symbol': 'JPY ',
 'int_frac_digits': 0,
 'mon_decimal_point': '.',
 'mon_grouping': [3, 0],
 'mon_thousands_sep': ',',
 'n_cs_precedes': 1,
 'n_sep_by_space': 0,
 'n_sign_posn': 4,
 'negative_sign': '-',
 'p_cs_precedes': 1,
 'p_sep_by_space': 0,
 'p_sign_posn': 4,
 'positive_sign': '',
 'thousands_sep': ','}
'''


Funciones para aplicar las definiciones de configuración


Para aplicar las definiciones de una configuración regional utilizar las siguientes funciones:

import locale
locale.setlocale(locale.LC_ALL, '')

# Formatear números de acuerdo con la configuración
# actual de LC_NUMERIC
valor = 123456.78
locale.format('%10.2f', valor, grouping=True)   # '123.456,78'
locale.format('%10.2f', valor, grouping=False)  # ' 123456,78'

# Formatear procesando especificadores de formato %
locale.format_string('%i', valor, grouping=True)  # '123.456'
locale.format_string('%.1f', valor, grouping=True)  # '123.456,8'

# Formatear números de acuerdo con la 
# configuración LC_MONETARY actual.
locale.currency(valor, symbol=True, grouping=False)  # '123456,78 €'
# Establecer configuración para Reino Unido
locale.setlocale(locale.LC_ALL, 'en_IN') 
locale.currency(valor, symbol=True, grouping=False)  # '₹ 123456.78'
# Establecer configuración predeterminada
locale.setlocale(locale.LC_ALL, '') 

# Formatear flotantes como str pero con el carácter
# predeterminado para el punto decimal
locale.str(valor)  # '123456,78'

# Comparar dos cadenas de acuerdo con la 
# configuración LC_COLLATE actual
locale.strcoll('Guadalquivir', 'Guadalhorce')  # 10
locale.strcoll('Guadalquivir', 'Guadalupe')  # -4
locale.strcoll('Guadalupe', 'Guadalupe')  # 0

# Definir clave de ordenación de acuerdo a la
# configuración actual
cadenas = ['Guadalquivir', 'Guadalhorce', 'Guadalupe']
cadenas.sort(key=locale.strxfrm)
print(cadenas)  # ['Guadalhorce', 'Guadalquivir', 'Guadalupe']

# Convertir cadena en cadena numérica normaliza
# de acuerdo con LC_NUMERIC. 
# Disponible a partir de Python 3.5
cadena = '6543,21'
locale.delocalize(cadena)  # '6543.21'


Obtener información específica de configuración: locale.nl_langinfo()


La función nl_langinfo() retorna una cadena con información específica de la configuración regional actual. Esta función no está disponible en todos los sistemas y el conjunto de opciones posibles también puede variar entre plataformas.

import locale
from datetime import datetime

# Establecer configuración del entorno de usuario 
# En este ejemplo se corresponde con 'es_ES.utf8' (España)
locale.setlocale(locale.LC_ALL, '')

# Obtener codificación de los caracteres utilizada
codificacion = locale.nl_langinfo(locale.CODESET)  # 'UTF-8'

# En este caso la codificación se utiliza para
# convertir una cadena de tipo Unicode a Byte
pais = bytes("España", codificacion)
print(pais)  # b'Espa\xc3\xb1a' 
# El formato Byte acepta sólo caracteres ASCII y
# facilita la creación de archivos de texto.

# Obtener formato de fecha y hora 
formato1 = locale.nl_langinfo(locale.D_T_FMT)  # '%a %d %b %Y %T %Z'

# Obtener fecha y hora actual e imprimir utilizando
# el formato de fecha-hora de la configuración actual
hoy = datetime.today()
print(hoy.strftime(formato1)) # mié 26 abr 2017 17:24:42 

# Obtener formato de fecha e imprimir utilizando
# el formato de fecha de la configuración actual
formato2 = locale.nl_langinfo(locale.D_FMT)  # '%d/%m/%y'
print(hoy.strftime(formato2)) # 26/04/17

# Obtener formato de hora e imprimir utilizando
# el formato de hora de la configuración actual
formato3 = locale.nl_langinfo(locale.T_FMT)  # '%T'
print(hoy.strftime(formato3))  # 17:24:42

# Obtener cadena para representar la hora con 
# el formato AM/PM. 
# Si devuelve cadena vacía se expresa con 24 horas
formato4 = locale.nl_langinfo(locale.T_FMT_AMPM)  # ''

# Obtener nombre completo y abreviado de los días de 
# la semana en el idioma de la configuración actual
for dia in range(1, 8):
    nombre_dia = 'locale.DAY_' + str(dia)
    abrev_dia = 'locale.ABDAY_' + str(dia)
    print(nombre_dia, ':', 
          locale.nl_langinfo(eval(nombre_dia)),
          '-',
          locale.nl_langinfo(eval(abrev_dia)))

'''
Salida:

locale.DAY_1 : domingo - dom
locale.DAY_2 : lunes - lun
locale.DAY_3 : martes - mar
locale.DAY_4 : miércoles - mié
locale.DAY_5 : jueves - jue
locale.DAY_6 : viernes - vie
locale.DAY_7 : sábado - sáb
'''

# Obtener nombre completo y abreviado de los meses  
# en el idioma de la configuración actual
for mes in range(1, 13):
    nombre_mes = 'locale.MON_' + str(mes)
    abrev_mes = 'locale.ABMON_' + str(mes)
    print(nombre_mes, ':', 
          locale.nl_langinfo(eval(nombre_mes)),
          '-',
          locale.nl_langinfo(eval(abrev_mes)))   

'''
Salida:

locale.MON_1 : enero - ene
locale.MON_2 : febrero - feb
locale.MON_3 : marzo - mar
locale.MON_4 : abril - abr
locale.MON_5 : mayo - may
locale.MON_6 : junio - jun
locale.MON_7 : julio - jul
locale.MON_8 : agosto - ago
locale.MON_9 : septiembre - sep
locale.MON_10 : octubre - oct
locale.MON_11 : noviembre - nov
locale.MON_12 : diciembre - dic
'''

# Obtener carácter que se emplea en los números
# para separar la parte entera de la decimal de
# la configuración actual
locale.nl_langinfo(locale.RADIXCHAR)  # ','

# Obtener carácter separador de millares
locale.nl_langinfo(locale.THOUSEP)  # '.'

# Obtener expresión regular que se puede usar con la función regex
# para reconocer una respuesta positiva o negativa a una pregunta.
locale.nl_langinfo(locale.YESEXPR)  # '^[sSyY].*'
locale.nl_langinfo(locale.NOEXPR)  # '^[nN].*'

# Obtener símbolo monetario
# El signo '-' indica que el símbolo aparecerá delante del valor
# El signo '+' indica que el símbolo aparecerá detrás del valor
# El '.' indica que el símbolo aparecerá en la posición del
# punto o coma decimal
locale.nl_langinfo(locale.CRNCYSTR)  # '+€'


Funciones para obtener el idioma y la codificación


Las funciones siguientes permiten obtener el idioma y la codificación de las cadenas de texto de distintos modos:

import locale
locale.setlocale(locale.LC_ALL, '')

# Determinar configuración a partir de variable de entorno
locale.getdefaultlocale()  # ('es_ES', 'UTF-8')
locale.getdefaultlocale(['LANG'])  # ('es_ES', 'UTF-8')

# Obtener configuración del entorno local a partir de categoria
locale.getlocale()  #  ('es_ES', 'UTF-8')
locale.getlocale(locale.LC_NUMERIC)  # ('es_ES', 'UTF-8')

# Obtener codificación que se utiliza para representar
# las cadenas de texto
locale.getpreferredencoding()  # 'UTF-8'

# Obtener código de configuración regional normalizado
locale.normalize('es_ES')  #  'es_ES.ISO8859-1'

# Establecer configuración regional para la categoria indicada
locale.resetlocale(locale.LC_NUMERIC)



Ir al índice del tutorial de Python