React-Intl outside your component tree

Recently while reworking our app to add multi-language support I came across the need to use the intl api outside of the component structures. I tried a couple of different paths, such as a singleton-like provider that is populated by a wrapper component when it is mounted. This worked fine, but was really ugly.

For my use case I have the need to load the language file (data) from the server at runtime, so we needed a way to dynamically load the intl provider after the fact. I didn’t find a way to do that, so we will have to make sure that the data is available when the components at the root are mounted (not a big deal). What I did find, however, was in their api I can create a new instance of the intl object outside of the provider.

There are some considerations with having two instances of the intl object floating around like memory usage, but for our user load that isn’t really an issue for us. To build this out we need to supply a two character locale string, so for that I am using the package locale2. I don’t think anyone could have made that package any easier to use. Like I mentioned, I needed to load the language data from the server when the page is rendered. To extract the language data, I use simple function to pull it from the window object. Now that I have all that I need, I can create the new intl object and return that as an export.

import { createIntl, createIntlCache } from 'react-intl'
import locale2 from 'locale2'

export const locale = locale2.substring(0, 2)
const cache = createIntlCache()

export const getMessages = () => {
    if (window['messages']) {
        try {
            return window['messages']
        } catch (error) {
            console.error(error)
            throw 'Failed to load messages from server'
        }
    }

    return null
}

export default createIntl(
    {
        locale: locale,
        messages: getMessages()
    },
    cache
)

That was all it took to access the intl object outside of the component tree. Now you can import intl and use it freely.

intl.formatMessage({ id: 'Hello' })

If you have any questions, leave a comment. Cheers