Skip to content

Formatting in a multilingual site

Different languages and locations can have radically different formatting styles when it comes to money. For example, ten U.S. dollars in American English should be written down "$10.00". However, in Canadian French, the same amount would be "10,00 $ US".

Dinero.js provides formatting functions that give you full control over how to format a Dinero object.

Building a custom Internationalization formatter

ECMAScript provides an Internationalization API (Intl) that lets you natively format monetary values into a given language by passing a locale. You can create your own Intl formatter by wrapping toDecimal.

js
import { dinero, toDecimal } from 'dinero.js';
import { USD } from '@dinero.js/currencies';

function intlFormat(dineroObject, locale, options = {}) {
  function transformer({ value, currency }) {
    return Number(value).toLocaleString(locale, {
      ...options,
      style: 'currency',
      currency: currency.code,
    });
  }

  return toDecimal(dineroObject, transformer);
};

const d = dinero({ amount: 1000, currency: USD });

intlFormat(d, 'en-US'); // "$10.00"
intlFormat(d, 'fr-CA'); // "10,00 $ US"

INFO

The Internationalization API is well-supported in modern browsers and Node.js. For full locale data in Node.js, make sure to use a build with full ICU support.

Using the custom formatter

You can use the formatter to display monetary values differently according to the current language of your site or app. For example, a React implementation could look like the following.

jsx
import React from 'react';
import { dinero } from 'dinero.js';
import { USD } from '@dinero.js/currencies';

import { intlFormat } from './intlFormat';

const languages = [
  {
    label: 'English (U.S.)',
    locale: 'en-US',
  },
  {
    label: 'Français (Canada)',
    locale: 'fr-CA',
  },
];

function App() {
  const [defaultLanguage] = languages;
  const [language, setLanguage] = React.useState(defaultLanguage);

  const price = dinero({ amount: 1000, currency: USD });

  return (
    <>
      <select
        value={language.locale}
        onChange={(event) =>
          setLanguage(languages.find(({ locale }) => locale === event.target.value))
        }
      >
        {languages.map(({ label, locale }) => (
          <option key={locale} value={locale}>
            {label}
          </option>
        ))}
      </select>
      <p>Price: {intlFormat(price, language.locale)}</p>
    </>
  );
}

Released under the MIT License.