Skip to content

Instantly share code, notes, and snippets.

@ylastapis
Created October 12, 2018 08:06
Show Gist options
  • Save ylastapis/4957cd664e62876987e5a14e1c3401fa to your computer and use it in GitHub Desktop.
Save ylastapis/4957cd664e62876987e5a14e1c3401fa to your computer and use it in GitHub Desktop.
react-intl + typescript + storybook
// .storybook/addons.js
import 'storybook-addon-intl/register';
// components/Any.ts
import * as React from 'react';
import { FormattedMessage, InjectedIntlProps } from 'react-intl';
export interface AnyMapStateToProps {
// your state actions here
}
export interface AnyMapDispatchToProps {
// your dispatch actions here
}
export interface AnyOwnProps {
location: Location;
}
type MergedProps = AnyMapStateToProps & AnyMapDispatchToProps & AnyOwnProps & InjectedIntlProps;
export class Any extends React.Component<MergedProps, {}> {
render() {
return (<FormattedMessage id="login.email" />);
}
}
// components/AnyContainer.ts
import { AppState } from 'src/store';
import { connect } from 'react-redux';
import { Dispatch } from 'redux';
import { Any, AnyMapDispatchToProps, AnyMapStateToProps } from 'src/components/Any';
import { injectIntl } from 'react-intl';
const mapStateToProps = (state: AppState) => ({
// your state actions here
});
const mapDispatchToProps = (dispatch: Dispatch<any>) => ({
// your dispatch actions here
});
export const AnyContainer =
injectIntl(
connect<AnyMapStateToProps, AnyMapDispatchToProps>(
mapStateToProps,
mapDispatchToProps
)(Any)
)
;
// store/app-state.ts
import { IntlState } from 'react-intl-redux';
export interface AppState {
intl: IntlState;
}
// .storybook/config.js
import { addDecorator, configure } from '@storybook/react';
import { setIntlConfig, withIntl } from 'storybook-addon-intl';
import { addLocaleData } from 'react-intl';
import enLocaleData from 'react-intl/locale-data/en';
import frLocaleData from 'react-intl/locale-data/fr';
import {getFlattenedMessages} from "../src/utils/locale";
addLocaleData(enLocaleData);
addLocaleData(frLocaleData);
// Set intl configuration
setIntlConfig({
locales: ['en', 'fr'],
defaultLocale: 'en',
getMessages: (locale) => getFlattenedMessages(locale)
});
// Register decorator
addDecorator(withIntl);
const req = require.context('../src/components', true, /\.stories\.js$/)
function loadStories() {
req.keys().forEach((filename) => req(filename))
}
configure(loadStories, module);
// translations/en.ts
export default {
login: {
email: 'EN email',
password: 'EN password',
}
};
// translations/fr.ts
export default {
login: {
email: 'FR email',
password: 'FR password',
}
};
// store/index.ts
import { reducer } from './reducers';
import { getFlattenedMessages } from 'src/utils/locale';
const initialState = {
intl: {
locale: 'en',
messages: getFlattenedMessages('en')
},
};
export const store = createStore(
reducer,
initialState,
composeWithDevTools(
applyMiddleware(
...middlewares
)
)
);
import * as React from 'react';
import * as ReactDOM from 'react-dom';
import { addLocaleData } from 'react-intl';
import { Provider } from 'react-redux';
import { IntlProvider } from 'react-intl-redux';
import * as fr from 'react-intl/locale-data/fr';
import { store } from 'src/store';
import registerServiceWorker from './registerServiceWorker';
import './index.css';
import { AppContainer } from './components/App';
addLocaleData(fr);
const { locale, messages } = store.getState().intl;
ReactDOM.render(
<Provider store={store}>
<IntlProvider
locale={locale}
messages={messages}
>
<AppContainer />
</IntlProvider>
</Provider>,
document.getElementById('root') as HTMLElement
);
registerServiceWorker();
// utils/locale.ts
import localeDataFr from '../translations/fr';
import localeDataEn from '../translations/en';
export function flattenMessages(nestedMessages: {}, prefix: string = '') {
return Object.keys(nestedMessages).reduce((messages, key) => {
const value = nestedMessages[key];
const prefixedKey = prefix ? `${prefix}.${key}` : key;
if (typeof value === 'string') {
messages[prefixedKey] = value;
} else {
Object.assign(messages, flattenMessages(value, prefixedKey));
}
return messages;
}, {});
}
export function getFlattenedMessages(lang: string) {
return lang === 'fr' ? flattenMessages(localeDataFr) : flattenMessages(localeDataEn);
}
// store/reducers.ts
import { combineReducers } from 'redux';
import { intlReducer } from 'react-intl-redux';
export const reducer = combineReducers({
intl: intlReducer,
});
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment