Wednesday, March 4, 2009

Easier field translation with django-transmeta

django-transmeta is a new project that provides django field translations in a simpler way than existing ones like django-multilingual and transdb.

The basis of that simplicity is creating a field in the database table for every translation, so internally we'll have something like:


CREATE TABLE app_model (
    [...]
    myfield_en varchar,
    myfield_ca varchar,
    [...]
);


where "en" and "ca" are the languages in our application (English and Catalan in this case).

For the developer, translating a model is as simple as adding a metaclass to the model, and specify the fields to translate in its Meta class:


from transmeta import TransMeta

class MyModel(models.Model):
    __metaclass__ = TransMeta

    name = models.CharField(max_length=64)
    description = models.TextField()
    price = models.FloatField()

    class Meta:
        translate = ('name', 'description', )


Even with this project is still as tricky as transdb and multilingual, its main goal is being really really simple, for its design, for developers, and its code (that mainly it's about 120 lines of code). It also breaks some limitations of transdb (its most simple predecessor IMHO) like translating non-text fields.

I also want to mention that I just discovered a new project for translating model fields, named django-modeltranslation, that looks cool, but I don't like the (admin like) registering way to set translatable fields (too much complicated).

18 comments:

  1. So adding a new language means modifying the structure of your database, adding a new column to the table you've called app_model? This doesn't scale very well (or I've completely misunderstood your description).

    ReplyDelete
  2. Great project, I think the simplest solution is probably the best (some kind of programmer's Occam's razor).

    To anonymous:
    Adding a new language or translatable field does indeed need change in the database schema, but django-transmeta includes a custom command to do that automatically. Take a look at the fine Google Code page.

    ReplyDelete
  3. Great, multilingual's classes system don't allow you to do anything with translated fields in model's save method/post_save signal, so your application is a step forward :)

    ReplyDelete
  4. It looks interesting! Did you try http://code.google.com/p/django-multilingual-model/ ? It's really really simple too :)

    ReplyDelete
  5. David, django-multilingual-model is "simpler" in the code because it's just 30 lines of code. That it's great, but the problem is after few minutes looking at the example I can't understand what I have to do to translate my fields... Split my model in two, create a foreign key from one to the other, and in the other specify the first one in the meta. Then specify the fields for translating in the model where they are not defined...

    Sorry but that's not why I understand by simple, adding a metaclass and specifying fields to translate looks much more clear to me.

    Thanks for you comment, and for pointing out this project anyway.

    ReplyDelete
  6. Looks nice. I think I'll opt for django-modeltranslation though; the "complex" admin-style registration has a huge advantage that I can translate models in 3rd-party apps without modifying the model at all.

    ReplyDelete
  7. Hi. I'm the author of the django-modeltranslation app. In fact one of the requirements for django-modeltranslation was not to change the original model class (mostly from a third-party app) - that's why i choose an registration approach.

    It has no management command for updating the schema like django-transmeta - that has to be done by the user.

    As far as I can see the only difference between my approach and this one here is where the translation options are placed - i.e. model/metaclass vs. registration.

    Interesting coincdence. I got my inspiration from Marty Alchin's "Pro Django" which is a great book, before reading this book I would not even have dared to implement something like this.

    ReplyDelete
  8. This is a very cool idea, but how do you get the fields into the templates? Considering the templates will have translation strings as well, how would you then feed them with the correct language fields?
    Will it automatically put the right language by simply putting {{ mymodel.name }}?

    ReplyDelete
  9. yeah, it will. That's the goal. :)

    ReplyDelete
  10. Groovy :-)
    I'm spending the afternoon trying it out ;-)

    ReplyDelete
  11. Not as simple as I thought.
    Is it possible to post a more complete example at the Google Code page?
    For example:

    def view(request, language, slug):
    activate(language)
    page = Page.objects.get(slug=slug)
    return render_to_response("view.html", {'page' : page})

    Will not work. If I send 'es' as the language, it will still give me the default English version.
    I've tried sending the language variable to the template and it's working, but it's not replacing 'slug' with 'slug_es' as it should.
    Maybe you could make it clearer for us beginner/intermediate folks :P

    ReplyDelete
  12. I know I'm commenting on old stuff and topic was deeply discussed elsewhere,
    but anyway I'd like to share my own eperience with wider audience.

    Your approach (django transmeta) works very well for simple applications.
    It place very nice with django forms forms (ModelForm works out of the box).

    But once you'll try to develop more complex publication system, where you
    need to bind Author and Translation to get 'Translation author' relationship,
    then tranmeta stops to scale. There must be always one reference between
    tables.

    The django-multilingual and django-multilingual-model are handling translated
    in fields in seperate table, therefore you can introduce a relation ship
    between Author/User and translated fields table. This scales well. On the
    other hand these model will have a problem with ModelForm. If you for whatever
    reason don't want to use Admin interface, then you have to create your
    forms manualy for translated models. ModelForm will not display translated
    fields.

    So my approach is to use django-transmeta for simple models like picture + its
    comment.

    For Article class, which instances are being published through process
    (Draft->Submitted->Accepted->Published) I'm going to use
    django-multilingual-model. I was considering django-multilingual, but the
    ModelForm problem there seems like a big obstacle for me. I was trying to come
    up with solution, but I was able to develop kind of POC. Once I'll gain some
    more experience with django-multilingual, I'll try to fix ModelForm there
    ultimately.

    After one week of playing with all that translation stuff I can see there is
    no ultimate one size fits all solution.

    just my 2c's.

    ReplyDelete
  13. Makes sense. I quite liked the transmeta approach, but not the column per langauge. A pile of the existing solutions don't support south database migrations either so I adapted transmeta to my own: http://www.io41.com/django/metalingual

    ReplyDelete
  14. Now iam working on some language translation in django.
    I like to use the Django-transmeta module..
    Where can i download the Django-transmeta module?

    ReplyDelete
  15. http://code.google.com/p/django-transmeta/

    ReplyDelete
  16. Hi,

    I'm a Windows user. I've placed transmeta at c:\python\Lib\site_packages\transmeta using "setuptools".

    When I go to my project to run the "sync_transmeta_db" command I get this error:

    Uknown command: 'sync_transmeta_db'
    Type 'manage.py help' for usage.

    I know I've done somthing incomplete, but can't find anything on this site to help me out.

    What should I do?

    ReplyDelete
  17. i have the same problem, Unkown command.... what should I do? :(

    ReplyDelete
  18. well, just copy management folder from transmeta to any application registered in your project...works great

    ReplyDelete