I support several languages in my application and use React-intl for this. I have the Redux middleware where I make a call to the server and in the case of error I want to show an error on the UI.
I know that I can do something like:
1) dispatch an action from middleware with a message key:
{type: SHOW_ERROR, message: 'message_error_key'}
2) in my React component use:
<FormattedMessage id={this.props.message_error_key}/>
But is there a way to dispatch an action with already translated message from middleware?
{type: SHOW_ERROR, message: [translated_message_should_be_here]}
It might not be the prettiest solution, but here's how we solved this problem;
1) First we created a 'IntlGlobalProvider' component that inherits the context and props from the IntlProvider in our component tree;
<ApolloProvider store={store} client={client}>
<IntlProvider>
<IntlGlobalProvider>
<Router history={history} children={routes} />
</IntlGlobalProvider>
</IntlProvider>
</ApolloProvider>
2) (inside IntlGlobalProvider.js) Then out of the context we get the intl functionality we want and expose this by a singleton.
// NPM Modules
import { intlShape } from 'react-intl'
// ======================================================
// React intl passes the messages and format functions down the component
// tree using the 'context' scope. the injectIntl HOC basically takes these out
// of the context and injects them into the props of the component. To be able to
// import this translation functionality as a module anywhere (and not just inside react components),
// this function inherits props & context from its parent and exports a singleton that'll
// expose all that shizzle.
// ======================================================
var INTL
const IntlGlobalProvider = (props, context) => {
INTL = context.intl
return props.children
}
IntlGlobalProvider.contextTypes = {
intl: intlShape.isRequired
}
// ======================================================
// Class that exposes translations
// ======================================================
var instance
class IntlTranslator {
// Singleton
constructor() {
if (!instance) {
instance = this;
}
return instance;
}
// ------------------------------------
// Formatting Functions
// ------------------------------------
formatMessage (message, values) {
return INTL.formatMessage(message, values)
}
}
export const intl = new IntlTranslator()
export default IntlGlobalProvider
3) Import it anywhere as a module
import { defineMessages } from 'react-intl'
import { intl } from 'modules/core/IntlGlobalProvider'
const intlStrings = defineMessages({
translation: {
id: 'myid',
defaultMessage: 'Hey there',
description: 'someStuff'
},
intl.formatMessage(intlStrings.translation)