Introducing the twiml-i18n Library

Programmers and developer teams are coding and developing software.
February 22, 2024
Written by
Reviewed by

Introducing the twiml-i18n Library

In today’s rapidly globalizing world, it is a requirement rather than an option for applications to provide support for various languages and regions – for web applications as well as text-based interactions via the phone. This is referred to as Internationalization (i18n). Implementing i18n can be a complex process, but fortunately there are many i18n libraries available for various programming languages. However, because there are so many options, we often find ourselves managing multiple dependencies.

Today, we are pleased to introduce the new Twilio Labs new open-source twiml-i18n package specifically designed to simplify this process. This plugin not only supports Express but also Fastify .

Blog post cover image

Introduction to i18n

Before we delve into the specifics of our package, it's important to understand what i18n is. I18n is the process of developing products in such a way that they can be localized for languages and cultures easily. In the context of programming, it typically involves providing support for multiple languages and adapting date and time formats, among other regional customs.

Challenges of Internationalizing TwiML Responses

Twilio's TwiML is a versatile XML-based language that enables developers to control phone calls or messaging flows. However, when it comes to making TwiML responses multilingual, things can get difficult.

Traditional i18n packages are often too generic; they look at various language indications in the query parameters, session, cookies or HTTP headers. But they aren't optimized for TwiML messages, which need to check for the country code of the phone number that is calling/texting-in. This forces developers to spend extra time on custom configurations, or worse, opt for multiple packages to fulfill their needs. The latter approach leads to another issue - synchronization between packages. Using different packages to translate, format dates, and handle plurals might lead to compatibility issues.

Our Solution - The One-Stop-Shop Package

Our new twiml-i18n project has been developed to address these challenges. It simplifies complexities and saves time, by providing all necessary i18n features in a single package. This tool can be used to internationalize TwiML responses across your entire application or selectively at a specific route, making it a flexible solution for diverse projects.

twiml-i18n looks up the country code for the phone number that sent the message (or made the call). With this information, it determines the language for the response. Note that some countries , such as Switzerland have multiple official languages and other countries, such as Antarctica don’t have any. In case there are multiple languages, we currently decided on the first one mentioned in the reference data (languages column).
npm add @twilio-labs/twiml-i18n

Straightforward integration with Express and Fastify

Whether you are building a web application using Express or Fastify, twiml-i18n has you covered as itt seamlessly integrates with both of these frameworks.

For Express, it can be used as a middleware for the entire application or a specific route.

// Require dependencies
const express = require("express");
const bodyParser = require("body-parser");
const twilio = require("twilio");
const twimlI18n = require("@twilio-labs/twiml-i18n");
const en = require("./locale/en.json");
const de = require("./locale/de.json");

// Initialize express
const server = express();
const port = process.env.PORT || 3000;
server.use(bodyParser.urlencoded({ extended: false }));

// Handle incoming messages
server.post(
  "/webhook",
  twimlI18n.i18n({
    fallbackLng: "en",
    resources: {
      en,
      de,
    },
  }),
  async (request, reply) => {
    const req = request;
    const twimlResponse = new twilio.twiml.MessagingResponse();
    twimlResponse.message(req.t("hello"));
    twimlResponse.message(req.t("placeholder", { number: request.body.From }));
    reply.type("text/xml");
    reply.send(twimlResponse.toString());
  },
);

// Start server
server.listen({ port }, (err) => {
  if (err) {
    console.error(err);
    process.exit(1);
  }
  console.info(`Server started on ${port}`);
});

For Fastify, it can be registered as a plugin.

// Require dependencies
const Fastify = require("fastify"),
  { twiml } = require("twilio"),
  { i18nPlugin } = require("twiml-i18n");

// Initialize Fastify
const server = Fastify();

server.register(require("@fastify/formbody"));

// Setup i18n plugin
server.register(i18nPlugin, {
  fallbackLng: "en",
  resources: {
    en: require("./locale/en.json"),
    de: require("./locale/de.json"),
    // Add more languages as needed
  },
});

// Handle incoming messages
server.post("/webhook", async (req, res) => {
  const twimlResponse = new twiml.MessagingResponse();
  const localizedGreeting = req.t("hello");
  twimlResponse.message(localizedGreeting);
  res.type("text/xml");
  res.send(twimlResponse.toString());
});

// Start server
const port = process.env.PORT || 3000;
server.listen({ port }, function (err) {
  if (err) {
    server.log.error(err);
    process.exit(1);
  }
  console.info(`Server started on ${port}`);
});

Both web servers lookup the localized strings from the locale/ folder that contains JSON files like en.json

{
  "translation": {
    "hello": "Ahoy World",
    "placeholder": "Your number is {{number}}"
  }
}

Conclusion

Mastering the art of internationalization is critical in today’s globally connected digital world. With our i18n package for TwiML responses twiml-i18n, internationalizing your web applications is a breeze. Whether you're using Express or Fastify, our package’s seamless integration and robust features make it the ultimate tool for your i18n needs.

Next Steps

As we continue to enhance and develop features, remember that twiml-i18n is open to contributions. Install it today and let us know what you think!

We currently don't support twiml-i18n through our official support channels. But you are welcome to reach out to us on GitHub for any questions, issues or suggestions or to contribute to this project.

Marius is a Developer Evangelist at Twilio who's a regular at various developer events in the DACH-Region. When not on the road, he works on innovative demo use cases that he shares on this blog and GitHub. You can contact him via the following channels if you have any questions: