Ranteando en varios idiomas, the easy way

Angel Velásquez

@angvp

angvp@archlinux.org

Rant

"Es un monólogo o un discurso largo, dado por una persona cuando está molesta o irritada"

(traducción de wikipedia)

Como perder 20 kilos en 2 semanas con HERBALIFE

Antes de empezar...

  • Hablo rápido, pero puedo ir más pausado si me lo piden.
  • Los rants de los ejemplos fueron suavizados para cumplir el código de conducta.
  • La charla se refiere a i18n de contenido que está en la DB
  • En caso de aburrimiento .. banquen un poco que hay pizza al final! :)

Un poco de contexto

Route Atlas es una herramienta creada para ayudar a los viajeros a planificar sus recorridos dándole toda la información posible (de manera escrita, visual y audiovisual) de los sitios más impresionantes de América del Sur.

Route Atlas

Los contenidos del sitio están disponibles en 3 idiomas .. (Español, Inglés, Portugués de Brasil).

El problema

 

  • Requiere cambios en los modelos (y migraciones en algunos casos).
  • Agrega más complejidad para lo que ya funcionaba en 1 idioma.
  • El framework de i18n que trae Django no alcanza :(

¿Y cómo resolvemos este problema?

  • Agregando 1 campo por columna x idioma en la tabla (django-modeltranslation)
  • Creando una tabla que tenga todas las traducciones (django-hvad, django-klingon)
  • Manejando las traducciones en un archivo .po (django-dbgettext)

Las soluciones

 

  • django-hvad
  • django-modeltranslation
  • django-dbgettext
  • django-klingon (nuestra propia cosecha)
  • ... etc

django-hvad

(+):

  • Usa el ORM de Django
  • Incluye admin
  • Se mantiene al día el desarrollo

(-):

  • Requiere cambios en la definición del modelo
  • La integración con DRF es inexistente

https://github.com/kristianoellegaard/django-hvad

django-modeltranslation

(+):

  • Muy simple de acceder
  • No requiere un admin especial
  • Se mantiene al día el desarrollo

(-):

  • Genera las traducciones en la misma tabla de origen añadiendo columnas según campo a traducir e idioma
  • Requiere que se hagan migraciones por cada idioma o campo a traducir.
  • La cobertura de tests es mala

https://github.com/deschler/django-modeltranslation

django-dbgettext

(+):

  • Simple
  • Se podría mantener control de versiones sin muchísimo esfuerzo
  • Se maneja como un archivo de traducciones

(-):

  • Requiere instalar otra aplicación para administrar catálogos de traducciones (rosetta, etc)
  • Requiere compilación de mensajes con cada cambio
  • El desarrollo está estancado

https://bitbucket.org/drmeers/django-dbgettext/wiki/browse/

django-klingon

(+):

  • Simple
  • Integración con el backend de cache que esté en la app
  • Integración con admin de Django
  • Integración con DRF2 en otra app (y pronto DRF3)
  • Desarrollo activo

(-):

  • Requiere cambios mínimos en la definición del modelo (no genera migrations)
  • Un poco verde (Faltan contributors :()

https://github.com/RouteAtlas/django-klingon/

Klingon en acción

settings.py

...

_ = lambda s: s


LANGUAGES = (
    ('es', _('Español')),
    ('it', _('Italiano')),
    ('en', _('Inglés')),
)

DEFAULT_LANGUAGE = 'es'
KLINGON_DEFAULT_LANGUAGE = DEFAULT_LANGUAGE

INSTALLED_APPS = (
    'django.contrib.admin',
    'django.contrib.auth',
    'django.contrib.contenttypes',
    'django.contrib.sessions',
    'django.contrib.messages',
    'django.contrib.staticfiles',
    'django_extensions',
    'klingon',
    'rant',
)

models.py

from autoslug import AutoSlugField
from django.db import models
from klingon.models import AutomaticTranslation


class Category(models.Model, AutomaticTranslation):
    name = models.CharField(max_length=100)
    description = models.TextField()
    #klingon begin
    translatable_fields = ('name', 'description')

    class Meta:
        verbose_name_plural = 'Categories'

    def __str__(self):
        return self.name

class Rant(models.Model, AutomaticTranslation):
    category = models.ForeignKey(Category)
    title = models.CharField(max_length=100)
    description = models.TextField()
    slug = AutoSlugField(populate_from='title')
    # klingon begin
    translatable_fields = ('title', 'description', 'slug')
    translatable_slug = 'slug'

    def __str__(self):
        return self.title

admin.py

from django import forms
from django.contrib import admin
from rant.models import Category, Rant
from klingon.admin import TranslationInline, TranslationInlineForm, create_translations


class RichTranslationInlineForm(TranslationInlineForm):
    widgets = {
        'CharField': forms.TextInput(attrs={'class': 'klingon-char-field'}),
        'TextField': forms.Textarea(attrs={'class': 'klingon-text-field'}),
        'SlugField': forms.TextInput(attrs={'readonly': 'readonly', 'disabled':
            'disabled'}),
    }


class RichTranslationInline(TranslationInline):
    form = RichTranslationInlineForm


class CategoryAdmin(admin.ModelAdmin):
    list_display = ('id', 'name', 'description', 'translations_link')
    search_fields = ['name', 'description']
    inlines = [RichTranslationInline]
    actions = [create_translations]


class RantAdmin(admin.ModelAdmin):
    list_display = ('id', 'title', 'slug', 'translations_link')
    search_fields = ['title', 'description']
    inlines = [RichTranslationInline]
    actions = [create_translations]


admin.site.register(Category, CategoryAdmin)
admin.site.register(Rant, RantAdmin)

Live Demo!

(casi siempre fallan) :( crucemos los dedos :D

¡GRACIAS!

Angel "qbasic" Velasquez

angvp@archlinux.org

@angvp (twitter, github)

https://github.com/angvp/klingonexample

Ranteando en varios idiomas, the easy way

By Angel Velásquez

Ranteando en varios idiomas, the easy way

Charla para la Django Meetup 4 @ RouteAtlas

  • 527