React项目国际化-React-intl
<div> npx create-react-app react-intl-demo && cd react-intl-demo,创建react-intl-demo项目。npm install react-intl, 安装react-intl。使用react-intl时, 首先要提供一个provider,把整个项目包起来。怎么提供呢?使用react-intl的IntlProvider,它有1个必传参数locale, 设置本地语言,你的app要使用哪种语言进行渲染。你app的用户使用哪种语言,就要设置local为哪种语言, 比如en-us(美式英语) zh-cn(简体中文)。</div><div>
<div class="cnblogs_code">
<pre>import {IntlProvider} <span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">react-intl</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">;
ReactDOM.render(
</span><React.StrictMode>
<IntlProvider locale=<span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">en-us</span><span style="color: rgba(128, 0, 0, 1)">'</span>>
<App />
</IntlProvider>
</React.StrictMode><span style="color: rgba(0, 0, 0, 1)">,
document.getElementById(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">root</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
);</span></pre>
</div>
</div>
<div> 为什么要提供一个provider呢?就是为了让React组件能够使用国际化的函数,翻译文本。React Intl 使用Provider的模式为组件树提供i18n(国际化)的上下文。在根组件中提供配置本地语言和翻译信息,<Formatted*>组件可以直接使用。</div>
<p> 怎么翻译项目中的文本?翻译文件放到什么地方?通常来说,会为每一种语言提供一个翻译文件(json文件),src/translations/zh.json提供中文翻译 . en.json file 提供英文翻译。假设要翻译App.js中的内容,src/translations/en.json</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">{
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">app.learn-react-link</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Learn React.</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">app.text</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Edit <code>src/App.js</code> and save to reload.</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
}</span></pre>
</div>
<p> src/translations/zh.json</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 0, 1)">{
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">app.learn-react-link</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">学习 React.</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">app.text</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">编辑<code>src/App.js</code>,保存,并刷新页面</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
}</span></pre>
</div>
<p> 项目中怎么获取到翻译文件? <IntlProvider />有messages属性, 把locale设置的语言对应的翻译内容,传给它,就可以为项目提供翻译内容。比如locale是en-us,那就要把en.json中的翻译内容传递给messsages. locale是zh-cn,那就把zh.json中的翻译内容传递给messages。怎么传递,只能先把json文件引入到项目中,再构建一个以locale为属性,翻译内容为值的对象,让messages的值根据locale来定。index.js中</p>
<div class="cnblogs_code">
<pre>import zh <span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">./translations/zh.json</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
import en </span><span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">./translations/en.json</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 0, 255, 1)">const</span> messages =<span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">en-us</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">: en,
</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">zh-cn</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">: zh
}
</span><span style="color: rgba(0, 0, 255, 1)">const</span> locale = <span style="color: rgba(128, 0, 0, 1)">'zh-cn</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
ReactDOM.render(
</span><React.StrictMode>
<IntlProvider locale={locale} messages={messages}>
<App />
</IntlProvider>
</React.StrictMode><span style="color: rgba(0, 0, 0, 1)">,
document.getElementById(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">root</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">)
);</span></pre>
</div>
<p> 组件中怎么使用翻译内容?最简单的方法就是把要翻译的文本使用<FormattedMessage> 组件来代替。组件有一个必传属性id,用来引用翻译文件。怎么理解id呢?IntlProvider 的messages属性实际上是一个js对象,包含着项目中每一句文本的翻译,格式为{"app.learn-react-link": "学习 React."},"app.learn-react-link"可以看作组件中使用翻译时引用的id,react-intl自动会引用id 对应的翻译好的文本。<FormattedMessage> 中的id就是引用的这个id,也就是说,id必须和messages中指向json文件中的id一致。App.js</p>
<div class="cnblogs_code">
<pre>import {FormattedMessage} <span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">react-intl</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
</span><p><FormattedMessage id=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">app.text</span><span style="color: rgba(128, 0, 0, 1)">"</span> /></p>
<a className=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">App-link</span><span style="color: rgba(128, 0, 0, 1)">"</span> href=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">https://reactjs.org</span><span style="color: rgba(128, 0, 0, 1)">"</span> target=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_blank</span><span style="color: rgba(128, 0, 0, 1)">"</span> rel=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">noopener noreferrer</span><span style="color: rgba(128, 0, 0, 1)">"</span>>
<FormattedMessage id=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">app.learn-react-link</span><span style="color: rgba(128, 0, 0, 1)">"</span> />
</a></pre>
</div>
<p> npm start, 可以看到项目已经翻译成中文了。能不能把<code> 去掉呢?FormattedMessage 可以在value属性中解析出富文本中的XML标签。FormattedMessage 有一个value属性</p>
<div class="cnblogs_code">
<pre><FormattedMessage id=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">app.text</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
values</span>=<span style="color: rgba(0, 0, 0, 1)">{{
code: chunks </span>=> <code>{chunks}</code><span style="color: rgba(0, 0, 0, 1)">
}}
</span>>
</FormattedMessage></pre>
</div>
<p> code对应的就是app.text中的<code></code>标签, 要解析富文本中的哪个标签,属性就是哪个标签。chunks就可解析出标签中的的内容,在这里就是code标签中的内容,src/App.js, 返回值就是替换整个标签及内容。但此时有个问题,如果有一种语言,恰好没有翻译呢?比如把locale改成en,</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">const</span> locale = <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">en</span><span style="color: rgba(128, 0, 0, 1)">'</span>;</pre>
</div>
<p> 页面就只显示app.text和app.learn-react-link 等Id</p>
<p><img src="https://img2022.cnblogs.com/blog/1013082/202203/1013082-20220312113351471-246174227.png"></p>
<p> </p>
<p> 这时要用<FormattedMessage />的defaultMessage属性,设置默认展示的文本。 如果此文本没有在翻译文件中找到,就显示默认文本。它还有一个description: 描述这个文本的作用,主要为翻译者提供上下文。</p>
<div class="cnblogs_code">
<pre><FormattedMessage id=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">app.text</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
values</span>=<span style="color: rgba(0, 0, 0, 1)">{{
code: chunks </span>=> <code>{chunks}</code><span style="color: rgba(0, 0, 0, 1)">
}}
defaultMessage</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">编辑<code>src/App.js</code>,保存,并刷新页面</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
description</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">edit text</span><span style="color: rgba(128, 0, 0, 1)">"</span>
>
<FormattedMessage id=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">app.learn-react-link</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
defaultMessage</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">学习 React.</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
description</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">text link</span><span style="color: rgba(128, 0, 0, 1)">"</span>
/></pre>
</div>
<div> 但有时候,你不能使用组件,比如输入框的placeholder, 它只是纯文本,这就要用到formatMessage 函数。但使用formatMessage函数时,你需要一个intl的上下文。如果在函数组件中可以使用useIntl。写一个input输入框
<div class="cnblogs_code">
<pre>import React <span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">react</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
import { useIntl } </span><span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">react-intl</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
export function Input() {
</span><span style="color: rgba(0, 0, 255, 1)">const</span> intl =<span style="color: rgba(0, 0, 0, 1)"> useIntl();
</span><span style="color: rgba(0, 0, 255, 1)">const</span> placeholder = intl.formatMessage({id: <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">app.placeholder</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">})
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <input placeholder={placeholder}></input><span style="color: rgba(0, 0, 0, 1)">
} </span></pre>
</div>
<p> 引入useIntl,在组件中调用它,返回intl上下文,调用formatMessage方法,它接受一个对象作为参数,id属性就是对应翻译文件中的id。不要忘了在,json文件中写</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">app.placeholder</span><span style="color: rgba(128, 0, 0, 1)">"</span>: <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">请输入数字</span><span style="color: rgba(128, 0, 0, 1)">"</span></pre>
</div>
<p> 当然,id属性可以是动态生成的,比如</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 0, 255, 1)">const</span> intlKey = <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">something</span><span style="color: rgba(128, 0, 0, 1)">"</span>
<span style="color: rgba(0, 0, 255, 1)">const</span> placeholder = intl.formatMessage({ id: `${intlKey}` })</pre>
</div>
</div>
<div> 随着<FormattedMessage />用的越来越多,页面结构可能有点混乱,把id, defaultmessage, description 都写到组件中,太占空间。这时可以使用defineMessages 定义文本,就是用一个变量来指代这一系列的参数。单独创建一个文件 messages.js
<div class="cnblogs_code">
<pre>import { defineMessages } <span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">react-intl</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
export </span><span style="color: rgba(0, 0, 255, 1)">default</span><span style="color: rgba(0, 0, 0, 1)"> defineMessages({
text: {
id: </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">app.text</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">,
defaultMessage: </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Edit <code>src/App.js</code></span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
},
link: {
id: </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">app.learn-react-link</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">,
defaultMessage: </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Lerne React</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">,
description: </span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Link on react page</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
},<br></span></pre>
<div>
<div> placeholder: {</div>
<div> id: 'app.placeholder'</div>
<div> }</div>
</div>
<pre><span style="color: rgba(0, 0, 0, 1)">});</span></pre>
</div>
<p> <FormattedMessage /> and formatMessage()就可以使用message.js中定义的text和link。App.js</p>
<div class="cnblogs_code">
<pre>import messages <span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">./message.js</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
import { FormattedMessage } </span><span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">react-intl</span><span style="color: rgba(128, 0, 0, 1)">'</span>
<p>
<<span style="color: rgba(0, 0, 0, 1)">FormattedMessage {...messages.text}
values</span>=<span style="color: rgba(0, 0, 0, 1)">{{
code: chunks </span>=> <code>{chunks}</code><span style="color: rgba(0, 0, 0, 1)">
}}
</span>>
</FormattedMessage>
</p>
<<span style="color: rgba(0, 0, 0, 1)">a
className</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">App-link</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
href</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">https://reactjs.org</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">
target</span>=<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">_blank</span><span style="color: rgba(128, 0, 0, 1)">"</span>
>
<FormattedMessage {...messages.link} />
</a></pre>
</div>
<p> Input.js</p>
<div class="cnblogs_code">
<pre>import { useIntl } <span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">react-intl</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
import messages </span><span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">./message</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
export function Input() {
</span><span style="color: rgba(0, 0, 255, 1)">const</span> intl =<span style="color: rgba(0, 0, 0, 1)"> useIntl();
</span><span style="color: rgba(0, 0, 255, 1)">const</span> placeholder =<span style="color: rgba(0, 0, 0, 1)"> intl.formatMessage(messages.placeholder)
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <input placeholder={placeholder}></input><span style="color: rgba(0, 0, 0, 1)">
} </span></pre>
</div>
<p> 如果不能使用useIntl hooks, 在普通函数或类组件中可以使用injectIntl函数提供intl上下文。Input.js</p>
</div>
<div>
<div class="cnblogs_code">
<pre>import React <span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">react</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
import messages </span><span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">./message.js</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
import { injectIntl } </span><span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">react-intl</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
function Input({intl}) {
</span><span style="color: rgba(0, 0, 255, 1)">const</span> placeholder =<span style="color: rgba(0, 0, 0, 1)"> intl.formatMessage(messages.placeholder)
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <input placeholder={placeholder}></input><span style="color: rgba(0, 0, 0, 1)">
}
export </span><span style="color: rgba(0, 0, 255, 1)">default</span> injectIntl(Input);</pre>
</div>
<p> 使用类</p>
<div class="cnblogs_code">
<pre>import React <span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">react</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">;
import messages </span><span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">./message.js</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">
import { injectIntl } </span><span style="color: rgba(0, 0, 255, 1)">from</span> <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">react-intl</span><span style="color: rgba(128, 0, 0, 1)">'</span>
<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> Input extends React.Component {
render() {
</span><span style="color: rgba(0, 0, 255, 1)">const</span> {intl} = <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.props;
</span><span style="color: rgba(0, 0, 255, 1)">const</span> placeholder =<span style="color: rgba(0, 0, 0, 1)"> intl.formatMessage(messages.placeholder)
</span><span style="color: rgba(0, 0, 255, 1)">return</span> <input placeholder={placeholder}></input><span style="color: rgba(0, 0, 0, 1)">
}
}
export </span><span style="color: rgba(0, 0, 255, 1)">default</span> injectIntl(Input);</pre>
</div>
<p> </p>
</div><br><br>
来源:https://www.cnblogs.com/SamWeb/p/15772214.html
頁:
[1]