How to handle translations when serializing?

4,276 views
Skip to first unread message

Bill Pairaktaridis

unread,
Mar 12, 2013, 4:56:04 AM3/12/13
to django-res...@googlegroups.com
Well, as the subject says, I've gotten the api to work with filtering and all but I can't seem to be able to get the translation working. Any ideas?

Tom Christie

unread,
Mar 12, 2013, 6:40:19 AM3/12/13
to django-res...@googlegroups.com
Can you be specific about what exactly are you trying to do?
Are we talking a the contents of fields not being translated, or the field keys themselves?

Bill Pairaktaridis

unread,
Mar 12, 2013, 6:43:06 AM3/12/13
to django-res...@googlegroups.com
The contents of my field ("description") isn't being translated.

Here is my serializer:

class TagSerializer(serializers.HyperlinkedModelSerializer):
id = serializers.Field()
name = serializers.Field(source='description')
class Meta:
model = Tag
fields = ('id', 'name', )

And here is my view:

class TagFilter(django_filters.FilterSet):
    description = django_filters.CharFilter(lookup_type='icontains')
    class Meta:
        model = Tag
        fields = ['vertical', 'description']

class TagList(generics.ListCreateAPIView):
"""
API endpoint that represents a single tag.
"""
model = Tag
serializer_class = TagSerializer
filter_class = TagFilter

def get_queryset(self):
tags = Tag.objects.filter(status=Tag.STATUS__APPROVED)
return tags

This works fine for my purposes (producing a json of my tags based on a search done through a jquery tokeninput plugin) but I need to find a way for this to work for other languages besides English.


--
You received this message because you are subscribed to a topic in the Google Groups "django-rest-framework" group.
To unsubscribe from this topic, visit https://groups.google.com/d/topic/django-rest-framework/WTZ0H6dyJe4/unsubscribe?hl=en.
To unsubscribe from this group and all its topics, send an email to django-rest-fram...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Bill Pairaktaridis

unread,
Mar 12, 2013, 6:44:29 AM3/12/13
to django-res...@googlegroups.com
The contents of my field ("description") isn't being translated.

Here is my serializer:

class TagSerializer(serializers.HyperlinkedModelSerializer):
id = serializers.Field()
name = serializers.Field(source='description')
class Meta:
model = Tag
fields = ('id', 'name', )

And here is my view:

class TagFilter(django_filters.FilterSet):
    description = django_filters.CharFilter(lookup_type='icontains')
    class Meta:
        model = Tag
        fields = ['vertical', 'description']

class TagList(generics.ListCreateAPIView):
"""
API endpoint that represents a single tag.
"""
model = Tag
serializer_class = TagSerializer
filter_class = TagFilter

def get_queryset(self):
tags = Tag.objects.filter(status=Tag.STATUS__APPROVED)
return tags

This works fine for my purposes (producing a json of my tags based on a search done through a jquery tokeninput plugin) but I need to find a way for this to work for other languages besides English.

Tom Christie

unread,
Mar 12, 2013, 2:46:38 PM3/12/13
to django-res...@googlegroups.com
I haven't really worked with translations much, not really sure at what point database fields would get translated.
If you can get together an equivalent ModelForm that demonstrates how ModelForm behaves in a way that ModelSerializer also should but doesn't, then that'd be a good starting point.

Also if you can issue a PR with a failing test, that'd be another really good starting point.

If anyone else who more familiar with translations has an insight that'd also be appreciated?...

Bill Pairaktaridis

unread,
Mar 13, 2013, 5:46:10 AM3/13/13
to django-res...@googlegroups.com
Translation, in my case at least, happens on the templates, using i18n. So, I'm not so sure as to how it could work on the Serializer's side...

Tom Christie

unread,
Mar 18, 2013, 8:34:08 AM3/18/13
to django-res...@googlegroups.com
Hi Bill,

  See this thread for a follow up on how I think we'd want to deal with serializing translatable text.

Regards,

  Tom

Bill Pairaktaridis

unread,
Mar 19, 2013, 4:01:34 AM3/19/13
to django-res...@googlegroups.com
Thanks, Tom. I'll look into it and if I find a way to resolve it, I'll post back.

Bill Pairaktaridis

unread,
Mar 19, 2013, 10:35:09 AM3/19/13
to django-res...@googlegroups.com
OK, so I'm using this function that was built by a member in-house:

def __unicode__(self):
        return self.get_translation(get_language())

in my models and it returns the correctly translated description field. Is there any way I could get the serializer to use this instead of pulling the raw description from the database?

Marc Gibbons

unread,
Mar 23, 2013, 4:33:40 PM3/23/13
to django-res...@googlegroups.com
Hi Bill,
I am experimenting using the django-modeltranslation app to store data in French and English in database and am exposing models via django rest framework.
If I have a model with a field called "name" - I want the API to return the value in the correct language.

My API routes are prefixed by api/en or api/fr, and am overriding the APIView's initial method to capture the language and am using this parameter to activate the locale (django.utils.translation.activate(language)).

django-modeltranslation does the rest.

views.py:
class MyView(generics.ListAPIView):

    def initial(self, request, *args, **kwargs):

        language = kwargs.get('lang')
        translation.activate(language)
        super(MyView, self).initial(request, *args, **kwargs)

urls.py
url(r'^api/(?P<lang>(en|fr))/', include('.api.urls'))

In this case, I am determining the language from the route, but you could just as well detect and activate the browser's locale language.

Fco. Javier Velasco Arjona

unread,
Nov 6, 2013, 3:10:29 PM11/6/13
to django-res...@googlegroups.com
Hi guys, I've been working with translations this afternoon and I'd like to share with you my proposal. I'm only using translations for some fields in my data model and, in those, I'm using two attributes to represent the translations. For example, I have a model with a "name" attribute and a "name_es" attribute.

In my API, I want to receive requests for each language by using "Accept-Language" header. That's really REST. I want the client to see and deal with only "name" attribute. If the request is made for spanish my response will be with "name" attribute but "name_es" value. What I've done is overload the Modelserializer like this:

class TranslateSerializer(serializers.ModelSerializer):
    def __init__(self, *args, **kwargs):
        super(TranslateSerializer, self).__init__(*args, **kwargs)
        self.translate_fields = getattr(self.Meta, 'translate_fields', ())
        if kwargs.get('context', None):
            self.lang = utils.get_request_language(kwargs['context'].get('request', None))

    def to_native(self, obj):
        # Exclude ALWAYS language specific fields
        for language in settings.LANGUAGES:
            if language[0] != 'en':
                for field in self.translate_fields:
                    key = field + '_' + language[0]
                    if self.fields.get(key):
                        self.fields.pop(key)

        ret = super(serializers.ModelSerializer, self).to_native(obj)

        # Get current language and give the fields
        if self.lang != 'en':
            for field in self.translate_fields:
                trans = getattr(obj, field + "_" + self.lang)
                if trans:
                    ret[field] = trans
        return ret

    def from_native(self, data, files):
        instance = getattr(self, 'object', None)
        if self.lang != 'en':
            for field in self.translate_fields:
                value = data.get(field) or None
                if value:
                    data[field + "_" + self.lang] = value
                    # If is instance (existent object), set the original attr
                    data[field] = getattr(instance, field, data[field])

        ret = super(serializers.ModelSerializer, self).from_native(data, files)
        return ret

That's it. So, let's say I have a model Tag with name and name_es attributes among others. I can use this now:

class ProductTagSerializer(TranslateSerializer):
    class Meta:
        model = ProductTag
        translate_fields = ('name',)

And I'll be giving always name, but if the request is for spanish I'll get name_es value. If I'm creating a new tag in spanish I'll get name and name_es with spanish name (since name is required). If I'm patching the name in spanish, only name_es will be modified.

Hope it's useful for you, what do you guys think?
Cheers!!
Reply all
Reply to author
Forward
0 new messages