在Redux中间件中使用React-intl已翻译的消息

Ant*_*ton 10 reactjs redux-framework redux react-intl react-redux

我在我的应用程序中支持多种语言,并为此使用React-intl.我有Redux中间件,我在那里调用服务器,如果出现错误,我想在UI上显示错误.

我知道我可以这样做:

1)使用消息密钥从中间件调度操作:

{type: SHOW_ERROR, message: 'message_error_key'}
Run Code Online (Sandbox Code Playgroud)

2)在我的React组件中使用:

<FormattedMessage id={this.props.message_error_key}/>
Run Code Online (Sandbox Code Playgroud)

但有没有办法从中间件发送已翻译的消息的动作?

{type: SHOW_ERROR, message: [translated_message_should_be_here]}
Run Code Online (Sandbox Code Playgroud)

Dan*_*mov 8

我不认为你可以formatMessage直接从中间件访问,因为它似乎只暴露给组件injectIntl.您可能会提出一个问题来描述您的用例,并且可能formatMessage()会考虑在组件外部访问的普通JavaScript API ,但现在似乎不可用.


Sim*_*lai 7

它可能不是最漂亮的解决方案,但这就是我们如何解决这个问题;

1)首先,我们创建了一个'IntlGlobalProvider'组件,它继承了组件树中IntlProvider的上下文和props;

<ApolloProvider store={store} client={client}>
  <IntlProvider>
      <IntlGlobalProvider>
          <Router history={history} children={routes} />
      </IntlGlobalProvider>
  </IntlProvider>
</ApolloProvider>
Run Code Online (Sandbox Code Playgroud)

2)(在IntlGlobalProvider.js中)然后在上下文中我们得到我们想要的intl功能并通过单例公开它.

// 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
Run Code Online (Sandbox Code Playgroud)

3)将其作为模块导入任何地方

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)
Run Code Online (Sandbox Code Playgroud)


A. *_*son 5

受到Simon Somlai上面答案的启发,这里使用了 React hooks 的等效版本:

import React from 'react';
import { useIntl } from 'react-intl';

// 'intl' service singleton reference
let intl;

export function IntlGlobalProvider({ children }) {
  intl = useIntl(); // Keep the 'intl' service reference
  return children;
}

// Getter function to expose the read-only 'intl' service
export function appIntl() {
  return intl;
}

Run Code Online (Sandbox Code Playgroud)

然后按照上面Simon Somlai的答案IntlGlobalProvider的步骤 1 的说明进行设置。现在,当在任何帮助器/实用程序类中使用时,您可以执行以下操作:intl

import { appIntl } from 'modules/core/IntlGlobalProvider';

const translation = appIntl().formatMessage({ id: 'hello' });
console.log(translation);

Run Code Online (Sandbox Code Playgroud)