Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

i18n Django Internationalization and database objects

I'm working in a bilingual project (es/en); for this project I've chosen to use django's i18n internationalization system (and I'm starting to regret it...)

Today's problem is the following:
for some models, my database stores information like description and es_description, or english_common_name and spanish_common_name (these are attributes of my objects, and are used in many circumstances, not only for page-translation issues).

A sample model can be defined like:

def MyModel(models.Model):
    name = ...
    type = ...
    authors = ...
    contributors = ...
    ...
    ...
    description = models.TextField(max_length = 800, blank=True)
    es_description = models.TextField(max_length = 800, blank=True)
    ...
    english_common_name = models.CharField('name', max_length=80, unique=True)
    spanish_common_name = models.CharField('nombre', max_length=80, unique=True)
    ...




Let's say I want to retrieve this information in my template, according to lang, the language selected by the user.

For example, in some place of my template I could have something like

<h1>{{name}}</h1>
<h3>{{english_common_name}}</h3>
<p>{{description}}</p>
<p>{% trans "Contributors" %}: {{contributors}}</p>

How can I call {{spanish_common_name}} instead of {{english_common_name}} or {{es_description}} instead of {{description}} if the page language is set to 'es'?


I absolutely refuse to do something like

<p>{% ifequal lang 'es' %}{{descrpition}}{% else %}{{es_description}}{% endifequal %}</p>


And if I try to manage this in views... I don't want to define a get_translated_content function like this

def get_translated_content(en_content,es_content,lang):
    if lang is 'es':
        return es_content
    else:
        return en_content

...
# MyView
...
    return render_to_response(...,
                              {'object': my_object,
                               'object_common_name': get_translated_content(english_common_name, spanish_common_name, lang),
                               'object_description': get_translated_content(description, es_description, lang), 
                                ... ,})

This could work (still being an horrible solution) in simple situations, but in more complex cases I would be forced to return dictionaries which are localized copies of the original MyModel object (and if in a view I have to use lots of different instances of the same model, I would be forced to generate a biiiig list of these dictionaries).



Please, tell me that there is a good, logic way to access db object-fields according to the page's language, please!



Edit: after reading the answers received so far, I think I should add to my question a "leaving the database structure (almost) unchanged" clause.

like image 577
dolma33 Avatar asked Sep 06 '10 19:09

dolma33


2 Answers

You really should use something like django-multilingual (if you're using Django 1.2, see Django 1.2 compatible branch).

For your example (based on the documentation)

from django.db import models
from django.utils.translation import ugettext_lazy as _
from multilingual.translation import TranslationModel

class MyModel(models.Model):
    name = ...
    type = ...
    authors = ...
    contributors = ...
    ...
    ...
    class Translation(TranslationModel):
        description = models.TextField(max_length = 800, blank=True)
        ...
        common_name = models.CharField(_(u'name'), max_length=80, unique=True)
        ...

Accessing translatable fields

my_model = MyModel.objects.get(id=1)
my_model.description # the description in the current language
my_model.common_name # the common name in the current language
my_model.name # the name

The current language is deteced the same way django detects it.

like image 130
Nathan Avatar answered Jan 21 '23 15:01

Nathan


You can write a custom template tag, that basically does

{% ifequal lang 'es' %}{{descrpition}}{% else %}{{es_description}}{% endifequal %}

but without being so ugly:

def get_lang(object, property, lang):
    if lang=='en':
        return object.__getattribute__(property) # TODO: deal with AttributeError
    try: # assuming other lang is 'es'
        return object.__getattribute__("es_%s" % property) # try first option of spanish property
    except AttributeError: # try other option of spanish property
        return object.__getattribute__("spanish_%s" % property) # TODO: deal with AttributeError again.
    return ""

Then you can call this from the template by

{% get_lang obj common_name lang %}
like image 32
Ofri Raviv Avatar answered Jan 21 '23 15:01

Ofri Raviv