views:

55

answers:

2

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.

+1  A: 

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.

Nathan
Wow, thank you, this solution is terrific, and it would be the perfect solution... but I would prefer not to change my models structure: the project is already working and the db is populated with a loooot of data... [Also, reading this article http://www.muhuk.com/2010/01/dynamic-translation-apps-for-django/ , looks that django-multilingual isn't the best pick at all (same for i18n) ]
dolma33
Very interesting link, thanks for posting it. You can use south (http://south.aeracode.org/) to migrate your models.Regarding django-multilingual, there's a new fork of the project that works with Django 1.2 (http://github.com/ojii/django-multilingual-ng)
Nathan
A: 

If it's not too late you might consider re-working your data model so that you model a one-to-many relationship between the core entities and their language-specific representations. That way your model's more normalised - you're not enshrining meta-data in your field names - and you'll find it easier to work with.

Something like:

class MyModel(models.Model):
    // fields that don't need translating go here
    name = ...
    type = ...

class MyModelTranslation(models.Model):
    // fields that do need translating go here
    language = models.CharField(...)
    description = models.TextField(...)
    common_name = models.TextField(...)
    parent = models.ForeignKey('MyModel', related_name="translations")

    // TODO: enforce uniqueness for any given parent/language tuple

Then in your view you can do something like:

// Get the user's chosen language, default to 'en'
lang = request.session.get('django_language', 'en')


obj = MyModel.objects.get(...)
object_text = obj.translations.filter(language__exact=lang)[0]

return render_to_response(...,
{
    'object': obj,
    'object_common_name': object_text.common_name,
    'object_description': object_text.description,
})
Simon Whitaker
Ooh, I like Nathan's answer - hadn't come across django-multilingual before!
Simon Whitaker