0

I have a multiple language app (Django 1.11) with a form to create new users. In this form, the error messages when the user send invalid input must come in Portuguese (pt-BR) or English (en-US) based on the selected language. The custom validations and some of the automatic Django messages for validations are well translated, but not the following: "The password is too similar to the username."; "This password is too short. It must contain at least 8 characters." and "This password is too common.". Actually, they are shown in Portuguese, since the LANGUAGE_CODE from settings.py is 'pt-BR'.

I was able to translate some of the automatic messages such "A user with that username already exists." with django.utils.translation.activate as in the following code.

from django.utils.translation import activate
activate(curr_lang)

But this wasn't enough to translate the validations from settings.AUTH_PASSWORD_VALIDATORS. I manually changed the LANGUAGE_CODE from 'pt-BR' to 'en-US' and was able to see the messages only in English. What is the best strategy to translate these messages? As far as I researched, setting LANGUAGE_CODE is not a option, since the results I find suggest the use of django.utils.translation.activate. Thanks in advance

1 Answers1

1

After several tries, I think the solution was:

  1. Add "django.middleware.locale.LocaleMiddleware" to MIDDLEWARE at settings.py (be careful with the order as explained at the documentation)
MIDDLEWARE = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.locale.LocaleMiddleware',
    'django.middleware.common.CommonMiddleware',
...
  1. Add the LANGUAGES const also at settings.py after LANGUAGE_CODE, which has to contain the default language
LANGUAGE_CODE = 'pt-BR'
LANGUAGES = [
  ('pt-BR', 'Portuguese'),
  ('en-US', 'English'),
]
  1. Use Django's default set_language method - on urls.py, add the following line:
urlpatterns = [
....
    url(r'^i18n/', include('django.conf.urls.i18n')),

And, on the html file with the selection of language,

{% load i18n %}
{% load staticfiles %}

<form action="{% url 'set_language' %}" method="post">{% csrf_token %}
    <input name="next" type="hidden" value="{{ redirect_to }}" />
    <select name="language" id="curr_lang" class="select2-single" onchange="this.form.submit()">
        {% get_current_language as LANGUAGE_CODE %}
        {% get_available_languages as LANGUAGES %}
        {% get_language_info_list for LANGUAGES as languages %}
        <option value="pt-BR" title="Português" {% if LANGUAGE_CODE == 'pt-br' %}selected{% endif %}>{% static 'img/flags/br.png' %}</option>
        <option value="en-US" title="English" {% if LANGUAGE_CODE == 'en-us' %}selected{% endif %}>{% static 'img/flags/us.png' %}</option>
    </select>
</form>
  1. On context_processor.py, define a function (I'm calling global_env) to be run at the end of every view. On settings.py, add 'your-application-name-here.context_processor.global_env' such as
TEMPLATES = [
        ...
        'OPTIONS': {
            'context_processors': [
                'your-application-name-here.context_processor.global_env',
                 ...

And, on context_processor.py, the function must have

def global_env(request):
    from django.utils.translation import activate

    curr_lang = request.session[LANGUAGE_SESSION_KEY]
    activate(curr_lang)

    # More code to render dictionary to views for non-default messages on page 
    ....

I think these steps complete the translation of default form validation messages from Django without the need of custom validators.