Featured Articles
Article in Code Manual category.
Becoming A Multilingual Super Hero In Django — Part 3
Now that we’ve expanded our arsenal for supporting multilingual applications through Django, we’ve become a Multilingual SuperHero in Django.
If you haven’t read through Part 1 and Part 2 of the series to become a Multilingual Super Hero in Django, I highly encourage you to do that before reading this part of the series. This is the final part of the series where we’ll be focusing on the following:
- Passing context from the request-response cycle to async tasks, so that they can retain the language context depending on user request.
- Switching languages for certain parts of the template.
- Supporting multiple languages in Django Templates.
Let’s look into each of the topics:
Passing Context To Async Tasks
We’ve already seen how Django’s request-response cycle works. We can hook using LocaleMiddleware
to extract language information from the request and set up the appropriate language in Content-Language
header for the client to know the language the response was sent in. But we never thought about async tasks. In order to understand this in a better way, let’s take an example.
We want to send an email whenever a company is registered on our site, but we also want to ensure to use the correct language in the template that was being used while executing the registration logic. So, if someone accessed the registration page in the Chinese language, we want to ensure that the email that they receive is also in the Chinese language.
Let’s have a quick look at this code snippet:
Here we have a celery task named send_company_registration_email_task
accepting an argument for the language code to be used. In this case, since our primary users are Chinese, we default the language code to zh-cn
which stands for Simplified Chinese.
This celery task calls the service to send the company registration email and passes the language code to the service function. Next, we’ll have a look at our service function:
The first thing that we do in our service function is activate the particular language in the current celery task context. We do this in Django with the activate
function which can be found in django.utils.translation
Next, we set up the context for our template rendering process. The send_mail
service function will take care of rendering and the trans
tags inside the template will make sure that the static text will be translated to the language set in the context. Optionally here, we need to also send some links in the email body. Particularly we want to give to the company admin the ability to explore the company onboarding decision page which shows them the accepted or refused status on the page.
The trick here is that if the user is getting an email in Chinese and they open another page on the website through that link, it should be in the same language as in the email.
If the content is targeted at a Chinese user, we cannot show them a page in English or German. Our first preference will always be Chinese.
In Django, we pass the lang_code
to the translate_url
function available in django.urls.base
so that the actual link that will be rendered in the template would contain the language information as shown above.
Notice here that the lang_code
is passed as an argument to our send_company_registration_email
service function. By default, all the links in this application will be in Chinese as we have a default value of zh-cn
for the lang_code
parameter. After all the things are in place regarding the setting of the language context, we just trigger the utility function send_email
which would trigger actual emails through a celery task.
Switching Language in templates for certain parts of the template
Sometimes there is a need to override certain parts of a template to display the text in that language. For example, when the user is visiting your website for the first time, you’d like to display a greeting to them. If this website is for Chinese users, the default language is maybe Chinese — but we’d also like to display the message in English.
The first and foremost thing to do here is to load the internationalization tag at the top of the template.
Next, we use the get_current_language
function to pick up the language set in the current thread context during the rendering of the template. We then present the sentence “Welcome to our page” in Chinese (in case the template is rendered with the language set as Chinese) and the second block of code ensures that we override the language to ‘en
’ and then display the same message. We use the trans
tag for the static string translations as we’ve seen in the previous blog posts.
Supporting multiple languages in Django Templates
You might have already come across sites that showcase a menu icon giving the ability to change the language of the website. This menu item is supposed to display all the languages that the current website supports. Here we’ll see how we can accomplish this task in Django templates.
Consider this code snippet where we use the get_available_languages
function to get all the available languages from the LANGUAGES
setting that we had a look in Part 1 of the series.
languages
is now a dictionary and we iterate over it to get the language code (lang_code
) and language name (lang_name
).
For each language, we then override the context of the page as we did previously and mention the name of the language in the hyperlinks that will be rendered.
Now that we’ve expanded our arsenal for supporting multilingual applications through Django, we’ve become a Multilingual SuperHero in Django.
Although there is more to explore about multilingual applications, we’ve tried to cover almost everything that a developer will use most of the time. This shouldn’t restrict you to just this tutorial and I highly encourage you to explore the Django documentation as it provides numerous utility methods that can help in accomplishing almost any task in your Django application. The trick is to keep expanding your arsenal and always be a Hero. ;)
This brings us to the end of the series of Becoming a Multilingual SuperHero in Django. If you’ve any questions/thoughts/suggestions, please let me know.