本文主要介紹了react-intl實現React國際化多語言的方法,分享給大家,具體如下:
效果預覽
React Intl 國際化步驟
- 創建國際化資源文件
- 根據語言獲取國際化資源
- 引入 react-intl 的 local data
- 創建 LocaleProvider 國際化上下文組件
- 創建 react-intl 國際化上下文組件
- 使用 react-intl's components & apis,進行國際化開發
1. 創建國際化資源文件
目前我們管理資源文件的方式是在 src/locales 文件夾下:
1
2
3
4
5
|
. ├── en-US.js ├── en-US.messages.js ├── zh-Hans.js └── zh-Hans.messages.js |
*.messages.js 是我們的資源文件(這里我們采用了 js 格式,你也可以使用 json 等等),返回的是一個對象,key 為我們翻譯用的 id,value 為具體語言的翻譯,內容是:
1
2
3
4
5
6
7
8
9
10
11
|
export default { 'page.localeProvider.react' : '{ name }, a JavaScript library for building user interfaces.' , 'page.localeProvider.react.html' : '<p>{ name } makes it painless to create interactive UIs. Design simple views for each state in your application, and { name } will efficiently update and render just the right components when your data changes.</p><p>Declarative views make your code more predictable and easier to debug.</p>' , 'page.localeProvider.unreadCount' : 'You have {unreadCount} new {notifications}' , 'page.localeProvider.title.date' : 'Current date: ' , 'page.localeProvider.title.time' : 'Current time: ' , 'page.localeProvider.title.relative' : 'Relative current time: ' , 'page.localeProvider.title.number' : 'Comma number: ' , 'page.localeProvider.title.price' : 'Price: ' , 'page.localeProvider.title.percent' : 'Percent: ' , }; |
en-US.js 文件封裝了 messages、locale 等國際化上下文組件需要的內容:
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
33
34
35
36
37
|
import appLocaleData from 'react-intl/locale-data/en' ; // 引入組件多語言 import paginationLocale from '@/components/pagination/locales/en-US' ; import messages from './en-US.messages' ; window.appLocale = { // 合并所有 messages, 加入組件的 messages messages: Object.assign({}, messages, { Pagination: paginationLocale, }), // locale locale: 'en-US' , // react-intl locale-data data: appLocaleData, // 自定義 formates formats: { date: { normal: { hour12: false , year: 'numeric' , month: '2-digit' , day: '2-digit' , hour: '2-digit' , minute: '2-digit' , }, }, // 貨幣 money: { currency: 'USD' , }, }, }; export default window.appLocale; |
有了這些資源文件以及相關的封裝之后,我們就可以在 LocaleProvider 和 InltProvider 中使用了。
2. 根據語言加載國際化資源
上一步我們創建了不同語言版本的國際化資源文件,我們還需要一個函數能夠根據語言,加載對應的資源文件:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
|
/** * 獲取國際化資源文件 * * @param {any} lang * @returns */ function getLocale(lang) { let result = {}; switch (lang) { case 'zh-CN' : result = require( './locales/zh-Hans' ); break ; case 'en-US' : result = require( './locales/en-US' ); break ; default : result = require( './locales/zh-Hans' ); } return result. default || result; } |
3. 引入 react-intl 的 local data
1
2
3
4
5
6
7
8
|
import { addLocaleData } from 'react-intl' ; ... render() { const appLocale = getLocale( 'en-US' ); addLocaleData(...appLocale.data); ... } |
react-intl 在做國際化的時候需要一些特有的 local data,主要是進行相對時間翻譯時,比如昨天、今天、明天、幾分鐘前、幾個月前之類的。我們通過 addLocaleData 這個方法加載相關內容,大家可以根據實際情況加載需要的 locale-data。
4. 創建 LocaleProvider 國際化上下文組件
為了組件能夠國際化資源信息,我們需要一個 LocaleProvider 組件,用它來提供國際化的上下文,具體用法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
export default class LocaleProvider extends React.Component { static propTypes = { children: PropTypes.any, locale: PropTypes.object, }; static childContextTypes = { // 語言信息 locale: PropTypes.object, }; getChildContext() { return { locale: { ... this .props.locale, }, }; } render() { return React.Children.only( this .props.children); } } |
5. 創建 react-intl 國際化上下文組件
為了能夠使用 react-intl 進行國際化,跟 redux 這些框架一樣,我們需要一個 Provider Component,用它來提供國際化的上下文,具體用法:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
... import { addLocaleData, IntlProvider } from 'react-intl' ; import LocaleProvider from '@/components/locale-provider' ; import Home from '@/views/home' ; ... render() { // 根據語言獲取國際化資源 const appLocale = getLocale( 'en-US' ); addLocaleData(...appLocale.data); return ( <LocaleProvider locale={appLocale}> <IntlProvider locale={appLocale.locale} messages={appLocale.messages} formats={appLocale.formats} > <Home /> </IntlProvider> </LocaleProvider> ); } |
LocaleProvider 有三個配置參數:
- locale, <object>, 國際化資源.
IntlProvider 有三個配置參數:
- locale, <string>, 語言標記,例如 'zh-CN' 'en-US'
- messages, <object>, 國際化所需的 key-value 對象
- formats, <object>, 自定義 format,比如日期格式、貨幣等
在定義好 IntlProvider 之后,我們就可以在頁面使用它提供的 api 或者組件來進行國際化了。
6. 使用 react-intl's components & apis
react-intl 提供了豐富的組件和 api 來完成頁面部分的國際化。
字符串的格式化
a. <FormattedMessage /> 這個組件用于格式化字符串,是所有的組件中使用頻率最高的組件。除了可以根據配置輸出不同語言的簡單字符串之外,還可以輸出包含動態變化的參數的復雜字符串,具體的用法在后面的例子中會慢慢敘述。
比如我們在 *.message.js 配置文件中寫了如下內容:
1
2
3
|
export default { 'page.localeProvider.react' : '{ name }, a JavaScript library for building user interfaces.' , }; |
使用這個組件的時候,我們這么寫:
1
2
3
4
5
6
7
8
9
|
<FormattedMessage tagName= "p" id= "page.localeProvider.react" values={{ name: 'React' , }} defaultMessage= "{name} 是一個用于構建用戶界面的 JAVASCRIPT 庫。" description= "{name} 是什么?" /> |
- id 指代的是這個字符串在配置文件中的屬性名
- description 指的是對于這個位置替代的字符串的描述,便于維護代碼,不寫的話也不會影響輸出的結果
- defaultMessage 當在locale配置文件中沒有找到這個id的時候,輸出的默認值
- tagName 實際生成的標簽,默認是 span
- values 動態參數. 格式為對象
輸出的結果:
<p>React, a JavaScript library for building user interfaces.</p>
b. <FormattedHTMLMessage />這個組件的用法和完全相同,唯一的不同就是輸出的字符串可以包含HTML標簽。
日期時間
a. <FormattedDate /> 用于格式化日期,能夠將一個時間戳格式化成不同語言中的日期格式。
傳入時間戳作為參數:
1
2
3
|
<FormattedDate value={ new Date(1459832991883)} /> |
輸出結果:
<!-- 英文 -->
<span>4/5/2016</span><!-- 中文 -->
<span>2016/5/4</span>
b. <FormattedTime> 用于格式化時間,效果與<FormattedDate />相似。
傳入時間戳作為參數:
1
2
3
|
<FormattedTime value={ new Date(1459832991883)} /> |
輸出結果:
<!-- 英文 -->
<span>1:09 AM</span><!-- 中文 -->
<span>上午1:09</span>
c. <FormattedRelative /> 通過這個組件可以顯示傳入組件的某個時間戳和當前時間的關系,比如“10 minutes ago”。
傳入時間戳作為參數:
1
2
3
|
<FormattedRelative value={Date.now()} /> |
輸出結果:
<!-- 英文 =>> 運行時的輸出結果: -->
<span>now</span><!-- 英文 =>> 10秒之后的輸出結果: -->
<span>10 seconds ago</span><!-- 英文 =>> 1分鐘之后的輸出結果: -->
<span>1 minute ago</span><!-- 中文 =>> 運行時的輸出結果: -->
<span>現在</span><!-- 中文 =>> 10秒之后的輸出結果: -->
<span>10秒前</span><!-- 中文 =>> 1分鐘之后的輸出結果: -->
<span>1分鐘前</span>
數字量詞
a. <FormattedPlural /> 這個組件可用于格式化量詞,在中文的語境中,其實不太會用得到,比如我們說一個雞腿,那么量詞就是‘個',我們說兩個雞腿,量詞還是‘個',不會發生變化。但是在英文的語言環境中,描述一個蘋果的時候,量詞是apple,當蘋果數量為兩個時,就會變成apples,這個組件的作用就在于此。
傳入組件的參數中,value為數量,其他的為不同數量時對應的量詞,在下面的例子中,一個的時候量詞為message,兩個的時候量詞為messages。實際上可以傳入組件的量詞包括 zero, one, two, few, many, other 已經涵蓋了所有的情況。
結合 <FormattedMessage />運用:
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
const unreadCount = 10; const unreadCount2 = 1; ... <p> <FormattedMessage id= "page.localeProvider.unreadCount" defaultMessage={ '你有{ unreadCount }條新信息' } values={{ unreadCount: ( <strong style={{ color: '#f30' , fontWeight: 'normal' , }} > <FormattedNumber value={unreadCount} /> </strong> ), notifications: ( <FormattedPlural value={unreadCount} one= "notification" other= "notifications" /> ), }} /> </p> <p> <FormattedMessage id= "page.localeProvider.unreadCount" defaultMessage={ '你有{ unreadCount2 }條新信息' } values={{ unreadCount: ( <strong style={{ color: '#f30' , fontWeight: 'normal' , }} > <FormattedNumber value={unreadCount2} /> </strong> ), notifications: ( <FormattedPlural value={unreadCount2} one= "notification" other= "notifications" /> ), }} /> </p> |
輸出結果:
<!-- 英文 -->
<p>You have 10 new notifications</p>
<p>You have 1 notification</p><!-- 中文 -->
<p>你有10條新信息</p>
<p>你有1條新信息</p>
b. <FormattedNumber /> 這個組件最主要的用途是用來給一串數字標逗號,比如10000這個數字,在中文的語言環境中應該是1,0000,是每隔4位加一個逗號,而在英語的環境中是10,000,每隔3位加一個逗號。
傳入數字作為參數:
1
2
3
|
<FormattedNumber value={1000} /> |
輸出結果:
<span>1,000</span>
<FormattedNumber /> 輸出百分比
傳入小數作為參數:
1
2
3
4
|
<FormattedNumber value={0.5} style= "percent" /> |
輸出結果:
<span>50%</span>
<FormattedNumber /> 輸出貨幣
傳入數字作為參數:
1
2
3
4
5
6
7
|
// locale.formats.money.currency 是 /locales/*.js 國際化資源配置的貨幣信息。中文: 'CNY'; 英文: 'USD' <FormattedNumber value={123456.78} style= "currency" currency={locale.formats.money.currency} /> |
輸出結果:
<!-- 英文 -->
<span>$123,456.78</span><!-- 中文 -->
<span>¥123,456.78</span>
注:項目在中文情況下也是每隔3位加一個逗號,具體原因詳,如果有知道原因的請告知。
組件國際化
1. 創建獲取上下文國際化資源函數
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
33
34
35
36
37
38
39
40
41
|
/** * 獲取 組件的語言配置 * * @param {any} props 屬性 * @param {any} context 上下文 * @param {any} componentName 組件名. 對應 context.locale.messages 中的 key 值 * @param {any} getDefaultLocale */ function getComponentLocale(props, context, componentName, getDefaultLocale) { let locale = {}; // 如果 context 上下文中有多語言配置. 則取 context 上下文中的多語言值. // 否則, 取默認值的多語言值. if (context && context.locale && context.locale.messages[componentName]) { locale = context.locale.messages[componentName]; } else { const defaultLocale = getDefaultLocale(); locale = defaultLocale. default || defaultLocale; } let result = { ...locale, }; // 如果屬性有語言配置項, 則合并. if (props.locale) { result = { ...result, ...props.locale, }; if (props.locale.lang) { result.lang = { ...locale.lang, ...props.locale.lang, }; } } return result; } |
2. 創建國際化的組件
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
|
... import { getComponentLocale } from '../_utils/getLocale' ; ... export default class Pagination extends React.Component { // context 上下文 static contextTypes = { locale: PropTypes.object, }; render() { const currentlocale = getComponentLocale( this .props, this .context, 'Pagination' , () => { require( './locales/zh-CN' ); }); return ( <div className= "pagination" > <div className= "pagination__wrapper" > <div className= "pagination__button__prev" > <a>{currentlocale.prevText}</a> </div> <div className= "pagination__button__next" > <a>{currentlocale.nextText}</a> </div> </div> </div> ); } } |
國際化規范附錄
React Intl 編寫規范
- 必須填寫 defaultMessage,并將 defaultMessage 作為中文翻譯
- id 不得重復
- 在使用 intl.formatMessage() 時,必須使用 defineMessages,預定義消息
源碼
整個項目源碼
資料
到此這篇關于react-intl實現React國際化多語言的方法的文章就介紹到這了,更多相關React國際化多語言內容請搜索服務器之家以前的文章或繼續瀏覽下面的相關文章希望大家以后多多支持服務器之家!
原文鏈接:https://juejin.im/post/6844903507791888397