非组件的 React-intl
React-intl for non components
目前我有以下代码将 react-intl 暴露给非组件,但它会抛出 intl as undefined 的错误。
我已经创建了一个单独的组件 '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 文件中被称为
import t from './locale/t';
t( { type: 'message', id:'button.Next'});
错误信息如下。
提前致谢。
这一行:const { intl } = this.context.intl;
应该是 const { intl } = this.context;
这里有一个参考 post 某人在做与你几乎完全相同的事情:https://github.com/yahoo/react-intl/issues/983#issuecomment-342314143
在上面,作者实际上是在创建一个导出的单例,而不是像上面那样每次都创建一个新实例。这可能也是您要考虑的事情。
还有另一种非常简单的方法我用来解决类似的问题:为非组件提供对 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),
},
};
它工作得很好!
UPDATE for v3.x
After migration to 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),
},
};
还有另一种方法可以解决与使用 react-intl formatMessage for non-components.
类似的问题
创建一个 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);
};
}
导入 LocaleStore 您的 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);
}
}
createIntl
有一种新方法可以很轻松地做到这一点,它 returns 是一个可以在 React 组件外部使用的对象。这是 documentation.
中的示例
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 存储中,这样我就可以在我的应用程序中的任何地方访问它。
如果你可以接受使用功能组件我更愿意使用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' }),
目前我有以下代码将 react-intl 暴露给非组件,但它会抛出 intl as undefined 的错误。
我已经创建了一个单独的组件 '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 文件中被称为
import t from './locale/t';
t( { type: 'message', id:'button.Next'});
错误信息如下。
这一行:const { intl } = this.context.intl;
应该是 const { intl } = this.context;
这里有一个参考 post 某人在做与你几乎完全相同的事情:https://github.com/yahoo/react-intl/issues/983#issuecomment-342314143
在上面,作者实际上是在创建一个导出的单例,而不是像上面那样每次都创建一个新实例。这可能也是您要考虑的事情。
还有另一种非常简单的方法我用来解决类似的问题:为非组件提供对 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),
},
};
它工作得很好!
UPDATE for v3.x
After migration to 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),
},
};
还有另一种方法可以解决与使用 react-intl formatMessage for non-components.
类似的问题创建一个 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);
};
}
导入 LocaleStore 您的 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);
}
}
createIntl
有一种新方法可以很轻松地做到这一点,它 returns 是一个可以在 React 组件外部使用的对象。这是 documentation.
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 存储中,这样我就可以在我的应用程序中的任何地方访问它。
如果你可以接受使用功能组件我更愿意使用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' }),