覆盖Django翻译方法

时间:2020-08-06 12:01:48

标签: django gettext google-cloud-translate

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

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

我的目标是使用翻译+ Google Cloud Translation数据库。

我没有找到一种方法...但是Django si完美,所以我想有办法吗? :)

2 个答案:

答案 0 :(得分:2)

您需要编写自定义模板context_preprocessor,以使您的自定义翻译功能在全球范围内可用供所有模板使用,请参阅https://docs.djangoproject.com/en/3.0/ref/templates/api/#writing-your-own-context-processors

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

在根项目下创建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

            ],
        },
    },
]
# ..

答案 1 :(得分:0)

这是我的工作方式。

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

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

初始化 .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('\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

最后在settings.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