将Redux存储与i18next LanguageDetector同步

时间:2019-06-20 13:17:39

标签: reactjs redux react-redux i18next react-i18next

我想跟踪Redux商店(store.l10n.locale)中的当前语言环境,但是由于插件检测用户语言可能无法更改而不会触发任何动作,因此在初始化时无法执行此操作。 ..

当用户选择一种语言时,我设法将Redux存储与当前语言环境同步,我什至听了活动URI中的语言环境参数更改(由于HOC,请参见下文)以触发操作。

这是我的i18n初始化文件:

import i18n from 'i18next'
import Backend from 'i18next-xhr-backend'
import LanguageDetector from 'i18next-browser-languagedetector'
import { initReactI18next } from 'react-i18next'
import moment from 'moment'

i18n
  // Load translation using xhr from /public/locales.
  .use(Backend)
  // Detect user language.
  .use(LanguageDetector)
  // Pass the i18n instance to react-i18next.
  .use(initReactI18next)
  // Init i18next.
  .init({
    fallbackLng: 'en',
    debug: true,

    interpolation: {
      // Not needed for React as it escapes by default.
      escapeValue: false,
      format: (value, format, lng) => {
        if (value instanceof Date) return moment(value).format(format)
        return value
      }
    }
  })

// Keep the language on moment.js in sync with i18next
// by listening to the change language event.
i18n.on('languageChanged', newlocale => {
  moment.locale(newlocale)
})

export default i18n

这是我的l10n切片(动作类型,动作创建者,减速器...):

import { createSlice } from 'redux-starter-kit'
import { defaultLocale } from '../i18n/config'

const initialState = {
  locale: defaultLocale
}

const l10n = createSlice({
  slice: 'l10n',
  initialState: initialState,
  reducers: {
    changedLocale(state, action) {
      // 'Mutating' the state is possible
      // with the `createSlice()` function from `redux-starter-kit`
      // because it ships with the immer library.
      state.locale = action.payload
    }
  }
})

export default l10n
export const { reducer: l10nReducer, actions: l10nActions } = l10n
export const { changedLocale } = l10nActions

这是根据活动URI设置当前语言环境的HOC:

import React from 'react'
import { bindActionCreators } from 'redux'
import { connect } from 'react-redux'
import { withTranslation } from 'react-i18next'
import { withRouter } from 'react-router-dom'

import { getLocaleFromPath } from '../../../utils/l10n'
import { changedLocale } from '../../../ducks/l10n'

class L10nHOC extends React.Component {
  constructor(props) {
    super(props)

    this.setLocale(getLocaleFromPath(this.props.location.pathname), true)

    this.props.history.listen(location => {
      this.setLocale(getLocaleFromPath(location.pathname))
    })

    // this.props.i18n.on('languageChanged', lng => {
    //   this.props.changedLocale(lng)
    // })
  }

  setLocale = (newLocale, force = false) => {
    // if (force || newLocale !== this.props.locale) {
    if (force || newLocale !== this.props.i18n.language) {
      this.props.i18n.changeLanguage(newLocale)
      this.props.changedLocale(newLocale)
    }
  }

  render() {
    return this.props.children
  }
}

const mapStateToProps = state => ({
  // locale: state.l10n.locale
})

const mapDispatchToProps = dispatch =>
  bindActionCreators(
    {
      changedLocale
    },
    dispatch
  )

export default withRouter(
  withTranslation()(
    connect(
      mapStateToProps,
      mapDispatchToProps
    )(L10nHOC)
  )
)

但是,由于我的国际化解决方案位于react('react-i18next')之上,因此我使用了插件来检测用户语言('i18next-browser-languageDetector')。该插件可能会更改当前的语言环境,但是此更改不会反映在我的Redux存储中。

我想我应该“听”语言变更事件,这就是我在i18next API doc之后的HOC中尝试过的事情:

    this.props.i18n.on('languageChanged', lng => {
      this.props.changedLocale(lng)
    })

但是,它不起作用,因为该用户最初是从(例如)在法国,显示的语言是法语,但是商店仍处于其initialState(默认语言为“ en”)。

控制台显示确实检测到并更改了语言:

i18next.js:27 i18next::backendConnector: loaded namespace translation for language en {public: "This content is public...", private: "This content is private!", …}
i18next.js:27 i18next::backendConnector: loaded namespace translation for language fr {public: "Ce contenu est public...", private: "Ce contenu est privé !", …}
i18next.js:27 i18next: languageChanged fr
i18next.js:27 i18next: initialized {debug: true, initImmediate: true, ns: Array(1), defaultNS: Array(1), fallbackLng: Array(1), …}
i18next.js:27 i18next: languageChanged fr

预先感谢您的帮助...

0 个答案:

没有答案