Search code examples
djangogettextgoogle-cloud-translate

Override the django translation method


I wish to find a simple way to override the gettext method use by Django.

I wish to create my own method and tell Django to use it everywhere (.py, Template …). In my .py it's simple, I can use my new method directly but in the Django engine I do not know how to do it ?

My aim is to use a database of translations + Google Cloud Translation.

I do not find a way to do it … but Django si perfect, so I suppose there is a way ? :)


Solution

  • Here how I have done it.

    Create a class to save in the database the translations :

    class Cache(models.Model):
        source: str = models.TextField(verbose_name=_('Source'), null=False, blank=False)
        result: str = models.TextField(verbose_name=_('Result'), null=False, blank=False)
        language_code: str = models.CharField(verbose_name=_('Language Code'), max_length=10, null=False, blank=False)
        md5: str = models.CharField(verbose_name=_('MD5'), max_length=512, null=False, blank=False, db_index=True)
    
        def save(self):
            self.md5 = hashlib.md5( (self.language_code + '__' + self.source).encode() ).digest()
            obj: Cache = super(Cache, self).save()
            return obj
    

    Create a function to translate a text from Google Cloud API

    # -*- coding: utf-8 -*-
    import hashlib
    from google.cloud import translate_v2 as translate
    
    def GoogleTranslationGetText(msg, language_code):
        from .models import Cache
        from . import translate_client, cache_local
        md5 = hashlib.md5( (language_code + '__' + msg).encode()).digest()
    
        result = cache_local.get(md5, None)
        if not result:
            caches: Cache = Cache.objects.filter(md5 = md5).defer('source', 'language_code', 'md5')
            result = msg
            if caches:
                result = caches[0].result
            else:
                if not translate_client:
                    translate_client = translate.Client()
                result = translate_client.translate(msg, target_language=language_code)
                result = result['translatedText']
    
                #Save cache
                cache = Cache()
                cache.source = msg
                cache.result = result
                cache.language_code = language_code
                cache.save()
            
            cache_local[md5] = result
    
        return result
    

    init.py

    translate_client  = None
    cache_local = {}
    

    Modify the method gettext() of django/utils/translation/trans_real.py :

    def gettext(message):
        """
        Translate the 'message' string. It uses the current thread to find the
        translation object to use. If no current translation is activated, the
        message will be run through the default translation object.
        """
        global _default
    
        eol_message = message.replace('\r\n', '\n').replace('\r', '\n')
    
        if eol_message:
            _default = _default or translation(settings.LANGUAGE_CODE)
            translation_object = getattr(_active, "value", _default)
    
            ##CANICOMPET
            if type(translation_object) == DjangoTranslation and translation_object.language() in settings.LANGUAGE_TO_GOOGLE_CODES:
                result = settings.LANGUAGE_TO_GOOGLE_FCT(eol_message, translation_object.language())
            else:
                ## original Django
                result = translation_object.gettext(eol_message)
    
    
        else:
            # Return an empty value of the corresponding type if an empty message
            # is given, instead of metadata, which is the default gettext behavior.
            result = type(message)('')
    
        if isinstance(message, SafeData):
            return mark_safe(result)
    
        return result
    

    Finnaly in settings.py add :

    os.environ.setdefault("GOOGLE_APPLICATION_CREDENTIALS", "pth/to/google/api/json/key/file.json")
    LANGUAGE_TO_GOOGLE_CODES = ['de', ] #list of languages translated by Google
    from GoogleTranslation.functions import GoogleTranslationGetText
    LANGUAGE_TO_GOOGLE_FCT = GoogleTranslationGetText