What's the correct way to set up Django translation?

I've got an issue with translations not working on Django 1.6. I've added this to my settings.py:

LANGUAGE_CODE = 'en-us'
ugettext = lambda s: s
LANGUAGES = (
    ('en', ugettext('English')),
    ('de', ugettext('German')),
)

Also added middlewares:

MIDDLEWARE_CLASSES = (
    'django.middleware.common.CommonMiddleware',
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.locale.LocaleMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

as well as to my *.py files whenever I'm using a string which shall be l10nd:

from django.utils.translation import ugettext_lazy as _

My templates start with:

{% extends "base.html" %}
{% load i18n %}

and inside the template I used the trans placeholder. E.g.

<h1>{% trans "Register a tank" %}</h1>

I have provided translations in locale/de/LC_MESSAGES/django.po:

msgid "Register a tank"
msgstr "Einen neuen Tank anmelden"

My browser is set to request German content first: Browser settings

What did I miss?

P.S. The project I'm currently fuzzy around is hosted on GitHub: https://github.com/frlan/blankspot


Add LOCALE_PATHS to settings.py and set it as below:

import os
BASE_DIR = os.path.dirname(os.path.dirname(__file__))

LOCALE_PATHS = (
    os.path.join(BASE_DIR, 'locale'),
)

Note that LOCALE_PATHS must be a tuple (look at the comma at the end of the path).

Now based on LOCALE_PATHS, the locale folder should be in the root of your project.

And be sure that you run the commands django-admin.py makemessages -l de and django-admin.py compilemessages from the root of your project.

djPrj
  |
  +---> djPrj
  |
  +---> djApp
  |
  +---> locale
  |
  +---> templates

Also rearrange your MIDDLEWARE_CLASSES to be LocaleMiddleware after SessionMiddleware and before CommonMiddleware as mentioned here:

MIDDLEWARE_CLASSES = (
    'django.contrib.sessions.middleware.SessionMiddleware',
    'django.middleware.locale.LocaleMiddleware',
    'django.middleware.common.CommonMiddleware',
    'django.middleware.csrf.CsrfViewMiddleware',
    'django.contrib.auth.middleware.AuthenticationMiddleware',
    'django.contrib.messages.middleware.MessageMiddleware',
    'django.middleware.clickjacking.XFrameOptionsMiddleware',
)

Restart your service (python manage.py runserver) and check again.


Just to ensure that your localization is applied to your Django admin page with the default django.mo file of Django, do the following test:

First in main urls.py of project replace patterns with i18n_patterns:

from django.conf.urls.i18n import i18n_patterns

urlpatterns = i18n_patterns('',
    url(r'^admin/', include(admin.site.urls)),
    # ...
)

Now go to the admin page with a de prefix, like: http://127.0.0.1:8000/de/admin/ And the admin page should be shown in German.

OK, are you able to see the admin page of Django in German?

Also check your view with the de prefix too.


According to your project code, some sentences are not in trans blocks. Put them as:

{% trans "your sentence" %}

Also you must use ugettext_lazy instead of ugettext in your code for views and models (Read here and here.)

Replace this:

from django.utils.translation import ugettext as _ 

with:

from django.utils.translation import ugettext_lazy as _

And now everything will work.


In my case, I used en-gb as the parameter to run

django-admin.py makemessages -l en-gb

Instead, it should be en_GB.

django-admin.py makemessages -l en_GB


Please set translated string in django.po and then use python manage.py compilemessages

for e.g 

#: path/to/python/module.py:23
msgid "Welcome to my site."
msgstr "put appropriate translated string here"

Suggestion-: You can use django-rosetta package to add translated string from UI interface. It is easy to add T-string from django-admin. https://github.com/mbi/django-rosetta


Check the cookies and the session -- according to How Django Discovers Language Preference, the process is this:

  1. language prefix in the URL, when using i18n_patterns in URLconf
  2. _language key in the current user's session
  3. django_language cookie (or as specified by settings.LANGUAGE_COOKIE_NAME)
  4. Accept-Language HTTP header (this is what your browser setting sends)
  5. settings.LANGUAGE_CODE

Since your browser settings are set to prefer 'de', I suspect the LocaleMiddleware must decide otherwise in one of the previous steps 1. - 3.