覆盖django翻译方法



我想找到一种简单的方法来覆盖Django使用的gettext方法。

我希望创建自己的方法,并告诉Django在任何地方使用它(.py,Template…(。在我的.py中,它很简单,我可以直接使用我的新方法,但在Django引擎中,我不知道该怎么做?

我的目标是使用翻译数据库+谷歌云翻译。

我没有找到一种方法…但是Django是完美的,所以我想有一种方法吗?:(

您需要编写自定义模板context_preprocessor,以使您的自定义翻译功能在所有模板中都可用,请参阅https://docs.djangoproject.com/en/3.0/ref/templates/api/#writing-您自己的上下文处理器

自定义上下文处理器可以位于代码库中的任何位置,但由于您的功能是关于翻译的,因此使应用程序独立确实很有意义,这意味着代码应该位于根项目中:

在根项目下创建context_processors.py:

my_gettext(request):
#  put your logic here ..
# ..

则在settings.py:下

# ..
TEMPLATES = [
{
'BACKEND': 'django.template.backends.django.DjangoTemplates',
'DIRS': [os.path.join(BASE_DIR, 'templates')],
'APP_DIRS': True,
'OPTIONS': {
'context_processors': [
'django.template.context_processors.debug',
'django.template.context_processors.request',
'django.contrib.auth.context_processors.auth',
'django.contrib.messages.context_processors.messages',
'context_processors.my_gettext',  # register your custom context preprocessor
],
},
},
]
# ..

下面是我是如何做到的。

创建一个类以将翻译保存在数据库中:

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

创建一个函数来翻译来自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 = {}

修改django/utils/translation/trans_real.py的gettext((方法:

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('rn', '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在设置中.py添加:

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   

最新更新