Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to fall back to multiple languages in Django at runtime?

I am building a Django app that uses Django's translation features to provide localization to multiple languages. But I am also using Django's translation features to translate certain terminology into different industries based on the currently logged in user's settings.

For example, for an English speaking user working in the learning assessment industry, I want the following behavior:

For a given request to a page:

  1. Look up the user's natural language (e.g., German)
  2. Look up the user's industry (e.g., learning assessment)
  3. Activate the German/Learning Assessment language (e.g., translation.activate("learning-assessment-de")

The "learning-assessment-de" .po file will only translate a subset of all the strings in the project, because it's only there to translate certain industry-specific terminology.

This is the question:

When a string is missing, I want Django to fall back to German (determined in step #1 above) rather than English (the default language in my settings.py).

My default English/German .po files will assume a certain industry.

Is this possible?

like image 476
djsmith Avatar asked Sep 02 '13 16:09

djsmith


People also ask

Is Django multilingual?

Django Simple Multilingual Support for models An inefficient, minimal and utterly simple approach to model translation based on foreign key relations and attribute proxying. The project code is forked from the original project by yazzgoth on Google code.

What is Gettext_lazy in Django?

gettext_lazy is a callable within the django. utils. translation module of the Django project.

How do I translate text in Django?

Use the function django. utils. translation. gettext_noop() to mark a string as a translation string without translating it.


1 Answers

I think it's possible and one of the fastest ways to do this (even if to test if it works) would be to monkey-patch Django translation module to add fallback language support like this (not tested):

from django.utils.translation import trans_real
... # Import other things


# Added `fallback_language` parameter
def do_translate(message, translation_function, fallback_language=None):
    """
    Translates 'message' using the given 'translation_function' name -- which
    will be either gettext or ugettext. 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

    # str() is allowing a bytestring message to remain bytestring on Python 2
    eol_message = message.replace(str('\r\n'), str('\n')).replace(str('\r'), str('\n'))
    t = getattr(_active, "value", None)
    if t is not None:
        result = getattr(t, translation_function)(eol_message)
    else:

        # Use other language as fallback.
        if fallback_language is not None:
            fallback = translation(fallback_language)
            result = getattr(_default, translation_function)(eol_message)

        else:
            if _default is None:
                from django.conf import settings
                _default = translation(settings.LANGUAGE_CODE)
            result = getattr(_default, translation_function)(eol_message)
    if isinstance(message, SafeData):
        return mark_safe(result)
    return result

# Added `fallback_language` parameter
def do_ntranslate(singular, plural, number, translation_function, fallback_language=None):
    global _default

    t = getattr(_active, "value", None)
    if t is not None:
        return getattr(t, translation_function)(singular, plural, number)

    # Use other language as fallback.
    if fallback_language is not None:
       fallback = translation(fallback_language)
       return getattr(fallback, translation_function)(singular, plural, number)

    if _default is None:
        from django.conf import settings
        _default = translation(settings.LANGUAGE_CODE)
    return getattr(_default, translation_function)(singular, plural, number)


# Override Django functions with custom ones.
trans_real.do_translate = do_translate
trans_real.do_ntranslate = do_ntranslate

The two above functions are taken from the django.utils.translation.trans_real module. Just added few lines to these functions. You will also need to modify the other functions (e.g. gettext, ngettext, pgettext) to accept the fallback_language parameter and pass it to the two above ones. Please try if this code works.

Note, that monkey-patching is project-wide - it affects Your whole application and third-party applications too. Alternatively You may take the source of the django.utils.translation.trans_real module as a base to create custom translation functions that will be used only in few places in your application.

like image 130
HankMoody Avatar answered Oct 15 '22 23:10

HankMoody