react-intl实现React国际化多语言的方法


Posted in Javascript onSeptember 27, 2020

本文主要介绍了react-intl实现React国际化多语言的方法,分享给大家,具体如下:

效果预览

react-intl实现React国际化多语言的方法

React Intl 国际化步骤

  • 创建国际化资源文件
  • 根据语言获取国际化资源
  • 引入 react-intl 的 local data
  • 创建 LocaleProvider 国际化上下文组件
  • 创建 react-intl 国际化上下文组件
  • 使用 react-intl's components & apis,进行国际化开发

1. 创建国际化资源文件

目前我们管理资源文件的方式是在 src/locales 文件夹下:

.
├── en-US.js
├── en-US.messages.js
├── zh-Hans.js
└── zh-Hans.messages.js

*.messages.js 是我们的资源文件(这里我们采用了 js 格式,你也可以使用 json 等等),返回的是一个对象,key 为我们翻译用的 id,value 为具体语言的翻译,内容是:

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 等国际化上下文组件需要的内容:

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. 根据语言加载国际化资源

上一步我们创建了不同语言版本的国际化资源文件,我们还需要一个函数能够根据语言,加载对应的资源文件:

/**
 * 获取国际化资源文件
 *
 * @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

import { addLocaleData } from 'react-intl';
...

render() {
 const appLocale = getLocale('en-US');
 addLocaleData(...appLocale.data);
 ...
}

react-intl 在做国际化的时候需要一些特有的 local data,主要是进行相对时间翻译时,比如昨天、今天、明天、几分钟前、几个月前之类的。我们通过 addLocaleData 这个方法加载相关内容,大家可以根据实际情况加载需要的 locale-data。

4. 创建 LocaleProvider 国际化上下文组件

为了组件能够国际化资源信息,我们需要一个 LocaleProvider 组件,用它来提供国际化的上下文,具体用法:

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,用它来提供国际化的上下文,具体用法:

...
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 配置文件中写了如下内容:

export default {
 'page.localeProvider.react': '{ name }, a JavaScript library for building user interfaces.',
};

使用这个组件的时候,我们这么写:

<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 /> 用于格式化日期,能够将一个时间戳格式化成不同语言中的日期格式。

传入时间戳作为参数:

<FormattedDate 
 value={new Date(1459832991883)}
/>

输出结果:

<!-- 英文 -->
<span>4/5/2016</span>

<!-- 中文 -->
<span>2016/5/4</span>

b. <FormattedTime> 用于格式化时间,效果与<FormattedDate />相似。

传入时间戳作为参数:

<FormattedTime 
 value={new Date(1459832991883)}
/>

输出结果:

<!-- 英文 -->
<span>1:09 AM</span>

<!-- 中文 -->
<span>上午1:09</span>

c. <FormattedRelative /> 通过这个组件可以显示传入组件的某个时间戳和当前时间的关系,比如“10 minutes ago”。

传入时间戳作为参数:

<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 />运用:

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位加一个逗号。

传入数字作为参数:

<FormattedNumber 
 value={1000}
/>

输出结果:

<span>1,000</span>

<FormattedNumber /> 输出百分比

传入小数作为参数:

<FormattedNumber
 value={0.5}
 style="percent"
/>

输出结果:

<span>50%</span>

<FormattedNumber /> 输出货币

传入数字作为参数:

// 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. 创建获取上下文国际化资源函数

/**
 * 获取 组件的语言配置
 *
 * @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. 创建国际化的组件

...
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,预定义消息

源码

整个项目源码

资料

  • API
  • 国际化方案
  • Intl.NumberFormat

到此这篇关于react-intl实现React国际化多语言的方法的文章就介绍到这了,更多相关React国际化多语言内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Javascript 相关文章推荐
使用jQuery.Validate进行客户端验证(初级篇) 不使用微软验证控件的理由
Jun 28 Javascript
JS画5角星方法介绍
Sep 17 Javascript
jquery链式操作的正确使用方法
Jan 06 Javascript
原生javascript实现拖动元素示例代码
Sep 01 Javascript
TypeScript 中接口详解
Jun 19 Javascript
AngularJS的一些基本样式初窥
Jul 27 Javascript
Angular中$state.go页面跳转并传递参数的方法
May 09 Javascript
Angular2 组件通信的实例代码
Jun 23 Javascript
Vue项目引发的「过滤器」使用教程
Mar 12 Javascript
vue-resourc发起异步请求的方法
Feb 11 Javascript
VUE Elemen-ui之穿梭框使用方法详解
Jan 19 Javascript
JavaScript实现点击切换功能
Jan 27 Javascript
Javascript异步流程控制之串行执行详解
Sep 27 #Javascript
vue+elementUI 实现内容区域高度自适应的示例
Sep 26 #Javascript
Openlayers实现测量功能
Sep 25 #Javascript
openlayers4.6.5实现距离量测和面积量测
Sep 25 #Javascript
JQuery Ajax如何实现注册检测用户名
Sep 25 #jQuery
Openlayers测量距离与面积的实现方法
Sep 25 #Javascript
基于JS实现操作成功之后自动跳转页面
Sep 25 #Javascript
You might like
PHP 和 HTML
2006/10/09 PHP
Google Voice 短信发送接口PHP开源版(2010.5更新)
2010/07/22 PHP
php 冒泡排序 交换排序法
2011/05/10 PHP
PHP判断图片格式的七种方法小结
2013/06/03 PHP
PHP基于php_imagick_st-Q8.dll实现JPG合成GIF图片的方法
2014/07/11 PHP
php使用类继承解决代码重复的问题
2015/02/11 PHP
PHP实现对数组分页处理实例详解
2017/02/07 PHP
golang、python、php、c++、c、java、Nodejs性能对比
2017/03/12 NodeJs
php实现的双色球算法示例
2017/06/20 PHP
PHP FileSystem 文件系统常用api整理总结
2019/07/12 PHP
javascript 有用的脚本函数
2009/05/07 Javascript
js showModalDialog 弹出对话框的简单实例(子窗体)
2014/01/07 Javascript
使用node.js 获取客户端信息代码分享
2014/11/26 Javascript
小议JavaScript中Generator和Iterator的使用
2015/07/29 Javascript
javascript字符串对象常用api函数小结(连接,替换,分割,转换等)
2016/09/20 Javascript
jQuery中的100个技巧汇总
2016/12/15 Javascript
利用HBuilder打包前端开发webapp为apk的方法
2017/11/13 Javascript
NodeJs form-data格式传输文件的方法
2017/12/13 NodeJs
详解Vue底部导航栏组件
2019/05/02 Javascript
微信小程序实现图片选择并预览功能
2019/07/25 Javascript
vue 导航锚点_点击平滑滚动,导航栏对应变化详解
2020/08/10 Javascript
Antd-vue Table组件添加Click事件,实现点击某行数据教程
2020/11/17 Javascript
python操作xml文件示例
2014/04/07 Python
闭包在python中的应用之translate和maketrans用法详解
2014/08/27 Python
Python自动化运维和部署项目工具Fabric使用实例
2016/09/18 Python
《与孩子一起学编程》python自测题
2018/05/27 Python
利用arcgis的python读取要素的X,Y方法
2018/12/22 Python
Python操作Sonqube API获取检测结果并打印过程解析
2019/11/27 Python
HTML5中Canvas与SVG的画图原理比较
2013/01/16 HTML / CSS
Stuart Weitzman美国官网:美国奢华鞋履品牌
2016/08/18 全球购物
公司领导推荐信
2013/11/12 职场文书
《赶海》教学反思
2014/04/20 职场文书
2014年餐厅服务员工作总结
2014/11/18 职场文书
初中语文教师研修日志
2015/11/13 职场文书
家长必看:义务教育,不得以面试 评测等名义选拔学生
2019/07/09 职场文书
Springboot配置suffix指定mvc视图的后缀方法
2021/07/03 Java/Android