This guide demonstrates how to get started with Internationalization with react-intl. In fact, if you created your module with the One App Module Generator (highly recommended), most of the work is already done! You can skip ahead to ahead to Accessing Intl in Child Components.
However, if you are creating a module from scratch or to better understand the pieces of internationalization in a module, begin at Component Creation.
Begin with a parent and child component.
Parent.jsx
import React from 'react';
import Child from './Child';
const Parent = () => (
<Child />
);
export default Parent;
Child.jsx
import React from 'React';
const Child = () => <div>greeting</div>;
export default Child;
Next create the locale files. one-app-locale-bundler will bundle the locale files as a part of one-app-bundler. More information about locale folder structure and naming can be found in the README.
Create a folder structure and content as follows (locale must follow BCP-47):
- locale
- en-US.json
- es-MX.json
en-US.json
{
"greeting": "Welcome!"
}
es-MX.json
{
"greeting": "Bienvenidos!"
}
Turn the Parent
component into a module. The parent module will use compose from Redux and holocron
from holocron.
Install Redux and Holocron:
npm i -s redux holocron
Wrap the Parent
component with the Higher-Order Component (HOC) functions. Replace module-name
with the name of the module.
import React from 'react';
import Child from './Child';
const Parent = () => (
<Child />
);
Parent.holocron = {
name: 'module-name',
};
export default Parent;
With the module and locale files created, they need to be loaded into the Redux state. To load a language pack use loadLanguagePack when initializing your module with holocron during loadModuleData
.
Install One App Ducks:
npm i -s @americanexpress/one-app-ducks
Load the language pack during load:
import React from 'react';
import { compose } from 'redux';
import { loadLanguagePack } from '@americanexpress/one-app-ducks';
import Child from './Child';
const Parent = () => (
<Child />
);
export const loadModuleData = ({ store: { dispatch } }) => dispatch(loadLanguagePack('module-name', { fallbackLocale: 'en-US' }));
Parent.holocron = {
name: 'module-name',
loadModuleData
};
export default Parent;
Utilizing mapStateToProps will allow accessing the language pack and locale from the Redux state and provide them as props in the Parent
component.
Install React-Redux, Immutable, and PropTypes:
npm i -s redux react-redux immutable prop-types
Add a mapStateToProps
functionality and update the Parent
component's props.
import React from 'react';
import PropTypes from 'prop-types';
import { compose } from 'redux';
import { loadLanguagePack } from '@americanexpress/one-app-ducks';
import { connect } from 'react-redux';
import { fromJS } from 'immutable';
import Child from './Child';
const Parent = ({ languageData, localeName }) => (
<Child />
);
Parent.propTypes = {
languageData: PropTypes.shape({
greeting: PropTypes.string.isRequired,
}).isRequired,
localeName: PropTypes.string.isRequired,
};
export const loadModuleData = ({ store: { dispatch } }) => dispatch(loadLanguagePack('module-name', { fallbackLocale: 'en-US' }));
Parent.holocron = {
name: 'module-name',
loadModuleData,
};
export const mapStateToProps = (state) => {
const localeName = state.getIn(['intl', 'activeLocale']);
const languagePack = state.getIn(
['intl', 'languagePacks', localeName, 'module-name'],
fromJS({})
).toJS();
return {
languageData: languagePack && languagePack.data ? languagePack.data : {},
localeName,
};
};
export default compose(
connect(mapStateToProps)
)(Parent);
Creating an IntlProvider
from react-intl will allow child components access the intl
information configured for the module.
Install React-Intl:
npm i -s react-intl
Using the locale and language data, initialize an IntlProvider
that wraps the Child
component.
import React from 'react';
import PropTypes from 'prop-types';
import { compose } from 'redux';
import { loadLanguagePack } from '@americanexpress/one-app-ducks';
import { connect } from 'react-redux';
import { fromJS } from 'immutable';
import { IntlProvider } from 'react-intl';
import Child from './Child';
const Parent = ({ languageData, localeName }) => (
<IntlProvider locale={localeName} messages={languageData}>
<Child />
</IntlProvider>
);
Parent.propTypes = {
languageData: PropTypes.shape({
greeting: PropTypes.string.isRequired,
}).isRequired,
localeName: PropTypes.string.isRequired,
};
export const loadModuleData = ({ store: { dispatch } }) => dispatch(loadLanguagePack('module-name', { fallbackLocale: 'en-US' }));
Parent.holocron = {
name: 'module-name',
loadModuleData,
};
export const mapStateToProps = (state) => {
const localeName = state.getIn(['intl', 'activeLocale']);
const languagePack = state.getIn(
['intl', 'languagePacks', localeName, 'module-name'],
fromJS({})
).toJS();
return {
languageData: languagePack && languagePack.data ? languagePack.data : {},
localeName,
};
};
export default compose(
connect(mapStateToProps)
)(Parent);
With the IntlProvider
created in the Parent
component there are several ways to access the intl
information in the Child
component.
With useIntl Hook:
import React from 'react';
import { useIntl } from 'react-intl';
const Child = () => {
const intl = useIntl();
return <div>{intl.messages.greeting}</div>;
};
export default Child;
With injectIntl HOC:
import React from 'react';
import { injectIntl } from 'react-intl';
const Child = ({ intl }) => <div>{intl.messages.greeting}</div>;
export default injectIntl(Child);