import {IntlProvider} from "react-intl"; ReactDOM.render( <React.StrictMode> <IntlProvider locale='en-us'> <App /> </IntlProvider> </React.StrictMode>, document.getElementById('root') );
怎么翻譯項目中的文本?翻譯文件放到什么地方?通常來說,會為每一種語言提供一個翻譯文件(json文件),src/translations/zh.json提供中文翻譯 . en.json file 提供英文翻譯。假設要翻譯App.js中的內容,src/translations/en.json
{ "app.learn-react-link": "Learn React.", "app.text": "Edit <code>src/App.js</code> and save to reload." }
src/translations/zh.json
{ "app.learn-react-link": "學習 React.", "app.text": "編輯<code>src/App.js</code>,保存,並刷新頁面" }
項目中怎么獲取到翻譯文件? <IntlProvider />有messages屬性, 把locale設置的語言對應的翻譯內容,傳給它,就可以為項目提供翻譯內容。比如locale是en-us,那就要把en.json中的翻譯內容傳遞給messsages. locale是zh-cn,那就把zh.json中的翻譯內容傳遞給messages。怎么傳遞,只能先把json文件引入到項目中,再構建一個以locale為屬性,翻譯內容為值的對象,讓messages的值根據locale來定。index.js中
import zh from './translations/zh.json'; import en from './translations/en.json'; const messages = { 'en-us': en, 'zh-cn': zh } const locale = 'zh-cn'; ReactDOM.render( <React.StrictMode> <IntlProvider locale={locale} messages={messages[locale]}> <App /> </IntlProvider> </React.StrictMode>, document.getElementById('root') );
組件中怎么使用翻譯內容?最簡單的方法就是把要翻譯的文本使用<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
import {FormattedMessage} from 'react-intl'; <p><FormattedMessage id="app.text" /></p> <a className="App-link" href="https://reactjs.org" target="_blank" rel="noopener noreferrer"> <FormattedMessage id="app.learn-react-link" /> </a>
npm start, 可以看到項目已經翻譯成中文了。能不能把<code> 去掉呢?FormattedMessage 可以在value屬性中解析出富文本中的XML標簽。FormattedMessage 有一個value屬性
<FormattedMessage id="app.text" values={{ code: chunks => <code>{chunks}</code> }} > </FormattedMessage>
code對應的就是app.text中的<code></code>標簽, 要解析富文本中的哪個標簽,屬性就是哪個標簽。chunks就可解析出標簽中的的內容,在這里就是code標簽中的內容,src/App.js, 返回值就是替換整個標簽及內容。但此時有個問題,如果有一種語言,恰好沒有翻譯呢?比如把locale改成en,
const locale = 'en';
頁面就只顯示app.text和app.learn-react-link 等Id
這時要用<FormattedMessage />的defaultMessage屬性,設置默認展示的文本。 如果此文本沒有在翻譯文件中找到,就顯示默認文本。它還有一個description: 描述這個文本的作用,主要為翻譯者提供上下文。
<FormattedMessage id="app.text" values={{ code: chunks => <code>{chunks}</code> }} defaultMessage="編輯<code>src/App.js</code>,保存,並刷新頁面" description="edit text" > <FormattedMessage id="app.learn-react-link" defaultMessage="學習 React." description="text link" />
import React from 'react'; import { useIntl } from 'react-intl'; export function Input() { const intl = useIntl(); const placeholder = intl.formatMessage({id: 'app.placeholder'}) return <input placeholder={placeholder}></input> }
引入useIntl,在組件中調用它,返回intl上下文,調用formatMessage方法,它接受一個對象作為參數,id屬性就是對應翻譯文件中的id。不要忘了在,json文件中寫
"app.placeholder": "請輸入數字"
當然,id屬性可以是動態生成的,比如
const intlKey = "something" const placeholder = intl.formatMessage({ id: `${intlKey}` })
import { defineMessages } from 'react-intl' export default defineMessages({ text: { id: 'app.text', defaultMessage: 'Edit <code>src/App.js</code>' }, link: { id: 'app.learn-react-link', defaultMessage: 'Lerne React', description: 'Link on react page' },
});
<FormattedMessage /> and formatMessage()就可以使用message.js中定義的text和link。App.js
import messages from './message.js' import { FormattedMessage } from 'react-intl' <p> <FormattedMessage {...messages.text} values={{ code: chunks => <code>{chunks}</code> }} > </FormattedMessage> </p> <a className="App-link" href="https://reactjs.org" target="_blank" > <FormattedMessage {...messages.link} /> </a>
Input.js
import { useIntl } from 'react-intl'; import messages from './message' export function Input() { const intl = useIntl(); const placeholder = intl.formatMessage(messages.placeholder) return <input placeholder={placeholder}></input> }
如果不能使用useIntl hooks, 在普通函數或類組件中可以使用injectIntl函數提供intl上下文。Input.js
import React from 'react'; import messages from './message.js' import { injectIntl } from 'react-intl' function Input({intl}) { const placeholder = intl.formatMessage(messages.placeholder) return <input placeholder={placeholder}></input> } export default injectIntl(Input);
使用類
import React from 'react'; import messages from './message.js' import { injectIntl } from 'react-intl' class Input extends React.Component { render() { const {intl} = this.props; const placeholder = intl.formatMessage(messages.placeholder) return <input placeholder={placeholder}></input> } } export default injectIntl(Input);