Dynamic loading of message catalogs
I18nProvider
doesn't assume anything about your app and it's your responsibility to load messages based on active language.
Here's an example of a basic setup with a dynamic load of catalogs.
Setup
You don't have to install following Babel plugins if you're using Create React App or similar framework which already has it.
We are using the Dynamic Import() Proposal to ECMAScript. We need to install @babel/plugin-syntax-dynamic-import
and babel-plugin-dynamic-import-node
to make it work. Also, the code examples given here make use of @babel/plugin-proposal-class-properties
.
- npm
- Yarn
npm install --save-dev \
@babel/plugin-syntax-dynamic-import \
babel-plugin-dynamic-import-node \
@babel/plugin-proposal-class-properties
yarn add --dev \
@babel/plugin-syntax-dynamic-import \
babel-plugin-dynamic-import-node \
@babel/plugin-proposal-class-properties
babel-plugin-dynamic-import-node
is required when running tests in Jest.
{
"plugins": [
"@babel/plugin-syntax-dynamic-import",
"@babel/plugin-proposal-class-properties"
],
"env": {
"test": {
"plugins": [
"dynamic-import-node"
]
}
}
}
Final I18n loader helper
Here's the full source of i18n.ts
logic:
import { i18n } from '@lingui/core';
import { en, cs } from 'make-plural/plurals'
export const locales = {
en: "English",
cs: "Česky",
};
export const defaultLocale = "en";
i18n.loadLocaleData({
en: { plurals: en },
cs: { plurals: cs },
})
/**
* We do a dynamic import of just the catalog that we need
* @param locale any locale string
*/
export async function dynamicActivate(locale: string) {
const { messages } = await import(`./locales/${locale}/messages`)
i18n.load(locale, messages)
i18n.activate(locale)
}
How should I use the dynamicActivate in our application?
import React, { useEffect } from 'react';
import App from './App';
import { I18nProvider } from '@lingui/react';
import { i18n } from '@lingui/core';
import { defaultLocale, dynamicActivate } from './i18n';
const I18nApp = () => {
useEffect(() => {
// With this method we dynamically load the catalogs
dynamicActivate(defaultLocale)
}, [])
return (
<I18nProvider i18n={i18n}>
<App />
</I18nProvider>
)
}
Conclusion
Looking at the content of build dir, we see one chunk per language:
i18n-0.c433b3bd.chunk.js
i18n-1.f0cf2e3d.chunk.js
main.ab4626ef.js
When page is loaded initially, only main bundle and bundle for the first language are loaded:
After changing language in UI, the second language bundle is loaded:
And that's it! 🎉