DEV Community

Sébastien Belzile
Sébastien Belzile

Posted on

Embedding the formatting of currencies, dates and much more in i18next

Formatting currencies is a common problem. Let's say you are working on a website that supports multiple language, and is active in multiple countries. One of the problems that you will face is formatting an amount with a currency in a string that contains text. Example:

En: This will be $7.99.
Fr: This will be 7,99$.
Enter fullscreen mode Exit fullscreen mode

Valid solution

One way of solving this problem is to have 2 distinct processes and call them one by one:

const amount: number = 7.99;
const formattedAmount = toCurrency(amount);
t("This will be {{ amount }}", { amount: formattedAmount });
Enter fullscreen mode Exit fullscreen mode

This solution valid, but it could be nice to delegate this boilerplate to i18next.

i18next solution

Interpolation in i18next accepts a format function that can be implemented to handle formatting.

In your configuration:

interpolation: {
  escapeValue: false,
  // Add this line
  format: (value, format) => (format === "currency" ? toCurrency(value) : value),
},
Enter fullscreen mode Exit fullscreen mode

Then, in your code:

t("This will be {{ amount, currency }}.", { amount: 12 })
Enter fullscreen mode Exit fullscreen mode

This should format the currency properly.

Top comments (2)

Collapse
 
lukeshiru profile image
Luke Shiru

Worth mentioning that browsers nowadays have Intl which includes NumberFormat and that can format different currencies without the need of an entire library. So if you need to have something super simple translated, then you can replicate your example in JS without libraries:

// Curried Intl.NumberFormat.format 
const numberFormat = options => locale =>
    new Intl.NumberFormat(locale, options).format;

// We create a formater for euros
const formatEuros = numberFormat({
    style: "currency",
    currency: "EUR"
});

// And we localize that formatter to en-US
const formatEurosEnUS = formatEuros("en-US");

`This will be ${formatEurosEnUS(12)}`; // This will be €12.00
Enter fullscreen mode Exit fullscreen mode

Good thing about this approach is that it makes easy to implement different languages, and is all leveraged to the actual browser:

const formatDolars = numberFormat({
    style: "currency",
    currency: "USD"
});
const formatEurosEsAR = formatEuros("es-AR");
const formatDolarsEnUS = formatDolars("en-US");
const formatDolarsEsArs = formatDolars("es-AR");
Enter fullscreen mode Exit fullscreen mode

Or instead of doing it manually, you could also just use whatever the user has set:

// Manually:
const { language } = navigator;
const formatEurosLocal = formatEuros(language);
const formatDolarsLocal = formatDolars(language);

// Or automatic (the default is the user set language):
const formatEurosLocal = formatEuros();
const formatDolarsLocal = formatDolars();
Enter fullscreen mode Exit fullscreen mode

Cheers!

Collapse
 
sbelzile profile image
Sébastien Belzile

Indeed, thanks for adding the actual currency formatting implementation part!