The Django translation functionality is outlined here in the documentation and requires GNU gettext tools to flag the text that we wish to translate.
Languages
Django Languages
GNU Gettext
Download the precompiled binary installer to start. Ensure you download the correct version such as the 64 bit static and it should be installed to C:\Program Files\gettext-iconv.
In Your Views
Translation can be done on a view to view basis, however for complete usability, I ended up moving all of them to the core app context processor so that they are available on all pages.
from django.shortcuts import render
from django.conf import settings
# The general shorthand syntax is to us gettext as _
from django.utils.translation import gettext as _
from django.utils.translation import get_language, activate, gettext
def index(request):
'''Return the homepage'''
# Translations for the page using the translate function defined below
trans = translate(language=get_language() or settings.LANGUAGE_CODE)
context = {
'MEDIA_URL': settings.MEDIA_URL,
'DEBUG': settings.DEBUG,
# list the variables for the page defined in translation function below
'hotel_name': trans['hotel_name'],
}
return render(
request,
'homepage/index.html',
context,
)
# Define a translate function that was called in the above request
def translate(language):
'''Function to translate text'''
# get the current language
cur_language = get_language()
translations = {} # Ensure it is defined as an empty dictionary even if activation fails
# Try to activate the language you pass as a parameter
try:
activate(language)
# Select and define translations
translations = {
#use _ to identify the strings, same as gettext() because we imported it as _
'hotel_name': _('Hotel Name')
}
finally:
# If you cannot activate, activate the current language
activate(cur_language)
# Return translations
return translations
In the Template
At the top of the page have:
{% load i18n %}
Then you can call the templating language translate to automatically translate something (not recommended).
<h1>{% translate "Hotel Name" %}</h1>
Or just pass the variable you have defined.
<h1>{{ hotel_name }}</h1>
Update settings.py
Add the relevant imports to the top of the file.
# Import gettext_lazy at the top using the shorthand of _
from django.utils.translation import gettext_lazy as _
In the Internationalization section, add a LANGUAGES variable which will be a list of tuples. The tuples will be the language code as a string and the gettext_lazy of the language name. Then update your LANGUAGE_CODE variable to show the default language that you want for your website and add a LOCALE_PATHS to have the pathway of the stored location. We have not created this folder yet but the accepted name is 'locale'.
LANGUAGES = [
('en', _('English')),
('ka', _('Georgian')),
]
LANGUAGE_CODE = 'en'
LOCALE_PATHS = [
BASE_DIR / 'locale', # Path where translation files will be stored
]
# Make the following True:
USE_I18N = True
USE_L10N = True
USE_TZ = True
Add locale middleware to middleware. It needs to go after sessions (.SessionMiddleware) because it will run in a session but above common (.CommonMiddleware) because common deals with the URL and we will set up the URLs depending on the language.
MIDDLEWARE = [
…
'django.contrib.sessions.middleware.SessionMiddleware',
'django.middleware.locale.LocaleMiddleware', # Languages
'django.middleware.common.CommonMiddleware',
…
]
Make a Locale Folder
In the root directory create a locale folder. Inside it, create a folder for each language named after their language code e.g. locale/en.
Create Translation Files
With having trans variables in the templates you can run the translation tool to create translation files.
python manage.py makemessages --all -i requirements.txt
- This will ignore the requirements.txt file, which is not utf-8 and would cause errors
- It creates .po files in the folder in locale for each language e.g. in locale/en
- It works by looking for the translations from views
The .po files will be a list of the translations. They will have:
- A comment of the location where the gettext translation was specified
- An msgid which shows what the gettext function was called on
- An msgstr which shows what string will be shown for that language
#: .\homepage\views.py:12
msgid "Hotel Name"
msgstr ""
You can now go through these files and update the msgstr strings to show what you want displayed. The benefit of doing it this way instead of automatic translation is that you can have paragraphs translated so that their message is still clear and the prose flows well rather than a disjointed word by word translation.
With all your translations written, you can then compile them.
python manage.py compilemessages
URLs
In your project level urls.py file you can create a function to redirect the language to the default language if none is selected.
def redirect_to_default_language(request):
"""Force redirect to default language unless another language is explicitly set."""
language = get_language_from_request(request) or 'en'
# Override browser preference and force default language if no language cookie exists
if 'django_language' not in request.COOKIES:
language = 'en' # Force default language
response = redirect(f'/{language}/')
response.set_cookie('django_language', language) # Store language preference
return response
Then in your urlpatterns you can add in this redirect to the homepage so that the default language is selected when a user first comes to your website.
urlpatterns = [
path('admin/', admin.site.urls),
path('', redirect_to_default_language), # Redirect `/` to preferred or default language
]
You can then add your app urls to the urlpatterns by wrapping them in i18n_patterns() to automatically insert a language code at the start of the url.
urlpatterns += i18n_patterns(
path('', include('homepage.urls')),
)
Language Dropdown
You will need a way for the user to decide which language they want to use. Here is a simple language dropdown menu.
<ul class="dropdown-menu" aria-labelledby="dropdownMenuButton">
{% get_current_language as LANGUAGE_CODE %}
{% get_available_languages as LANGUAGES %}
{% get_language_info_list for LANGUAGES as languages %}
{% for lang in languages %}
<li>
<a class="dropdown-item" href="/{{ lang.code }}/">
{{ lang.name_local }}
</a>
</li>
{% endfor %}
</ul>
Adding a New Translation
Adding a new translation is simple.
-
In the view or context processor add a new translation
'welcome_message': _('Welcome to the website!')
-
Add it to the .po files
python manage.py makemessages --all -i requirements.txt
- Go to .po files and find "Welcome to the website!" and add translations
-
Compile the translations
python manage.py compilemessages
-
Add to template
{{ welcome_message }}
To change an existing translation, simply find it in your .po file, make the change and run
python manage.py compilemessages