Python i18n - Localizing Transactional Email Templates
Leverage Python, Jinja and i18n Ally to define, localize, and preview transactional emails
Applications which support frontend localization usually also require some localization strategies for backend services. A prominent example is the generation of localized transactional emails. This article discusses i18n strategies and workflows for transactional emails processed via Python backends. It relies mainly upon the following resources:
- Jinja, a versatile templating language for Python
- Postmark’s excellent resource for transactional email templates
- i18n Ally, a VS Code extension for localization
If you are interested in reviewing the complete implementation:
Defining Email Messages
For each “type” or kind of email message, inherit from a generic parent class EmailMessage
, which in turn implements the required attributes and methods (e.g., rendering templates). See the companion repository for a possible implementation.
Instantiate a new message with locales and variables, and retrieve all required attributes for sending localized emails:
Locales and Templates
All locale strings are stored in JSON format. This ensures flexibility with both localization workflow and should be relatively resilient against changing requirements. Global variables are defined across locales, since they usually do not depend on locale context (e.g., company or product names).
Locale strings files contain a global
key and a key for each email message type, for instance email_verification
. The former contain “localized globals”, i.e., strings reusable across various email message types. The latter define all strings of a particular email message type.
Use blocks to inherit the layout from higher order, more generic templates. In the companion repository, a three-layer hierarchical inheritance is proposed (barebone layout with basic styling → reusable email layout → specific email message template). Template files interpolate both locale strings and variables with double curly brace notation.
Define a separate template for plain text emails - add dividers to structure the template without any markup. See Postmark’s best practices for more details about how to format plain text emails.
Besides in template files, variables can be used for interpolating values in localization files with the same notation. Interpolate…
- global strings →
{{product_name}}
- locale-specific strings (“localized globals”) →
{{localized.support_phone_us}}
- variables →
{{variables.operating_system}}
It’s even possible to use more complex Jinja functionality, such as conditional statements, directly within locale strings.
A more maintainable approach however is to offload all logic to the respective templates and only use simple variable interpolation in locale string files for convenience.
Localization Workflow
i18n Ally is a VS Code extension for localization. It integrates with a variety of frameworks (e.g., Vue.js), but can also be used to speed up localization workflows of a static directory of locale JSON files. It even includes features to collaboratively review and discuss localizations.
Previewing Generated Emails
In the companion repository, a sample implementation for a thin utility to generate and serve rendered templates is provided.
- Auto-reload upon detected file changes (templates and locale strings)
- Interactively switch between locale, email type, and format (HTML and plain text)
- Responsive view (e.g., Chrome Devtools) allows viewing rendered templates in various scenarios
- Based on Vue.js and FastAPI, extensible and with minimal overhead
- Work in progress
Sending Email (AWS SES)
Access the class attributes of the instantiated email message for implementing email sending functionality. For illustration purposes, an example for AWS SES is provided below:
Conclusion
Supporting multiple locales for transactional emails requires some additional considerations for templates and locale strings definition. The proposed approach includes classes and additional tooling to implement i18n transactional emails in Python applications.
I hope you found this article informative for how to approach i18n in Python backends!