Content translation in Django, compatible with South
I'm looking for a solution to have translatable database fields in Django, and the solution needs to be compatible with South.
I already found django-transmeta and transdb. Only the latter seems to be compatible wit开发者_开发技巧h South, but I'm not sure about that. Also, transdb values don't look nice in the database (something the customer actually cares about).
Has anybody worked with such a combination? I'm not particaluary focussed on South, but it seems to be the way to go for schema migration in Django.
I suppose that tho two apps use custom fields and South complains about that. Here you can read about how to enable south for those custom fields: http://south.aeracode.org/docs/customfields.html.
Two relevant links:
- THE DJANGO ORM AND MULTILINGUAL DATABASE CONTENTS (A talk on Djangocon 2011)
- http://djangopackages.com/grids/g/i18n/
Because we did know that the number of languages will never change, we switched to having fields for each language and a simple mechanism for automatically reading the correct field for the current language. Our implementation is used like this:
class Question(models.Model):
__metaclass__ = LocalizeModelBase
text_de = models.TextField(verbose_name=_(u"question text (german)"))
text_en = models.TextField(verbose_name=_(u"question text (english)"))
text = Translate
Question().text
then automatically returns the correct field, based on the current language with a fallback to the default language.
The implementation behind it should be pretty much self-explaining:
from django.db.models.base import ModelBase
from django.utils.translation import get_language
from django.conf import settings
__all__ = ('Translate', 'LocalizeModelBase')
# a dummy placeholder object
Translate = object()
class LocalizeModelBase(ModelBase):
"""This meta-class provides automatically translated content properties. Set
a model field to `Translate` and it will automatically return the property
with the name of the current language. E.g. if there is a normal member
`text_de`, a member `text = Translate` and the current language is `de`, then
an object will return the content of `text_de` when it is asked for the value
of `text`.
"""
def __new__(metacls, classname, bases, classDict):
# find all classDict entries that point to `Translate`
for key in classDict.keys():
if classDict[key] is Translate:
# replace them with a getter that uses the current language
classDict[key] = make_property(key)
return super(LocalizeModelBase, metacls).__new__(metacls, classname, bases, classDict)
def make_property(k):
"""Creates a new property that implements the automatic translation
described above. Every use of `Translate` in a class definition will be
replaces with a property returned by this function."""
def pget(self):
try:
# try to return the attribute for the current language
return getattr(self, "%s_%s" % (k, get_language()))
except AttributeError:
# use the default language if the current language is not available
return getattr(self, "%s_%s" % (k, settings.LANGUAGE_CODE))
return property(pget)
精彩评论