Skip to main content Skip to footer

Template Literals Formatting and Globalization

Template literals are a great JavaScript feature introduced in ES2015/ES6. They allow you to build multiline strings with interpolated values and make it easy to handle single and double quotes embedded in your strings. It's much easier/cleaner to write:

var address = `${street}
${city}
${country}`;

...than the more traditional alternative:

var address = street + '\r\n' +
    city + '\r\n' +
    country;

Unfortunately, template literals don't have built-in formatting and globalization, so if you want to create strings that contain dates or numeric values you must use some ugly markup:

console.log(`Today is ${new Intl.DateTimeFormat('en-US').format(new Date())}`);
> Today is 4/15/2019

This works and illustrates the power of using JavaScript within template literals. But using Intl for globalization in this context is not only ugly and inconvenient, but also inflexible and inefficient.

Wijmo has a format method that provides interpolation with formatting and globalization with a simple, flexible, and concise syntax:

import { format } from '@grapecity/wijmo';
console.log(format('Today is {day:d}', { day: new Date() }));
> Today is 4/15/2019

The syntax is clean, and you have a lot of control over formatting of numbers and dates. But you do give up the benefits of the native template literals and the standard literal template syntax.

So how do you get the best of both worlds? There are a couple of simple ways to achieve that.

Using Wijmo's format function in templates

This method is very simple and straightforward. You can call the format function from within the template literals, like we did with Intl in the example above. The syntax looks a lot like React/JSX, where curly brackets allow you embed JavaScript statements into your expressions:

import { Globalize } from '@grapecity/wijmo';
const gf = Globalize.format;
console.log(`Today is ${gf(new Date(), 'd')}, and PI is ${gf(Math.PI, 'n4')}.`);
> Today is 4/15/2019, and PI is 3.1416.

This is simpler and more powerful than using Intl, but we can do better using "tag functions."

Using tag functions to handle formatting and globalization

Template literals can be called with a "tag function" that parses the literals and can apply formatting. The syntax used by tag functions is a little unusual:

console.log(i18n`Today is ${new Date()}:d, and PI is ${Math.PI}:n4.`);
> Today is 4/15/2019, and PI is 3.1416.

OK, this is cool! It's concise, standard, and flexible. You can format dates and numbers in whatever way you like, and you can globalize the output by including the appropriate Wijmo culture file in your app (Wijmo ships with support for over 40 cultures).

Since some date formats include spaces, the formatter function allows for quoted formats. Here's another example to demonstrate:

console.log(
  i18n`Today is ${new Date()}:'MMMM 4, yyyy', and PI is worth ${Math.PI * 1e6}:c.`
);
> Today is April 4, 2019, and PI is worth $3,141,592.65.

This is the i18n function used in the examples above:

https://stackblitz.com/edit/typescript-jefdew?file=i18n.ts
function i18n(...args) {
    let result = [];
    args[0].forEach((part, index) => {
        if (index > 0) {
            let val = args[index];
            let match = part.match(/:([a-z][0-9]*)/i) || part.match(/:'(.+)'/);
            if (match) {
                let fmt = match[1];
                val = Globalize.format(val, fmt);
                part = part.substr(match[0].length);
            }
            result.push(val); // push formatted interpolation
        }
        result.push(part); // push string part
    });
    return result.join(''); // return the result as a string
}

The function works by enumerating the items in the first argument. These items represent the template parts, i. e. "today is," ":d, and PI is," ":n4." For each item except the first, the function uses a regular expression to check if the part starts with a format specifier. If it does, the interpolated value is replaced with the formatted value, and the format specifier is removed from the part.

Conclusion

Template Literals are a great JavaScript feature. Like most great features, it can be easily extended to support useful scenarios.

In this article, we showed how you can extend Template Literals using a tag function that allows you to use Wijmo's formatting and globalization features in your Template Literals, making it easy to display dates and numbers using whatever format and culture you want.

Happy coding!

Bernardo de Castilho

comments powered by Disqus