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:
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.