React-Intl 如何在输入占位符中使用 FormattedMessage
React-Intl How to use FormattedMessage in input placeholder
我不确定如何从
获取值
<FormattedMessage {...messages.placeholderIntlText} />
转换为占位符格式,如输入:
<input placeholder={<FormattedMessage {...messages.placeholderIntlText} />} />
就像实际占位符中的 return [Object object] 一样。有没有办法得到实际正确的值?
您正在尝试将名为 FormattedMessage 的 React 组件渲染到需要字符串的占位符标记中。
您应该创建一个名为 FormattedMessage 的函数,将 returns 一个字符串放入占位符中。
function FormattedMessage(props) {
...
}
<input placeholder=`{$(FormattedMessage({...messages.placeholderIntlText})}` />
react-intl
中的 <Formatted... />
React 组件旨在用于呈现场景,而不是用于占位符、替代文本等。它们呈现 HTML,不是纯文本,这在您的场景中没有用。
相反,react-intl
出于同样的原因提供了 lower level API。渲染组件本身使用这个 API 在引擎盖下将值格式化为 HTML。您的场景可能需要您使用较低级别 formatMessage(...)
API.
您应该使用 injectIntl
HOC 将 intl
对象注入您的组件,然后通过 API.
格式化消息
示例:
import React from 'react';
import { injectIntl, intlShape } from 'react-intl';
const ChildComponent = ({ intl }) => {
const placeholder = intl.formatMessage({id: 'messageId'});
return(
<input placeholder={placeholder} />
);
}
ChildComponent.propTypes = {
intl: intlShape.isRequired
}
export default injectIntl(ChildComponent);
请注意,我在这里使用了一些 ES6 功能,因此请根据您的设置进行调整。
- 您可以使用来自
injectIntl
HoC 的 intl
道具
- 您还可以提供功能作为子组件:
<FormattedMessage {...messages.placeholderIntlText}>
{(msg) => (<input placeholder={msg} />)}
</FormattedMessage>
像这样:
import React, {PropTypes} from 'react';
import { injectIntl, FormattedMessage } from 'react-intl';
/**
* {
* "hello": "Hello",
* "world": "World"
* }
*/
// pure function
const PureFunciton = injectIntl(({ intl }) => {
return (
<div>
<p>{intl.formatMessage({ id: 'hello' })}</p>
<p><FormattedMessage id="world" /></p>
</div>
)
});
// class Component
class componentName extends Component {
handleStr = () => {
// return 'Hello';
const { intl } = this.props;
return intl.formatMessage({ id: 'hello' })
}
render() {
return (
<div>
<p>{this.handleStr()}</p>
<p><FormattedMessage id="world" /></p>
</div>
);
}
}
export default injectIntl(connect(componentName));
在我的例子中,我将整个应用程序放在一个文件中,因此使用 export
是行不通的。这个使用正常的 class 结构,因此您可以根据需要使用 React 的状态和其他功能。
class nameInputOrig extends React.Component {
render () {
const {formatMessage} = this.props.intl;
return (
<input type="text" placeholder={formatMessage({id:"placeholderIntlText"})} />
);
}
}
const nameInput = injectIntl(nameInputOrig);
使用创建的常量应用:
class App extends React.Component {
render () {
<nameInput />
}
}
基于 react intl wiki 带有可翻译占位符的输入框的实现如下所示:
import React from 'react';
import { injectIntl, intlShape, defineMessages } from 'react-intl';
const messages = defineMessages({
placeholder: {
id: 'myPlaceholderText',
defaultMessage: '{text} and static text',
},
});
const ComponentWithInput = ({ intl, placeholderText }) => {
return (
<input
placeholder={ intl.formatMessage(messages.placeholder, { text: placeholderText }) }
/>
);
};
ComponentWithInput.propTypes = {
intl: intlShape.isRequired
};
export default injectIntl(ComponentWithInput);
及其用法:
import ComponentWithInput from './component-with-input';
...
render() {
<ComponentWithInput placeholderText="foo" />
}
...
id: 'myPlaceholderText',
部分是启用 babel-plugin-react-intl 收集消息进行翻译所必需的。
对于输入占位符对于更多details
<FormattedMessage id="yourid" defaultMessage="search">
{placeholder=>
<Input placeholder={placeholder}/>
}
</FormattedMessage>
现在是 2019 年 7 月,react-intl 3 beta 附带 useIntl 挂钩,使此类翻译更容易:
import React from 'react';
import {useIntl, FormattedDate} from 'react-intl';
const FunctionComponent: React.FC<{date: number | Date}> = ({date}) => {
const intl = useIntl();
return (
<span title={intl.formatDate(date)}>
<FormattedDate value={date} />
</span>
);
};
export default FunctionComponent;
然后你可以自定义钩子来使用API:
提供的方法
import { useIntl } from 'react-intl'
export function useFormatMessage(messageId) {
return useIntl().formatMessage({ id: messageId })
}
从@gazdagerg 的回答开始,我修改了他的代码以便:
- 有一个新组件,它是 输入
的包装器
- 从 locale conf
接收字符串 ID
- 根据 ID,returns 与全局区域设置相关的字符串
- 处理未设置字符串ID的情况(导致异常和页面崩溃)
import React from 'react';
import { injectIntl, intlShape, defineMessages } from 'react-intl';
const InputWithPlaceholder = ({ intl, placeholder }) => {
const messages = defineMessages({
placeholder: {
id: placeholder,
defaultMessage: '',
},
});
if(messages.placeholder.id) {
return (
<input placeholder={ intl.formatMessage(messages.placeholder) } />
);
} else {
return (
<input/>
);
}
};
InputWithPlaceholder.propTypes = {
intl: intlShape.isRequired
};
export default injectIntl(InputWithPlaceholder);
您可以通过以下方式在其他文件中使用它:
- 导入新组件
- 将它与语言环境字符串的 ID 作为参数一起使用
import InputWithIntlPlaceholder from 'your/path/to/component/InputWithIntlPlaceholder';
... more code here ...
<InputWithIntlPlaceholder placeholder="your.locale.string.id" />
从 React 版本 >= 16.8 开始,你可以使用 useIntl hook :
import React from 'react';
import { IntlProvider, useIntl } from 'react-intl';
const FunctionComponent = () => {
const intl = useIntl();
const lang = "en";
const messages = {
en: {
'placeholderMessageId': 'placeholder in english',
},
fr: {
'placeholderMessageId': 'placeholder en fançais',
}
}
return (
<IntlProvider locale = {lang} messages = { messages[lang] } >
<input placeholder = { intl.formatMessage({ id: 'placeholderMessageId' })}/>
</IntlProvider >
);
};
export default FunctionComponent;
考虑这种可能性。
最简单的解决方案
<IntlMessages id="category.name">
{text => (
<Input placeholder={text} />
)}
</IntlMessages>
或
我想推荐这个解决方案:
import { useIntl } from "react-intl";
export default function MyComponent() {
const intl = useIntl();
return (
<input placeholder={intl.formatMessage({ id: "messageId" })} />
);
}
我不确定如何从
获取值<FormattedMessage {...messages.placeholderIntlText} />
转换为占位符格式,如输入:
<input placeholder={<FormattedMessage {...messages.placeholderIntlText} />} />
就像实际占位符中的 return [Object object] 一样。有没有办法得到实际正确的值?
您正在尝试将名为 FormattedMessage 的 React 组件渲染到需要字符串的占位符标记中。
您应该创建一个名为 FormattedMessage 的函数,将 returns 一个字符串放入占位符中。
function FormattedMessage(props) {
...
}
<input placeholder=`{$(FormattedMessage({...messages.placeholderIntlText})}` />
react-intl
中的 <Formatted... />
React 组件旨在用于呈现场景,而不是用于占位符、替代文本等。它们呈现 HTML,不是纯文本,这在您的场景中没有用。
相反,react-intl
出于同样的原因提供了 lower level API。渲染组件本身使用这个 API 在引擎盖下将值格式化为 HTML。您的场景可能需要您使用较低级别 formatMessage(...)
API.
您应该使用 injectIntl
HOC 将 intl
对象注入您的组件,然后通过 API.
示例:
import React from 'react';
import { injectIntl, intlShape } from 'react-intl';
const ChildComponent = ({ intl }) => {
const placeholder = intl.formatMessage({id: 'messageId'});
return(
<input placeholder={placeholder} />
);
}
ChildComponent.propTypes = {
intl: intlShape.isRequired
}
export default injectIntl(ChildComponent);
请注意,我在这里使用了一些 ES6 功能,因此请根据您的设置进行调整。
- 您可以使用来自
injectIntl
HoC 的 - 您还可以提供功能作为子组件:
intl
道具
<FormattedMessage {...messages.placeholderIntlText}>
{(msg) => (<input placeholder={msg} />)}
</FormattedMessage>
像这样:
import React, {PropTypes} from 'react';
import { injectIntl, FormattedMessage } from 'react-intl';
/**
* {
* "hello": "Hello",
* "world": "World"
* }
*/
// pure function
const PureFunciton = injectIntl(({ intl }) => {
return (
<div>
<p>{intl.formatMessage({ id: 'hello' })}</p>
<p><FormattedMessage id="world" /></p>
</div>
)
});
// class Component
class componentName extends Component {
handleStr = () => {
// return 'Hello';
const { intl } = this.props;
return intl.formatMessage({ id: 'hello' })
}
render() {
return (
<div>
<p>{this.handleStr()}</p>
<p><FormattedMessage id="world" /></p>
</div>
);
}
}
export default injectIntl(connect(componentName));
在我的例子中,我将整个应用程序放在一个文件中,因此使用 export
是行不通的。这个使用正常的 class 结构,因此您可以根据需要使用 React 的状态和其他功能。
class nameInputOrig extends React.Component {
render () {
const {formatMessage} = this.props.intl;
return (
<input type="text" placeholder={formatMessage({id:"placeholderIntlText"})} />
);
}
}
const nameInput = injectIntl(nameInputOrig);
使用创建的常量应用:
class App extends React.Component {
render () {
<nameInput />
}
}
基于 react intl wiki 带有可翻译占位符的输入框的实现如下所示:
import React from 'react';
import { injectIntl, intlShape, defineMessages } from 'react-intl';
const messages = defineMessages({
placeholder: {
id: 'myPlaceholderText',
defaultMessage: '{text} and static text',
},
});
const ComponentWithInput = ({ intl, placeholderText }) => {
return (
<input
placeholder={ intl.formatMessage(messages.placeholder, { text: placeholderText }) }
/>
);
};
ComponentWithInput.propTypes = {
intl: intlShape.isRequired
};
export default injectIntl(ComponentWithInput);
及其用法:
import ComponentWithInput from './component-with-input';
...
render() {
<ComponentWithInput placeholderText="foo" />
}
...
id: 'myPlaceholderText',
部分是启用 babel-plugin-react-intl 收集消息进行翻译所必需的。
对于输入占位符对于更多details
<FormattedMessage id="yourid" defaultMessage="search">
{placeholder=>
<Input placeholder={placeholder}/>
}
</FormattedMessage>
现在是 2019 年 7 月,react-intl 3 beta 附带 useIntl 挂钩,使此类翻译更容易:
import React from 'react';
import {useIntl, FormattedDate} from 'react-intl';
const FunctionComponent: React.FC<{date: number | Date}> = ({date}) => {
const intl = useIntl();
return (
<span title={intl.formatDate(date)}>
<FormattedDate value={date} />
</span>
);
};
export default FunctionComponent;
然后你可以自定义钩子来使用API:
提供的方法import { useIntl } from 'react-intl'
export function useFormatMessage(messageId) {
return useIntl().formatMessage({ id: messageId })
}
从@gazdagerg 的回答开始,我修改了他的代码以便:
- 有一个新组件,它是 输入 的包装器
- 从 locale conf 接收字符串 ID
- 根据 ID,returns 与全局区域设置相关的字符串
- 处理未设置字符串ID的情况(导致异常和页面崩溃)
import React from 'react';
import { injectIntl, intlShape, defineMessages } from 'react-intl';
const InputWithPlaceholder = ({ intl, placeholder }) => {
const messages = defineMessages({
placeholder: {
id: placeholder,
defaultMessage: '',
},
});
if(messages.placeholder.id) {
return (
<input placeholder={ intl.formatMessage(messages.placeholder) } />
);
} else {
return (
<input/>
);
}
};
InputWithPlaceholder.propTypes = {
intl: intlShape.isRequired
};
export default injectIntl(InputWithPlaceholder);
您可以通过以下方式在其他文件中使用它:
- 导入新组件
- 将它与语言环境字符串的 ID 作为参数一起使用
import InputWithIntlPlaceholder from 'your/path/to/component/InputWithIntlPlaceholder';
... more code here ...
<InputWithIntlPlaceholder placeholder="your.locale.string.id" />
从 React 版本 >= 16.8 开始,你可以使用 useIntl hook :
import React from 'react';
import { IntlProvider, useIntl } from 'react-intl';
const FunctionComponent = () => {
const intl = useIntl();
const lang = "en";
const messages = {
en: {
'placeholderMessageId': 'placeholder in english',
},
fr: {
'placeholderMessageId': 'placeholder en fançais',
}
}
return (
<IntlProvider locale = {lang} messages = { messages[lang] } >
<input placeholder = { intl.formatMessage({ id: 'placeholderMessageId' })}/>
</IntlProvider >
);
};
export default FunctionComponent;
考虑这种可能性。
最简单的解决方案
<IntlMessages id="category.name">
{text => (
<Input placeholder={text} />
)}
</IntlMessages>
或
我想推荐这个解决方案:
import { useIntl } from "react-intl";
export default function MyComponent() {
const intl = useIntl();
return (
<input placeholder={intl.formatMessage({ id: "messageId" })} />
);
}