Skip to content

Instantly share code, notes, and snippets.

@dkarmalita
Last active November 30, 2017 19:06
Show Gist options
  • Save dkarmalita/5250416e7bc48212db15e51752cfbd7c to your computer and use it in GitHub Desktop.
Save dkarmalita/5250416e7bc48212db15e51752cfbd7c to your computer and use it in GitHub Desktop.
Example: React-Intl + Redux (i18n)
import React, { Component, PropTypes } from 'react';
import { render } from 'react-dom';
import { createStore, combineReducers, bindActionCreators } from 'redux'
import { Provider, connect } from 'react-redux';
import {
FormattedDate,
FormattedTime,
FormattedRelative,
FormattedNumber,
FormattedPlural,
FormattedMessage,
IntlProvider, addLocaleData } from 'react-intl';
// utils
// =====
const getBrowserLocale = ()=> {
return (navigator.languages && navigator.languages[0]) ||
navigator.language ||
navigator.userLanguage;
}
const getBrowserLanguage = () => getBrowserLocale().toLowerCase().split(/[_-]+/)[0];
const addLocales = (locales) => {
locales.forEach(locale=>{
addLocaleData(require('react-intl/locale-data/'+locale))
})
}
// types
// =====
const UPDATE_LOCALE = 'UPDATE_LOCALE';
// actions (creators)
// ==================
const createUpdateLocale = locale => ({
type: UPDATE_LOCALE,
payload: locale
});
// config.js
// =====================
const locales = ['en', 'ru', 'it'];
// note: If browser doesn't support Intl (i.e. IE11, then we manually import
// the intl polyfill and locale data.
if (!window.Intl) {
require.ensure([
'intl',
'intl/locale-data/jsonp/en.js',
'intl/locale-data/jsonp/ru.js',
'intl/locale-data/jsonp/it.js',
], (require) => {
require('intl');
require('intl/locale-data/jsonp/en.js');
require('intl/locale-data/jsonp/ru.js');
require('intl/locale-data/jsonp/it.js');
addLocales(locales);
});
}else{
//setTimeout(()=>addLocales(locales), 1000);
addLocales(locales);
}
// note: Suppress [React Intl] console noise for "default message as fallback"
if (process.env.NODE_ENV !== 'production') {
const originalConsoleError = console.error
if (console.error === originalConsoleError) {
console.error = (...args) => {
if (args[0].indexOf('[React Intl] Missing message:') === 0) {
return
}
originalConsoleError.call(console, ...args)
}
}
}
// messages.json
// =========================
// const messages = {"en":{}}
const messages = {
"en": {
"app.helloWorld": "Hello World",
"app.greeting": "Hello, {name}!"
},
"ru": {
"app.helloWorld": "Привет, Мир!",
"app.greeting": "Привет, {name}!"
} }
// conteiner
// =========
const mapStateToIntlProps = (state) => {
return {
locale: state.i18n.locale,
messages: state.i18n.messages
}
}
const IntlProviderConnected = connect(mapStateToIntlProps)(IntlProvider)
// reducer
// =======
const browserLanguage = getBrowserLanguage();
//const browserLanguage = 'az';
const initialState = {
locale: browserLanguage,//'en',
messages: messages[browserLanguage]//'en']//{}
}
const updateLocale = (state, action) => {
const newState = {
...state,
locale: action.payload,
messages: messages[action.payload]
};
return newState;
}
const i18n = (state = initialState, action) => {
switch (action.type) {
case UPDATE_LOCALE:
return updateLocale(state, action);
default:
return state;
}
};
// Main app.js
// ===========
class Root extends Component {
constructor(props) {
super(props);
}
render() {
return <div>
<div>Locale: {this.props.locale}</div>
<input type="button" value={this.props.locale === 'en'?'ru':'en'} onClick={()=>this.props.updateLocale(this.props.locale === 'en'?'ru':'en')}/>
<br/><FormattedMessage
id="app.helloWorld"
defaultMessage={`Hello World`}
/>
<br/><FormattedMessage
id="app.no-translation-msg"
defaultMessage={`This message has no translation.`}
/>
<br/><FormattedDate
value={new Date(1459913574887)}
year='numeric'
month='long'
day='numeric'
weekday='long'
/>
<br/><FormattedDate value={new Date(1459832991883)}/>
<br/><FormattedTime value={new Date(1459832991883)}/>
<br/><FormattedRelative value={Date.now()}/>
<br/><FormattedNumber value={1000}/>
<br/>10 <FormattedPlural
value={10}
one='message'
other='messages'
/>
<br/><FormattedMessage
id='app.greeting'
description='Greeting to welcome the user to the app'
defaultMessage='Hello, {name}!'
values={{
name: <b>Eric</b>
}}
/>
</div>
}
}
const rootReducer = combineReducers({
i18n
})
const store = createStore(rootReducer)
const mapStateToProps = (state) => {
return {
locale: state.i18n.locale,
}
}
const mapDispatchToProps = (dispatch) => {
return {
updateLocale: bindActionCreators(updateLocale, dispatch)
}
}
const ConnectedRoot = connect(mapStateToProps, mapDispatchToProps)(Root)
const appRun = () => {
render(
<Provider store={store}>
<IntlProvider>
<ConnectedRoot/>
</IntlProvider>
</Provider>,
document.getElementById('root')
);
}
appRun();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment