Use JSON to localize(translate) Auth0 email templates based on user language

ParhamParham
9 min read

Background

Answering questions in Auth0 community forum is one of the ways I give back to the community and also learn more about common problems or confusions Auth0 users face.

Recently, I came across a question asking how to customize the Auth0 email templates in a more maintainable way.

Screen Shot 2022-09-22 at 8.30.24 pm.png

Link: https://community.auth0.com/t/localization-and-saving-the-user-language/90515

Auth0 supports email template customization for various emails that is sent to a user as part of different flows, such as verification email, password reset email, and so on. You can use a combination of Liquid and HTML to customize the email templates.

On top of that, Auth0 exposes some variables that you can use in the email templates. Things like the user's name, email, and other information.

Screen Shot 2022-09-16 at 8.28.11 am.png

Screen Shot 2022-09-22 at 8.37.18 pm.png

Here is an example of the variables you can use in the email templates.

<html>
  <head>
    ...
  </head>
  <body>
    <center>
      <p>
        {% if user.user_metadata.lang == 'es' %}
          <b>Hola {{ user.name }}, ...</b>
        {% elsif user.user_metadata.lang == 'it' %}
        <b>Ciao {{ user.name }}, ...</b>
        {% else %}
          <b>Hi {{user.name}} ...</b>
        {% endif %}
      </p>
      <table ...>
        <tr>
          <td>
          ...

You can see that the email template is using Liquid to check the user's language and display the appropriate greeting.

This is a great feature and it allows you to customize the email templates to fit your needs.

Note: You need to set the user's language in the user's metadata. You can do this in different ways which is out of the scope of this article.

What is Liquid?

Liquid is a template language that uses a combination of objects, tags, and filters inside template files to display dynamic content. Auth0 uses Liquid to customize the email template.

Problem

If your application supports multiple languages, you might want to customize the email templates to display the appropriate message based on the user's language.

In a scenario like this, you might end up with a lot of if-else statements in the email template. This can make the email template hard to maintain.

Depending on the number of languages you need to support and the complexity of the email template, this can become a maintenance nightmare.

Add to that, the fact that most users manage the email templates in the Auth0 dashboard, which means:

  • The code is not version controlled

  • Editor experience is limited

  • You can't use any of the tools you use to write code

  • This code is not part of your test and build pipeline which means you can't test it and changes can break the email template

Solution

My solution to the problem is:

1- Keep these email templates as part of our codebase. This way, we can use all the tools we use to manage our code. We can use version control, we can use our editor, we can use our build pipeline, and so on.

2- Use code to generate the email template. This way, we can write reusable, modular code that is easy to maintain.

3- Use JSON to maintain different language translations. This gives us the flexibility to add new languages without having to change the code.

How to do it?

We can use any programming language to generate the email template. In this example, I will be using Node.js and TypeScript.

I have created a GitHub repository that can be used as a starting point for this solution.

The repository contains a simple Node.js application that can be used to generate the email template.

Prerequisites

Project setup

Project code is under the src folder. There are 3 folders inside the src folder:

  • templates folder contains the email templates. These are the templates that will be used to generate the final email template. These templates are written in TypeScript so we can easily use variables and functions inside the them.

  • languages folder contains the language translations. These are JSON files that contain the translations for each language.

  • scripts folder contains the scripts that will be used to generate the final email template.

Screen Shot 2022-09-22 at 9.04.48 pm.png

What is inside the templates folder?

This folder contains a file for each email template. File name are the same as the template name in Auth0 for easy reference.

As an example, I have included a file called verification-email.ts that contains the email template for the verification email.

I have copied the original Auth0 email template and stored it in a variable called html. I am treating the original template as a string. Note that I am using backticks to define the string. This is because I want to use multi-line strings, be able to use variables and also call functions inside the string.

const html = `
...
    <h1>${localizeMessage("welcome")}</h1>
        <p>${localizeMessage("thankYou")}</p>
        <p><a href="{{ url }}">${localizeMessage("confirm")}</a></p>
         <p>
            ${localizeMessage("needHelp")}
         </p>
...
`;

The localizeMessage function is a helper function that will be used to localize the message. It takes a key as an argument and returns the appropriate Liquid if/else statement to support the translation for all available languages.

    {% if user.user_metadata.lang == 'en' %}
        Hello {{application.user}} Welcome to the site


    {% elsif user.user_metadata.lang == 'fr' %}
        Bonjour {{application.user}} Bienvenue sur le site


    {% elsif user.user_metadata.lang == 'jp' %}
        こんにちは{{application.user}}さん。サイトへようこそ。


    {% else %}
        Hello {{application.user}} Welcome to the site
    {% endif %}

