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 相关文章推荐
编写兼容IE和FireFox的脚本
May 18 Javascript
jquery tools 系列 scrollable(2)
Sep 06 Javascript
JavaScript学习笔记之获取当前目录的实现代码
Dec 14 Javascript
jQuery左右滚动支持图片放大缩略图图片轮播代码分享
Aug 26 Javascript
深入解析JavaScript中函数的Currying柯里化
Mar 19 Javascript
jQuery 检查某个元素在页面上是否存在实例代码
Oct 27 Javascript
探索Vue.js component内容实现
Nov 03 Javascript
Javascript 实现全屏滚动实例代码
Dec 31 Javascript
vue.js todolist实现代码
Oct 29 Javascript
node(koa2) web应用模块介绍详解
Mar 29 Javascript
js中值引用和地址引用实例分析
Jun 21 Javascript
vue项目使用$router.go(-1)返回时刷新原来的界面操作
Jul 26 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
颠覆常识!无色透明的咖啡诞生了(中日双语)
2021/03/03 咖啡文化
PHP的fsockopen、pfsockopen函数被主机商禁用的解决办法
2014/07/08 PHP
PHP通过引用传递参数用法分析
2016/12/01 PHP
ThinkPHP框架使用redirect实现页面重定向的方法实例分析
2018/04/12 PHP
js中利用tagname和id获取元素的方法
2016/01/03 Javascript
js数组常用操作方法小结(增加,删除,合并,分割等)
2016/08/02 Javascript
解析Javascript单例模式概念与实例
2016/12/05 Javascript
Vue.js双向绑定实现原理详解
2016/12/22 Javascript
详解nodejs 文本操作模块-fs模块(二)
2016/12/22 NodeJs
Angular在一个页面中使用两个ng-app的方法(二)
2017/02/20 Javascript
JavaScript评论点赞功能的实现方法
2017/03/13 Javascript
禁止弹窗中蒙层底部页面跟随滚动的几种方法
2017/12/07 Javascript
Vue中的v-for指令不起效果的解决方法
2018/09/27 Javascript
Angular使用ControlValueAccessor创建自定义表单控件
2019/03/08 Javascript
javascript实现点亮灯泡特效示例
2019/10/15 Javascript
JavaScript的变量声明与声明提前用法实例分析
2019/11/26 Javascript
Python 中pandas.read_excel详细介绍
2017/06/23 Python
python实现矩阵打印
2019/03/02 Python
python连接PostgreSQL数据库的过程详解
2019/09/18 Python
Django数据库操作之save与update的使用
2020/04/01 Python
python3实现语音转文字(语音识别)和文字转语音(语音合成)
2020/10/14 Python
中医药大学市场营销专业自荐信
2013/09/29 职场文书
职业规划书如何设计?
2014/01/09 职场文书
致接力运动员广播稿
2014/02/17 职场文书
办公室主任岗位承诺书
2014/05/29 职场文书
党员个人剖析材料
2014/09/30 职场文书
学校党的群众路线教育实践活动整改措施
2014/10/25 职场文书
用人单位聘用意向书
2015/05/11 职场文书
大学自主招生自荐信(2016精选篇)
2016/01/28 职场文书
Vue实现导入Excel功能步骤详解
2021/07/03 Vue.js
前端JavaScript大管家 package.json
2021/11/02 Javascript
php实例化对象的实例方法
2021/11/17 PHP
如何解决goland,idea全局搜索快捷键失效问题
2022/04/03 Golang
Linux、ubuntu系统下查看显卡型号、显卡信息详解
2022/04/07 Servers
Python中的协程(Coroutine)操作模块(greenlet、gevent)
2022/05/30 Python
Win2008系统搭建DHCP服务器
2022/06/25 Servers