Заменить метод перевода django - PullRequest
1 голос
/ 06 августа 2020

Я sh, чтобы найти простой способ переопределить использование метода gettext Django.

Я sh, чтобы создать свой собственный метод и сказать Django использовать его везде ( .py, шаблон…). В моем .py это просто, я могу использовать свой новый метод напрямую, но в движке Django я не знаю, как это сделать?

Моя цель - использовать базу переводов + Google Cloud Translation.

Я не могу найти способ сделать это ... но Django si perfect, так что, я полагаю, есть способ? :)

Ответы [ 2 ]

2 голосов
/ 06 августа 2020

вам необходимо написать свой собственный шаблон context_preprocessor, чтобы сделать вашу пользовательскую функцию перевода доступной глобально для использования во всех шаблонах, см. https://docs.djangoproject.com/en/3.0/ref/templates/api/#writing -your-own-context-processors

Пользовательские процессоры контекста могут находиться где угодно в вашей базе кода, но поскольку ваша функция связана с переводом, она имеет смысл сделать независимым от приложения, то есть код должен жить в проекте root:

под root создать проект 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

            ],
        },
    },
]
# ..

0 голосов
/ 05 сентября 2020

Вот как я это сделал.

Создайте класс для сохранения в базе данных переводов:

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 = {}

Измените метод gettext () 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

Финнали в 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   
...