Múltiples idiomas en django

No hay momento mas dulce en el desarrollo de un programa el ver que va tomando solidez y que puedas implantar detallitos interesantes en la generación de pdf, navegar por el programa que va a los sitios que tiene que ir, etc. Hoy vamos a hablar de una de estas otras cosas que señalan el avanzado estado de nuestro programa, la internacionalización, el disponer la página en varios idiomas. Vamos a contarlo!

Primero de todo recomiendo tener a mano la documentación de django y éste otro artículo de Alex Dzul al que le he copiado el título y la metedología.

Para resumir, lo que tendremos que hacer será configurar el settings.py, preparar y traducir la interfaz y finalmente generar los ficheros .po. En la documentación te habla primero de la generación de los ficheros de traducción y después desarrollar la traducción en la interfaz (templates), luego contaré porqué es mejor hacerlo al revés.

Así que empezamos

Primero modificaremos el fichero settings.py de nuestro proyecto

(venv) laura@melatonina:~/dev/colibri$ vi colibri/settings.py 
import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))

[...]

MIDDLEWARE_CLASSES = (
    # ...
    'django.middleware.locale.LocaleMiddleware',
    # ...
)

[...]

# Internationalization
# https://docs.djangoproject.com/en/2.1/topics/i18n/
# https://www.pythoniza.me/multiples-idiomas-en-django/

LANGUAGE_CODE = 'en-us'
TIME_ZONE = 'Europe/Madrid'
USE_I18N = True
USE_L10N = True
USE_TZ = True

from django.utils.translation import ugettext_lazy as _
LANGUAGES = (
    ('en', _('English')),
    ('es', _('Spanish')),
    ('ca', _('Catalan')),
)

# Definimos la ruta de los archivos de idiomas
LOCALE_PATHS = (
    os.path.join(BASE_DIR, 'locale'),
)

# Definimos el procesador de contexto para i18n
#from django.conf.global_settings import TEMPLATE_CONTEXT_PROCESSORS as TCP
#TEMPLATE_CONTEXT_PROCESSORS = TCP + (
#    "django.core.context_processors.i18n",
#    "django.core.context_processors.request",
#)

Tengo desactivada la última parte porque me falla y funciona correctamente sin ésta parte.

Ahora crearemos un directorio llamado locale en la raíz de nuestro programa (dónde está el manage.py)

(venv) laura@melatonina:~/dev/colibri$ mkdir locale
(venv) laura@melatonina:~/dev/colibri$ ls
colibri  locale  manage.py  __pycache__  README  requirements.txt  scripts venv  web

Ahora, según mi experiencia, lo mejor será configurar las plantillas para que se puedan traducir automáticamente las cadenas, para ello, añadiremos el plugin i18n en cada una de las páginas que vayamos a usar la traducción

Al principio de uno de los ficheros de plantilla (.html) tengo algo similar a ésto:

< !-- extend base layout -- >
{% extends "base.html" %}
{% load views_templates %}
{% load i18n %}

A continuación, para cada palabra o string que queramos traducir lo vamos a poner en éste formato:

< strong >{% trans "Status" %}: < /strong >
{% trans "Creation date" %}
{% trans request.language.name %}

En el primer caso lo vemos entre las etiquetas de negrita, en el segundo que ésta cadena puede disponer de espacios y en el tercero traducimos la salida de la base de datos, en éste caso el nombre del idioma de la sesión del usuario.

Una vez hecho ésto a lo ancho y largo de nuestro código vamos a generar los ficheros de traducción .po, así que volveremos a la raíz de nuestro programa y ejecutaremos lo siguiente:

(venv) laura@melatonina:~/dev/colibri$ django-admin makemessages --locale en

Ésto generará la siguiente estructura:

(venv) laura@melatonina:~/dev/colibri$ tree locale
locale
├── en
│   └── LC_MESSAGES
│       └── django.po

2 directories, 1 file

Si modificamos el fichero veremos que ha añadido muchísimas mas cadenas de las que realmente hemos traducido en nuestro proyecto, y deberemos limpiar el django.po. Dentro de él, nos encontraremos las cadenas que hemos pedido traducir con éste formato:

(venv) laura@melatonina:~/dev/colibri$ vi locale/en/LC_MESSAGES/django.po
msgid "Status"
msgstr ""

msgid "Creation date"
msgstr ""

msgid "English"
msgstr ""

msgid "Spanish"
msgstr ""

msgid "Catalan"
msgstr ""

Ahora lo siguiente será crear una estructura similar a ésta, y con las cadenas msgstr traducidas al idioma al que corresponda el .po. Si hemos definido la traducción (django-admin makemessages) en inglés, los strings en Inglés si están en blanco aparecerá la cadena de msgid.

(venv) laura@melatonina:~/dev/colibri$ tree locale/
locale/
├── ca
│   └── LC_MESSAGES
│       └── django.po
├── en
│   └── LC_MESSAGES
│       └── django.po
└── es
    └── LC_MESSAGES
        └── django.po

6 directories, 3 files

Una vez traducidos los django.po, tendremos que generar los ficheros django.mo (compilados), para ello ejecutaremos lo siguiente:

(venv) laura@melatonina:~/dev/colibri$ django-admin compilemessages

Y la estructura de directorios y ficheros será así

(venv) laura@melatonina:~/dev/colibri$ tree locale/
locale/
├── ca
│   └── LC_MESSAGES
│       ├── django.mo
│       └── django.po
├── en
│   └── LC_MESSAGES
│       ├── django.mo
│       └── django.po
└── es
    └── LC_MESSAGES
        ├── django.mo
        └── django.po

6 directories, 6 files

Ésto buscará todos los .po de nuestro sistema y los generará a .mo para que puedan ser leídos por django. Cada vez que queramos añadir una cadena nueva a los ficheros .po para que estén disponibles se tendrán que compilar los .mo. Por ésto es bueno primero traducir toda la interfaz y después generar los ficheros de traducción, al revés es un engorro!

A continuación os dejo un pequeño TIP para cambiar el idioma de la interfaz a partir de una configuración de usuario, ya que por defecto coje los valores del navegador.

Para cambiar el idioma importaremos la librería translation

from django.utils import translation

_profile = Profile.objects.get(pk=request.user.id)
request.language = _profile.language.name
request.lang = _profile.language.code

translation.activate(request.lang)

Si lo que queremos es usar i18n en nuestros views_*.py

from django.utils.translation import ugettext_lazy as _

_status_translated = _("Status");

Y hasta aquí éste manual. Espero que te haya sido de ayuda :)

Deixa un comentari

L'adreça electrònica no es publicarà. Els camps necessaris estan marcats amb *

Aquest lloc utilitza Akismet per reduir els comentaris brossa. Apreneu com es processen les dades dels comentaris.