reactjs 非组件的React-Intl

0mkxixxg  于 2023-01-02  发布在  React
关注(0)|答案(6)|浏览(343)

目前,我有以下代码将react-intl公开给非组件,但它会抛出一个intl未定义的错误。
我已经创建了一个单独的组件'CurrentLocale',并将intl注入其中。导出函数t将使用来自CurrentLocale上下文的intl formatMessage。

import React from 'react';
import {injectIntl} from 'react-intl';
import PropTypes from 'prop-types';
import { flow } from 'lodash';

class CurrentLocale extends React.Component {

    constructor(props,context){

        super();
        console.log(context,props);
        console.log(this.formatMessage);
        const { intl } = this.context.intl;//this.props;

        this.formatMessage = intl.formatMessage;
    }

    render() {
        return false;
    }
}
CurrentLocale.contextTypes={
    intl:PropTypes.object,
};

injectIntl(CurrentLocale);

function intl() {
    return new CurrentLocale();
}

function formatMessage(...args) {
    return intl().formatMessage(...args);
}

const t = opts => {
    const id = opts.id;
    const type = opts.type;
    const values = opts.values;
    let t;

    switch (type){

        case 'message':
        default:
            t = formatMessage(id, values);
    }

    return t;
}

export default t;

T在另一个普通JavaScript文件AS中被调用,

import t from './locale/t';
t( { type: 'message', id:'button.Next'});

以下是错误消息。x1c 0d1x提前感谢。

mdfafbf1

mdfafbf11#

还有一种方法非常简单,我用来解决类似的问题:为非组件提供对intl对象的访问:

import { IntlProvider, addLocaleData } from 'react-intl';
import localeDataDE from 'react-intl/locale-data/de';
import localeDataEN from 'react-intl/locale-data/en';
import { formMessages } from '../../../store/i18n'; // I defined some messages here
import { Locale } from '../../../../utils'; //I set the locale fom here

addLocaleData([...localeDataEN, ...localeDataDE]);
const locale = Locale.setLocale(); //my own methods to retrieve locale
const messages = Locale.setMessages(); //getting messages from the json file.
const intlProvider = new IntlProvider({ locale, messages });
const { intl } = intlProvider.getChildContext();

export const SCHEMA = {
  salutation: {
    label: intl.formatMessage(formMessages.salutationLabel),
    errormessages: {
      required: intl.formatMessage(formMessages.salutationError),
    },
  },
  academic_title_code: {
    label: intl.formatMessage(formMessages.academicTitleLabel),
  },
};

它的工作就像一个魅力!

针对v3.x的更新

迁移到react-intl 3.x后

import { createIntl, createIntlCache } from 'react-intl'
import { formMessages } from '../../../store/i18n'; // I defined some messages here
import { Locale } from '../../../../utils'; //I set the locale fom here

const locale = Locale.setLocale(); //my own methods to retrieve locale
const messages = Locale.setMessages(); //getting messages from the json file.
// This is optional but highly recommended
// since it prevents memory leak
const cache = createIntlCache();
const intl = createIntl({ locale, messages }, cache)

export const SCHEMA = {
  salutation: {
    label: intl.formatMessage(formMessages.salutationLabel),
    errormessages: {
      required: intl.formatMessage(formMessages.salutationError),
    },
  },
  academic_title_code: {
    label: intl.formatMessage(formMessages.academicTitleLabel),
  },
};
0tdrvxhp

0tdrvxhp2#

createIntl有一种新的方法可以很容易地做到这一点,它返回一个对象,你可以在React组件之外使用它,下面是文档中的一个例子。

import {createIntl, createIntlCache, RawIntlProvider} from 'react-intl'

// This is optional but highly recommended
// since it prevents memory leak
const cache = createIntlCache()

const intl = createIntl({
  locale: 'fr-FR',
  messages: {}
}, cache)

// Call imperatively
intl.formatNumber(20)

// Pass it to IntlProvider
<RawIntlProvider value={intl}>{foo}</RawIntlProvider>

我个人将intl对象存储在Redux存储中,这样我就可以在应用程序的任何地方访问它。

irtuqstp

irtuqstp3#

此行:const { intl } = this.context.intl;应为const { intl } = this.context;
这里有一个人做几乎完全一样的事情,你是参考后:https://github.com/yahoo/react-intl/issues/983#issuecomment-342314143
在上面的例子中,作者实际上创建了一个导出的单例示例,而不是像上面那样每次都创建一个新示例,这可能也是你需要考虑的。

pgky5nke

pgky5nke4#

还有另一种方法可以解决类似的问题,将react-intlformatMessage用于非组件。
创建LocaleStore.js存储文件。

import _formatMessage from "format-message";

    export default class LocaleStore {

      formatMessage = (id, values) => {
        if (!(id in this.messages)) {
          console.warn("Id not found in intl list: " + id);
          return id;
        }
        return _formatMessage(this.messages[id], values);
      };
    }

导入本地存储您CombinedStores.js

import LocaleStore from "./stores/LocaleStore";
import en from "./translations/en";
import de from "./translations/de";
import Global from "./stores/global"
const locale = new LocaleStore("en", {
  en,
  de
});
export default {
global:new Global(locale) 
}

现在你可以在你的GlobalStore.js中使用它

class GlobalStore {
    constructor(locale) {
     this.locale = locale;
    }

   formatMessage=(message_is,formatLanguage="en")=> {
     return  this.locale.formatMessage(message_id, formatLanguage);
    }
  }
6kkfgxo0

6kkfgxo05#

react-intl使用动态注入国际化消息的 Package 组件来装饰React.Component,以便能够动态加载语言环境数据。

import { injectIntl } from 'react-intl';
class MyComponent extends Component {
  render() {
    const intl = this.props;
    const title = intl.formatMessage({ id: 'title' });
    return (<div>{title}</div>);
  }
};
export default injectIntl(MyComponent);

只能在React.Component等视图层应用,react-intl不能在Vanilla JS中使用,例如:

export default const rules = {
  noSpace(value) {
    if (value.includes(' ')) {
      return 'Space is not allowed.';
    }
  }
};

react-intl-universal是一种替代方法,它不仅可以在Component中使用,也可以在Vanilla JS中使用。
例如:

import intl from 'react-intl-universal';
export default const rules = {
  noSpace(value) {
    if (value.includes(' ')) {
      return intl.get('no_space');
    }
  }
};

参见react-intl-universal online example

rggaifut

rggaifut6#

如果您可以接受使用函数组件,我更喜欢使用useIntl hook
https://reactjs.org/docs/components-and-props.html#function-and-class-components
我可以得到如下的值:

import { useIntl } from "react-intl";

const intl = useIntl()
intl.formatMessage({ id: 'myId' }),

https://formatjs.io/docs/react-intl/api/#useintl-hook

相关问题