Another helper function which I use often to get language dependent objects from database. I think that's this case is common enough to put support for that in the framework (see below).

---- code ----
from django.utils.translation import get_language
from django.core.exceptions import ObjectDoesNotExist

def get_for_lang(func, fallback='no translation', lang_field='locale', text_field='text', alt_lang=[]):
    """ get translation from db

        func: function to call to get object
        fallback: fallback text
        lang_field: locale id field
        text_field: text to return field
alt_lang: list of alternative locales, 'en' is added if not present
    """

    kwargs = {'%s__exact' % lang_field: get_language()}

    text = None

    # try preferred language
    try:
        obj = func(**kwargs)
        return getattr(obj, text_field)
    except ObjectDoesNotExist:
        pass

    if not isinstance(alt_lang, (tuple, list)):
        alt_lang = [alt_lang]
    #
    if 'en' not in alt_lang:
        alt_lang.append('en')
    #

    for lng in alt_lang:
        try:
            kwargs = {'%s__exact' % lang_field: lng}
            obj = func(**kwargs)
            text = getattr(obj, text_field)
            break
        except ObjectDoesNotExist:
            pass
    # for

    if text is None:
        return fallback

    return text
# get_for_lang
--------

OTOH, maybe is better to add new I18NCharField and I18NTextField (with better names than mine ;) ) to models to support this common case. I don't know enough about models to make that myself, but in time ... :)

Example:

class Article(meta.Model):
    model_no = CharField(...)
    price = FloatField(...)
    ...
    name = I18NCharField(maxlength=200)
    description = I18NTextField()

    def __repr__(self):
        return self.get_name()

this will create additional models like this:

class ArticleName(meta.Model):
    article = meta.ForeignKey(Article, edit_inline=meta.TABULAR,
num_in_admin=len(LANGUAGES), max_num_in_admin=len (LANGUAGES)) locale = meta.CharField(maxlength=10, choices=LANGUAGES, db_index=True)
    name = meta.CharField(maxlength=200, core=True)

    def __repr__(self):
        return '[%s] %s' % (self.locale, self.name)

    class META:
        ordering = ['locale']
        unique_together=(('article', 'locale'),)
    # class
# ArticleName

class ArticleDescription(meta.Model):
    article = meta.ForeignKey(Article, edit_inline=meta.TABULAR,
num_in_admin=len(LANGUAGES), max_num_in_admin=len (LANGUAGES)) locale = meta.CharField(maxlength=10, choices=LANGUAGES, db_index=True)
    description = meta.TextField(core=True)

    def __repr__(self):
        return '[%s] %s' % (self.locale, self.description)

    class META:
        ordering = ['locale']
        unique_together=(('article', 'locale'),)
    # class
# ArticleName

and also add this functions to the Article model: get_name() and get_ description() which will return appropriate heading or body field (i.e. using get_for_lang from above) from object based on current selected language.

I'm found while writing current application that this pattern is very common (almost a 2/3 of my models are using some type of localized name/description fields) and it will be great that i18n/model framework supports that without any additional code.

Any thoughts?

---
Nebojša Đorđević - nesh
Studio Quattro - Niš - SCG

http://djnesh.blogspot.com/  |  http://djnesh-django.blogspot.com/
Registered Linux User 282159 [http://counter.li.org]



Reply via email to