Migrate "i18n-provider" to new context API (#8213)

The "i18n-provider" module has been replaced by a new `i18n.js` module
in the `contexts` directory which provides the `t` function via the new
React Context API.

The legacy context API is still used throughout the codebase, so a
legacy context provider has also been added as a shim until we migrate
away from the old API. The migration does require changing every single
place where the `t` function is used, so it is a non-trivial amount of
work. This shim allows us to tackle it one piece at a time without
breaking anything.

This was placed in a new `contexts` directory because it didn't seem
to belong in any existing categories. It certainly isn't a higher-order
component.
feature/default_network_editable
Mark Stacey 5 years ago committed by GitHub
parent 2301d9980e
commit 2b6aff535e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 2
      .storybook/preview.js
  2. 61
      ui/app/contexts/i18n.js
  3. 4
      ui/app/ducks/locale/locale.js
  4. 2
      ui/app/ducks/metamask/metamask.js
  5. 46
      ui/app/helpers/higher-order-components/i18n-provider.js
  6. 16
      ui/app/pages/index.js

@ -1,7 +1,7 @@
import React from 'react'
import { addDecorator, addParameters } from '@storybook/react'
import { withKnobs } from '@storybook/addon-knobs/react'
import I18nProvider from '../ui/app/helpers/higher-order-components/i18n-provider'
import I18nProvider from '../ui/app/contexts/i18n'
import { Provider } from 'react-redux'
import configureStore from '../ui/app/store/store'
import '../ui/app/css/index.scss'

@ -0,0 +1,61 @@
import React, { Component, createContext, useMemo } from 'react'
import PropTypes from 'prop-types'
import { useSelector } from 'react-redux'
import { getMessage } from '../helpers/utils/i18n-helper'
import { getCurrentLocale } from '../ducks/metamask/metamask'
import { getCurrentLocaleMessages, getEnLocaleMessages } from '../ducks/locale/locale'
export const I18nContext = createContext((key) => `[${key}]`)
export const I18nProvider = (props) => {
const currentLocale = useSelector(getCurrentLocale)
const current = useSelector(getCurrentLocaleMessages)
const en = useSelector(getEnLocaleMessages)
const t = useMemo(() => {
return (key, ...args) => (
getMessage(currentLocale, current, key, ...args) ||
getMessage(currentLocale, en, key, ...args)
)
}, [currentLocale, current, en])
return (
<I18nContext.Provider value={t}>
{ props.children }
</I18nContext.Provider>
)
}
I18nProvider.propTypes = {
children: PropTypes.node,
}
I18nProvider.defaultProps = {
children: undefined,
}
export class LegacyI18nProvider extends Component {
static propTypes = {
children: PropTypes.node,
}
static defaultProps = {
children: undefined,
}
static contextType = I18nContext
static childContextTypes = {
t: PropTypes.func,
}
getChildContext () {
return {
t: this.context,
}
}
render () {
return this.props.children
}
}

@ -11,3 +11,7 @@ export default function reduceLocaleMessages (state = {}, { type, value }) {
return state
}
}
export const getCurrentLocaleMessages = (state) => state.localeMessages.current
export const getEnLocaleMessages = (state) => state.localeMessages.en

@ -379,3 +379,5 @@ export default function reduceMetamask (state = {}, action) {
return metamaskState
}
}
export const getCurrentLocale = (state) => state.metamask.currentLocale

@ -1,46 +0,0 @@
import { Component } from 'react'
import { connect } from 'react-redux'
import PropTypes from 'prop-types'
import { getMessage } from '../utils/i18n-helper'
class I18nProvider extends Component {
getChildContext () {
const { localeMessages, currentLocale } = this.props
const { current, en } = localeMessages
return {
/**
* Returns a localized message for the given key
* @param {string} key - The message key
* @param {string[]} args - A list of message substitution replacements
* @returns {string|undefined|null} - The localized message if available
*/
t (key, ...args) {
return getMessage(currentLocale, current, key, ...args) || getMessage(currentLocale, en, key, ...args)
},
}
}
render () {
return this.props.children
}
}
I18nProvider.propTypes = {
localeMessages: PropTypes.object,
currentLocale: PropTypes.string,
children: PropTypes.object,
}
I18nProvider.childContextTypes = {
t: PropTypes.func,
}
const mapStateToProps = (state) => {
const { localeMessages, metamask: { currentLocale } } = state
return {
currentLocale,
localeMessages,
}
}
export default connect(mapStateToProps)(I18nProvider)

@ -5,7 +5,7 @@ import { HashRouter } from 'react-router-dom'
import * as Sentry from '@sentry/browser'
import ErrorPage from './error'
import Routes from './routes'
import I18nProvider from '../helpers/higher-order-components/i18n-provider'
import { I18nProvider, LegacyI18nProvider } from '../contexts/i18n'
import MetaMetricsProvider from '../helpers/higher-order-components/metametrics/metametrics.provider'
class Index extends PureComponent {
@ -27,10 +27,12 @@ class Index extends PureComponent {
return (
<Provider store={store}>
<I18nProvider>
<ErrorPage
error={error}
errorId={errorId}
/>
<LegacyI18nProvider>
<ErrorPage
error={error}
errorId={errorId}
/>
</LegacyI18nProvider>
</I18nProvider>
</Provider>
)
@ -41,7 +43,9 @@ class Index extends PureComponent {
<HashRouter hashType="noslash">
<MetaMetricsProvider>
<I18nProvider>
<Routes />
<LegacyI18nProvider>
<Routes />
</LegacyI18nProvider>
</I18nProvider>
</MetaMetricsProvider>
</HashRouter>

Loading…
Cancel
Save