Search code examples
pythondjangodjango-rest-frameworkdjango-i18ndjango-modeltranslation

Django activate translations project wide instead of per view?


I have a Django project where I activate the translations based on the Accept-Language header on each and every view as follows,

from django.utils import translation
translation.activate(request.headers.get('Accept-Language', 'en'))

So if I have a ViewSet using Django Rest Framework, I had to do the above for each and every methods as following,

class MyViewSet(viewsets.ModelViewSet):
    
    def list(self, request, *args, **kwargs):
        translation.activate(request.headers.get('Accept-Language', 'en'))
        # ....
    
    def retrieve(self, request, *args, **kwargs):
        translation.activate(request.headers.get('Accept-Language', 'en'))
        # ....
    
    def update(self, request, *args, **kwargs):
        translation.activate(request.headers.get('Accept-Language', 'en'))
        # ....
    
    def destroy(self, request, *args, **kwargs):
        translation.activate(request.headers.get('Accept-Language', 'en'))
        # ....

This is just for a viewset, I currently have 10+ viewsets and Translations are needed for every viewset. This make the process even harder to maintain and results in much code duplication. How can I clean up this code to something like activating translations project wide, any options available to do?

thank you for any input.


Solution

  • I think the cleanest approach will be writing a mixin for translations. Something along the lines:

    class ActivateTranslationMixin:
        def initialize_request(self, request, *args, **kwargs):
            init_request = super().initialize_request(request, *args, **kwargs)
            translation.activate(request.headers.get('Accept-Language', 'en'))
            return init_request
    

    Then you inherit this mixin in all the views you need

    class MyViewSet(ActivateTranslationMixin, viewsets.ModelViewSet):
        ...
    

    Never tried this way before but it should work.