Skip to content

LocalizationProvider

Staś Małolepszy edited this page Jun 28, 2017 · 5 revisions

In fluent-react, all <Localized> components need access to an instance of the Localization class, the central localization store to which they subscribe. The <LocalizationProvider> component implements the provider pattern known from Redux. Taking advantage of React's context feature, it makes translations available to all localized elements in the app without passing them explicitly.

ReactDOM.render(
    <LocalizationProvider messages={}></LocalizationProvider>,
    document.getElementById('root')
);

The LocalizationProvider component takes one prop: messages. It should be an iterable of MessageContext instances in order of the user's preferred languages. The MessageContext instances will be used by Localization to format translations. If a translation is missing in one instance, Localization will fall back to the next one.

In its simplest form, messages can be an array:

function generateMessages(currentLocales) {
    return currentLocales.map(locale => {
        const cx = new MessageContext(locale);
        cx.addMessages(MESSAGES_ALL[locale]);
        return cx;
    });
}

<LocalizationProvider messages={generateMessages(['en-US'])}></LocalizationProvider>,

In order to avoid having to create all MessageContext instances for all locales up front, it's a good idea to make messages an iterator. The Localization class will iterate over it (caching the items it yields) in case fallback is required.

export function* generateMessages(currentLocales) {
    for (const locale of currentLocales) {
        const cx = new MessageContext(locale);
        cx.addMessages(MESSAGES_ALL[locale]);
        yield cx;
    }
}

<LocalizationProvider messages={generateMessages(['en-US'])}></LocalizationProvider>,

The messages iterable

The design of the LocalizationProvider requires a little bit of work from the developer. The messages iterable needs to be created manually. This is intentional: it gives the most control to the developer with regards to the following three areas:

  • translations - the developer decides where translations are stored and how they're fetched,
  • language negotiation - the developer decides which factors are taken into account for the purpose of the language negotiation, as well as how exactly it's being done (we recommend fluent-langneg),
  • custom extensions - the developer can pass options to the MessageContext constructor to configure its bahavior or to define functions available to translations.

In the future we might end up providing ready-made generators of the messages iterable for the most common scenarios.

One limitation of the current design is that in asynchronous scenarios, all translations (including any fallback) must be fetched at once before <LocalizationProvider> is rendered. See the *-async examples in the examples/ directory for more information.

In the future we might be able to allow async fetching of fallback locales.

Clone this wiki locally