Advanced formatting
Message formatting
Basic token replacement
Dojo’s i18n
framework supports ICU message formatting, which also supports basic token replacement.
The message formatting examples in the next two subsections will use a message bundle with a guestInfo
message as follows:
nls/main.ts
export default {
messages: {
guestInfo: '{host} invites {guest} to the party.'
}
};
Replacing tokens in widgets
I18n-aware widgets can use the format
function returned from the i18n
middleware’s localize
method to perform simple token replacement in their messages.
The guestInfo
message can be rendered directly via format
:
widgets/MyI18nWidget.tsx
import { create, tsx } from '@dojo/framework/core/vdom';
import i18n from '@dojo/framework/core/middleware/i18n';
import nlsBundle from '../nls/main';
const factory = create({ i18n });
export default factory(function MyI18nWidget({ middleware: { i18n } }) {
const { format } = i18n.localize(nlsBundle);
return (
<div>
{format('guestInfo', {
host: 'Margaret Mead',
guest: 'Laura Nader'
})}
</div>
// Will render as 'Margaret Mead invites Laura Nader to the party.'
);
});
Direct token replacement formatting
The object returned by the localizeBundle
function from the i18n
module includes a format
method that handles message formatting:
import { localizeBundle } from '@dojo/framework/i18n/i18n';
import bundle from 'nls/main';
localizeBundle(bundle, { locale: 'en' }).then(({ format }) => {
const message = format('guestInfo', {
host: 'Margaret Mead',
guest: 'Laura Nader'
});
console.log(message); // "Margaret Mead invites Laura Nader to the party."
});
ICU message formatting
@dojo/framework/i18n
relies on Globalize.js for ICU message formatting, and as such all of the features offered by Globalize.js are available through @dojo/framework/i18n
.
The message formatting examples in the next two subsections will use a message bundle with an updated guestInfo
message as follows:
nls/main.ts
export default {
messages: {
guestInfo: `{gender, select,
female {
{guestCount, plural, offset:1
=0 {{host} does not give a party.}
=1 {{host} invites {guest} to her party.}
=2 {{host} invites {guest} and one other person to her party.}
other {{host} invites {guest} and # other people to her party.}}}
male {
{guestCount, plural, offset:1
=0 {{host} does not give a party.}
=1 {{host} invites {guest} to his party.}
=2 {{host} invites {guest} and one other person to his party.}
other {{host} invites {guest} and # other people to his party.}}}
other {
{guestCount, plural, offset:1
=0 {{host} does not give a party.}
=1 {{host} invites {guest} to their party.}
=2 {{host} invites {guest} and one other person to their party.}
other {{host} invites {guest} and # other people to their party.}}}}`
}
};
ICU message formatting in widgets
I18n-aware widgets can use the format
function returned from their localizeBundle
method to perform ICU message formatting in the same way as for simple token replacement described above.
The ICU-formatted guestInfo
message can then be rendered as:
widgets/MyI18nWidget.tsx
import { create, tsx } from '@dojo/framework/core/vdom';
import i18n from '@dojo/framework/core/middleware/i18n';
import nlsBundle from '../nls/main';
const factory = create({ i18n });
export default factory(function MyI18nWidget({ middleware: { i18n } }) {
const { format } = i18n.localize(nlsBundle);
return (
<div>
{
format('guestInfo', {
host: 'Margaret Mead',
gender: 'female',
guest: 'Laura Nader',
guestCount: 20
})
}
</div>
]); // Will render as 'Margaret Mead invites Laura Nader and 19 other people to her party.'
);
});
Direct ICU message formatting
The ICU-formatted guestInfo
message can be converted directly with the format
method included on the object returned by localizeBundle
.
import { localizeBundle } from '@dojo/framework/i18n/i18n';
import bundle from 'nls/main';
// 1. Load the messages for the locale.
localizeBundle(bundle, { locale: 'en' }).then(({ format }) => {
const message = format('guestInfo', {
host: 'Margaret Mead',
gender: 'female',
guest: 'Laura Nader',
guestCount: 20
});
console.log(message); // "Margaret Mead invites Laura Nader and 19 other people to her party."
console.log(
format('guestInfo', {
host: 'Marshall Sahlins',
gender: 'male',
guest: 'Bronisław Malinowski'
})
); // "Marshall Sahlins invites Bronisław Malinowski to his party."
});
Date and number formatting.
As with the message formatting capabilities, @dojo/framework/i18n
relies on Globalize.js to provide locale-specific formatting for dates, times, currencies, numbers, and units. The formatters themselves are essentially light wrappers around their Globalize.js counterparts, which helps maintain consistency with the Dojo ecosystem and prevents the need to work with the Globalize
object directly. Unlike the message formatters, the date, number, and unit formatters are not cached, as they have a more complex set of options. As such, executing the various “get formatter” methods multiple times with the same inputs does not return the exact same function object.
@dojo/framework/i18n
groups the various formatters accordingly: date and time formatters (@dojo/framework/i18n/date
); number, currency, and pluralization formatters (@dojo/framework/i18n/number
); and unit formatters (@dojo/framework/i18n/unit
). Each method corresponds to a Globalize.js method (see below), and each method follows the same basic format: the last argument is an optional locale, and the penultimate argument is the method options. If specifying a locale but no options, pass null
as the options
argument. If no locale is provided, then the current (i18n.locale
) is assumed.
import { formatDate, getDateFormatter, formatRelativeTime } from '@dojo/framework/i18n/date';
import { formatCurrency, getCurrencyFormatter } from '@dojo/framework/i18n/number';
import { formatUnit, getUnitFormatter } from '@dojo/framework/i18n/unit';
const date = new Date(1815, 11, 10, 11, 27);
// Assume the current locale is "en"
const enDateFormatter = getDateFormatter({ datetime: 'medium' });
enDateFormatter(date); // Dec 10, 1815, 11:27:00 AM
formatDate(date, { date: 'short' }); // 12/10/15
const frDateFormatter = getDateFormatter({ datetime: 'medium' }, 'fr');
frDateFormatter(date); // 10 déc. 1815 à 11:27:00
formatDate(date, { date: 'short' }, 'fr'); // 10/12/1815
formatRelativeTime(-1, 'week'); // "last week"
formatRelativeTime(-1, 'week', { form: 'short' }); // "last wk."
formatRelativeTime(-3, 'week', null, 'fr'); // "il y a 3 semaines"
formatRelativeTime(-3, 'week', { form: 'short' }, 'fr'); // "il y a 3 sem."
const enCurrencyFormatter = getCurrencyFormatter('USD', { style: 'code' });
enCurrencyFormatter(1234.56); // "1,234.56 USD"
formatCurrency(12345.56, 'USD', { style: 'code' }); // "1,234.56 USD"
const frCurrencyFormatter = getCurrencyFormatter('EUR', { style: 'code' }, 'fr');
frCurrencyFormatter(1234.56); // "1 234,56 EUR"
formatCurrency(12345.56, 'EUR', { style: 'code' }, 'fr'); // "1 234,56 EUR"
const enUnitFormatter = getUnitFormatter('feet', { form: 'narrow' });
enUnitFormatter(5280); // 5,280′
formatUnit(5280, 'feet', { form: 'narrow' }); // 5,280′
const frUnitFormatter = getUnitFormatter('meter', null, 'fr');
frUnitFormatter(1000); // 1 000 mètres'
formatUnit(1000, 'meter', null, 'fr); // 1 000 mètres'
@dojo/framework/i18n/date
methods:
formatDate
=>Globalize.formatDate
formatRelativeTime
=>Globalize.formatRelativeTime
getDateFormatter
=>Globalize.dateFormatter
getDateParser
=>Globalize.dateParser
getRelativeTimeFormatter
=>Globalize.relativeTimeFormatter
parseDate
=>Globalize.parseDate
@dojo/framework/i18n/number
methods:
formatCurrency
=>Globalize.formatCurrency
formatNumber
=>Globalize.formatNumber
getCurrencyFormatter
=>Globalize.currencyFormatter
getNumberFormatter
=>Globalize.numberFormatter
getNumberParser
=>Globalize.numberParser
getPluralGenerator
=>Globalize.pluralGenerator
parseNumber
=>Globalize.parseNumber
pluralize
=>Globalize.plural
@dojo/framework/i18n/unit
methods:
formatUnit
=>Globalize.formatUnit
getUnitFormatter
=>Globalize.unitFormatter