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 ? :)
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