So anywhere in the email template I need to localize a message, I can call the localizeMessage function and pass the key as an argument.

There is also an index.ts file that exports an array which contains all the email template names. We will use this variable later in code to decide which templates to include in our build.

  export const templates = ["verification-email"];

What is inside the languages folder?

As an example I have included the translation for English, French and Japanese represented by the files en.json, fr.json, and jp.json respectively.

Each json file is a map of message keys to the translated message. For example, the fr.json file might look like this:

{
    "welcome": "Bonjour {{application.user}} Bienvenue sur le site",
    "thankYou": "Merci de vous être inscrit. Veuillez vérifier votre adresse e-mail en cliquant sur le lien suivant:",
    "confirm": "Confirmer mon compte",
    "needHelp": "Si vous rencontrez des problèmes avec votre compte, n'hésitez pas à nous contacter en répondant à ce mail.",
    "regards": "Cordialement",
    "footer": "Si vous n'avez pas fait cette demande, veuillez nous contacter en répondant à ce mail."
}

For this to work properly, the message keys should be the same as the message keys in all language files.

There is also an index.ts file that exports all the language codes as a single array. This is the array that will be used when deciding which language translation are available and should be included in the generated email template.

What is inside the scripts folder?

This folder contains two main functions:

  • localizeMessage which I described above. This function uses the array of language codes to decide which translations should be included in the generated email template.

  • writeFile which is used to write the generated email template to a file.

and an index.ts file that contains the main function. This function loops over the list of templates exported from templates folder and generates the localized email template for each one.


const generateTemplates = async () => {
    for (const template of templates) {
        const templateContent = require(`../templates/${template}`).default;
        writeFile(template, templateContent);
    }
};

How to run the project?

To run the project, we need to install the dependencies first. You can do that by running npm install in the root folder of the project.

Next we need to build the project. You can do that by running npm run build in the root folder of the project.

Build command will compile the TypeScript code. You can see the compiled JavaScript code in the build folder.

Finally, we need to generate the email templates. You can do that by running npm run generate in the root folder of the project.

This command will generate the email templates and store them in the output folder.

Generated email templates are html files. You can open them in your browser to see the final result. There is a serve script that can be used to serve the generated email templates. You can run npm run serve to start the server.

Note: Build and Output folders are ignored by git. You can change this in the .gitignore file.

How to use the generated email templates?

After you have generated the email templates, you can use them in your Auth0 tenant. You can find the instructions on how to do that in the Auth0 documentation.

Simply open the generated email template in your code editor and copy the content of the file. Then go to the Auth0 dashboard and open the email template you want to customize. Paste the content of the generated email template in the editor and save the changes.

How to add a new language?

To add a new language, you need to add a new JSON file in the languages folder. The file name should be the language code. For example, if you want to add a new language called Spanish, you need to create a file called es.json in the languages folder.

You need to also add the language code to the languages array in the index.ts file in the languages folder.

How to add a new email template?

To add a new email template, you need to add a new file in the templates folder. The file name should be the same as the template name in Auth0. For example, if you want to add a new email template called change-password, you need to create a file called my-template.ts in the templates folder.

Then copy the content of the original email template from Auth0 and paste it in the my-template.ts file and customize it as you like.

Don't forget to add the template name to the templates array in the index.ts file in the templates folder.

Future improvements

  • Add validation for generated HTML files.

  • Integrate the project build and template generation with your project CI/CD pipeline.

  • Use Auth0 Management API to update an email template as part CI/CD pipeline.

  • Add test for templates as part of the CI/CD pipeline. We can automate sending a test email so we can make sure it works as expected before deploying it to production.

Conclusion

In this article, we tested the idea of using code and json language files to localize email templates. We created a simple project that can be used to generate localized email templates for Auth0. This project can be used as a starting point for your own project. You can add more functions to help you process the email templates and make them more dynamic.

For example, you might want to pull some data from other sources like external APIs or databases and use it in your email templates.

You can find the source code for this project on GitHub

Reference

Thanks for reading this article. Please reach out here or on Twitter if you have any feedback or questions.

0
Subscribe to my newsletter

Read articles from Parham directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Parham
Parham

Web & mobile developer, @Auth0Ambassador. Follow me for content on JavaScript, Angular, React, Ionic & Capacitor, Progressive web apps & UI/UX.