什麼是 React Intl?
React Intl 這套函式庫讓 React 實做多國語系更加直觀,透過現成的元件和 API 能處理字串、日期、數字的轉換。
React Intl 主要功能
React Intl 主要提供下列的功能:
- 支援數字和分隔符號格式
- 日期與時間的格式
- 顯示距離現在多久
- 支援 150+ 種語言
- 在瀏覽器以及 Node 環境都可運行
- 依照標準建立的一套函式庫
基本配置
使用 Yahoo react-intl 來幫 React 專案做多國語系處理,最重要的就是安裝 npm install --save react-intl
。
專案配置先加入addLocaleData
各語系配置檔,呆丸專用繁體中文 zh-Hant-TW 已包含在 zh 中可以直接使用,然後透過 IntlProvider
注入相關環境及設定到我們的 App 中,其中像是現在要顯示的語系(locale)及翻譯黨(messages),然後就可以透過更改 local 及 message 達到語言切換的目的~
1 2 3 4 5 6 7 8 9 10
| import { addLocaleData } from "react-intl"; import en from "react-intl/locale-data/en"; import zh from "react-intl/locale-data/zh"; import es from "react-intl/locale-data/es";
addLocaleData([...en, ...zh, ...es]);
<IntlProvider locale={localeProp} key={localeProp} messages={messagesProp}> <App /> </IntlProvider>;
|
假設雙語的話,就是三位一體的概念,首先必須把專案裏需要雙語的地方改成特定元件或是變數,接著配合剛才的元件或變數中的 id
撰寫翻譯檔,然後透過改變剛剛提到的 locale, message 去對應切換相關語言翻譯檔~
一般顯示
1
| <FormattedMessage id="App.hello" />
|
當成變數使用,注入後使用
1 2 3 4 5
| const App = (props) => { const { intl } = props; const strHello = intl.formatMessage({ id: "App.hello" }); }; injectIntl(App);
|
英文語言
1 2 3
| { "App.hello": "hello" }
|
中文語言
locale
透過 injectIntl()
這個 HOC 就可以使用程式取得現在 React Intl 設定的語系
1 2 3 4 5 6 7 8 9 10 11 12 13
| import { injectIntl, intlShape } from 'react-intl' const LocaleComponent = ({ intl }) => ( <div>{`語系: ${intl.locale}`}</div> )
LocaleComponent.propTypes = { intl: intlShape.isRequired }
export default injectIntl(LocaleComponent)
|
Placeholder
這時候需要用到比元件更底層 API formatMessage()
,在使用 injectIntl()
注入 intl
物件到元件中後,就可以透過 formatMessage()
來進行字串的轉換
1 2 3 4 5 6 7 8 9 10 11 12 13
| import React from 'react' import { injectIntl, intlShape } from 'react-intl'
const LocaleComponent = ({ intl }) => { const placeholder = intl.formatMessage({id: 'messageId'}) return <input placeholder={placeholder} /> }
LocaleComponent.propTypes = { intl: intlShape.isRequired }
export default injectIntl(LocaleComponent)
|
設計 HOC
完全建議在專案一開始就加入多國語言的配置,這樣才不會到後來各種麻煩,底下 Demo 了一個交換語言用的 Container,透過每次改變語言去改變狀態並傳入 IntlProvide
中,當然也可以考慮用 HOC 的方式去包裝~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| class HotSwappingIntlProvider extends React.Component { constructor(props) { super(props); const { initialLocale: locale, initialMessages: messages } = props; this.state = { locale, messages }; this.handleChange = this.handleChange.bind(this); }
handleChange(locale) { let messages = enJson; if (locale !== "en") { messages = zhJson; }
this.setState({ locale: locale, messages: messages, }); }
render() { return ( <IntlProvider locale={this.state.locale} key={this.state.locale} messages={this.state.messages} > {this.props.children} </IntlProvider> ); } }
|
喜歡這篇文章,請幫忙拍拍手喔 🤣