I recently needed a way to override the currently-active language for l10n entirely from Django template code.
tl;dr: {% language 'en' %}
{% load i18n %}
{% language 'fr' %}
{{ event.starts_at|date }}
{% endlanguage %}
This will give us exactly what we want, without any side effects:
samedi, novembre 1
Why I needed it
The context was an ActionKit template that sends a confirmation email using Django’s built-in date filter:
<p>
Thanks for signing up for an event! Here's the details:
</p>
<p>
When: {{ event.starts_at|date }}
</p>
We need the email to go out in the end user’s preferred language. In ActionKit the content (“Thanks for signing up”, etc) is easy to translate by setting up different signup pages with localized after-action emails, but that doesn’t give us access to localize the rendered date — that will still appear in en-us
format1 for all users:
<p>
Merci de vous être inscrit à un événement ! Voici les détails :
</p>
<p>
Quand : Saturday, November 1
</p>
In a full Django project I would typically do this with a bit of Python code right before rendering the email’s template:
translation.activate('fr')
Of course ActionKit doesn’t let us write custom Python code.
It does let us freely edit Django templates though. And luckily, Django provides a way to temporarily activate a specific language in a template, with fine-grained control over the exact context for that language: the language
template tag.
That was exactly what I needed. Each language’s template should just explicitly set its language at the Django level:
{% load i18n %}
{% language 'fr' %}
<p>
Merci de vous être inscrit à un événement ! Voici les détails :
</p>
<p>
Quand : {{ event.starts_at|date }}
</p>
{% endlanguage %}
I needed it for date strings, but it’ll work for any parts of Django that hook into localization: floatformat
, intcomma
and intword
, of course the translate
tag, and so on.
I believe it'll also work for getting locale-specific versions of phrases like “3 days, 8 hours” from timeuntil
and timesince
, which I'm excited to test — I’ve used those to build “recent petition signers” and fundraising deadline components in ActionKit, but I always get stuck without full localization.
Apparently this has been around since Django 1.4 but I have never known about it. Until now!
ActionKit uses a global LANGUAGE_CODE
and doesn’t vary the current Django-side language per end user or per request; instead it mostly uses its own custom i18n system.