什麼是 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 達到語言切換的目的~
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 去對應切換相關語言翻譯檔~
一般顯示
<FormattedMessage id="App.hello" />
當成變數使用,注入後使用
const App = (props) => {
const { intl } = props;
const strHello = intl.formatMessage({ id: "App.hello" });
};
injectIntl(App);
英文語言
{
"App.hello": "hello"
}
中文語言
{
"App.hello": "哈囉"
}
locale
透過 injectIntl()
這個 HOC 就可以使用程式取得現在 React Intl 設定的語系
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()
來進行字串的轉換
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 的方式去包裝~
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>
);
}
}
喜歡這篇文章,請幫忙拍拍手喔 🤣