React项目国际化(antd)多语言开发

栏目: 服务器 · 发布时间: 6年前

内容简介:最近搭建一个项目,从0开始做,需要做多语言的国际化,今天搞了一下,基本达到了想要的效果,第一次发掘金勿喷,在这里简单分享下:国际化是一个看似简单,实则非常复杂的领域,实际进行国际化工作时,大家会发现它往往会涉及很多内容:

前言

最近搭建一个项目,从0开始做,需要做多语言的国际化,今天搞了一下,基本达到了想要的效果,第一次发掘金勿喷,在这里简单分享下:

React项目国际化(antd)多语言开发

背景

国际化方案

  • 国际化方案概述
  • 前端国际化详解、举例
  • 国际化资源文件管理
  • 项目之间、开发者与翻译者之间的协作
  • 国际化规范附录
  • 扩展阅读

国际化方案概述

国际化是一个看似简单,实则非常复杂的领域,实际进行国际化工作时,大家会发现它往往会涉及很多内容:

  • 前端国际化
  • 服务端国际化
  • 国际化资源文件管理
  • 项目之间、开发者与翻译者之间如何协作

而且,国际化方案往往与具体的技术栈是绑定的。

本国际化方案仅针对 React 技术栈,且不会涉及服务端国际化内容。

前端国际化详解、举例

国际化的核心步骤有两步:

  1. 创建资源文件,以 key-value 方式存储
  2. 加载资源文件,将页面上 key 的内容替换为相关 value

一些探索

也说不上是探索吧,就Google了一波, GitHub 上找了一个比较成熟的库如下:

react-i18next

react-intl

react-intl-universa

接下来一一介绍一下如何使用

react-i18next

安装

npm install i18next react-i18next --save复制代码

引入App.js

import i18n from 'i18next';
import { useTranslation, initReactI18next } from 'react-i18next';
复制代码

初始化

const lng = 'en';
i18n
  .use(initReactI18next) // passes i18n down to react-i18next
  .init({
    resources: {
      en: {
        translation: {
          Welcome: 'Welcome to React',
        },
      },
      zh: {
        translation: {
          Welcome: '欢迎进入react',
        },
      },
    },
    lng: lng,
    fallbackLng: lng,

    interpolation: {
      escapeValue: false,
    },
  });
复制代码

实际使用结果

function App() {
  const { t } = useTranslation();
  return (
    <div className="App">
      <p>{t('Welcome')}</p>
    </div>
  );
}

export default App;
复制代码

封装后的成果:

// ...
import i18n from '@src/i18n';
// xxx component
console.log('i18n来一发:', i18n.t('INVALID_ORDER'));
render() { 
  // ...
  <button> {i18n.t('INVALID_ORDER')} </button>
}复制代码

react-intl

背景:

用于国际化 React 组件,提供 React 组件和 API 来格式化日期,数字,字符串(包括单复数和翻译)。

react-intl库是业界很受欢迎的库之一。 react-intl用包裹组件的形式装饰你的React.Component,动态注入国际化消息,以便能够动态加载语言环境数据,并且无需重新加载页面

安装:

npm install react-intl --save复制代码

载入语言环境数据。

React Intl 依赖这些数据来支持单复数和相对时间格式化的功能。

// Main.js
import { addLocaleData } from 'react-intl'; /* react-intl imports */
import en from 'react-intl/locale-data/en';
import zh from 'react-intl/locale-data/zh';
addLocaleData([...en, ...zh]);  // 引入多语言环境的数据  复制代码

虽然我只用到了文本翻译的功能,以为就不需要加载这些数据,但后来发现这是必须的步骤。不然会报错:

[React Intl] Missing locale data for locale: "zh". Using default locale: "en" as fallback.复制代码

使用

组件包裹需要实现国际化的根组件,这个组件树之后就会在配置的i18n上下文中了。

由于项目中用到了 react-hot-loader ,根组件 Main<AppContainer> 包裹了,并且是从单独的一个文件 import 了 Main 组件。

//app.js
import { AppContainer } from 'react-hot-loader'
import Main from './components/Main'
//... ...
const render = Component => {
    ReactDOM.render(
        <AppContainer>
            <Component />
        </AppContainer>,
        document.getElementById('app')
    )
}
render(Main);复制代码

于是直接在 Main.js 中使用 <IntlProvider> 组件。把它加到 render() 返回节点的最外层就行了。

// Main.js
import { addLocaleData, IntlProvider } from 'react-intl'; /* react-intl imports */
render(){
    return (
        <IntlProvider>
          //··· ···
        </IntlProvider>
    )
}复制代码

添加多种语言对应的文本。

比如要支持中英文,为了方便之后维护,可以新建两个文件:

locale目录下新建
// en_US.js
const en_US = {
    hello: "Hello!",
    //... ...
}
export default en_US;

// zh_CN.js
const zh_CN = {
    hello: "你好!",
    //... ...
}
export default zh_CN;复制代码

然后在Main.js中引入这两个变量。

// Main.js
import zh_CN from "../locale/zh_CN"     // import defined messages in Chinese
import en_US from "../locale/en_US"     // import defined messages in English复制代码

全局配置当前的语言,和相对应的文本。

即配置 <IntlProvider> 组件的两个属性 localemessages

// Main.js
render(){
    let messages = {}
    messages['en'] = en_US;
    messages['zh'] = zh_CN;
    return (
        <IntlProvider locale={this.state.lang} messages={messages[this.state.lang]}>
            //··· ···
        </IntlProvider>
    )
}复制代码

这样基本配置就完成了,可以通过改变 this.state.lang 的值来改变页面语言。

// Main.js
/**
 * Change language
 * @param {String} lang new language
 */
changeLanguage(lang) {
    this.setState({
        lang: lang
    })
}复制代码

接下来,添加翻译的文本到页面中

基本只需要使用到一个组件: <FormattedMessage> 。这个组件默认生成一个 <span> ,内容是翻译后的文本,也就是 messages 中对应字段的值。

在需要添加国际化文本的组件中,引入 FormattedMessage 组件。

import { FormattedMessage  } from 'react-intl'; /* react-intl imports */
//... ...
<FormattedMessage id="hello" />复制代码

当前语言为 en 时,生成结果:

<span>Hello!</span>复制代码

到这里, react-intl 基本的国际化就实现了。

尾声

编写规范

  1. 必须填写 defaultMessage,并将 defaultMessage 作为中文翻译
  2. id 不得重复
  3. 在使用 intl.formatMessage() 时,必须使用 defineMessages,预定义消息

扩展阅读

react-intl-universal

背景:

由阿里巴巴推出的react国际化库

这个库最好地方在于使用简单方便,侵入性低

安装

使用npm安装

npm install react-intl-universal --save复制代码

初始化

在初始页面,进行该库的初始化,配置语言包,json文件根据需要支持几种语言来决定,下面的图片中仅支持中英文

React项目国际化(antd)多语言开发

于项目入口文件中配置国际化

import intl from 'react-intl-universal';

// locale data
const locales = {
  "en-US": require('./locales/en-US.json'),
  "zh-CN": require('./locales/zh-CN.json'),
};

class App extends Component {

  state = {initDone: false}

  componentDidMount() {
    this.loadLocales();
  }

  loadLocales() {
    // react-intl-universal 是单例模式, 只应该实例化一次
    intl.init({
      currentLocale: 'en-US', // TODO: determine locale here
      locales,
    })
    .then(() => {
    this.setState({initDone: true});
    });
  }

  render() {
    return (
      this.state.initDone &&
      <div>
        {intl.get('SIMPLE')}
      </div>
    );
  }

}复制代码

语言配置文件可以是json或者js,json格式如下:

英语配置文件 ./locales/en-US.json

{
    "SIMPLE": "Simple Sentence",
    "LANG_TYPE": "paas-us",
    "INPUT_MOBILE": "Mobile Number",
    "HELLO": "Hello, {name}. Welcome to {where}!"
}复制代码

中文配置文件 ./locales/zh-CN.json

{
    "SIMPLE": "简单的句子",
    "LANG_TYPE": "paas-cn",
    "INPUT_MOBILE": "手机号",
    "HELLO": "你好, {name}。欢迎来到{where}!"
}复制代码

调用

在刚才的初始化代码中,render函数里面已经进行了调用了。在整个项目的其他地方,由于已经进行了初始化了,所以可以直接调用了。调用的例子如下:

import intl from 'react-intl-universal';

class Test extends Component {
  render() {
    return (
      <div>
        {intl.get('INPUT_MOBILE')}
      </div>
    );
  }

}复制代码

切换

再来看一下初始化函数

intl.init({
    currentLocale: 'en-US', // TODO: determine locale here
    locales,
})复制代码

初始化的时候,除了直接指定语言外,还可以由 函数determineLocale 根据以下配置进行指定:

  1. Url中的query参数
  2. cookie中的参数
  3. 浏览器的当前语言(当没有配置query参数和cookie参数时)

这些配置的生效如下面代码所示:

let currentLocale = intl.determineLocale({
  urlLocaleKey: "lang",
  cookieLocaleKey: "lang"
});

intl.init({
    currentLocale, // determine locale here
    locales,
})复制代码

那么,我们可以利用如下方式进行切换:当选择相应语言时,触发回调函数,在函数内,修改url或者cookie,然后进行页面刷新,重新初始化,即可以切换语言了。

下面我给出一个根据cookie切换的例子:

handleClick = (lang) => {
    Cookies.set('lang', lang, { expires: '1Y' });
    window.location.reload(true);
}复制代码

进阶

react-intl-universal库在语言处理上,还有很多其他功能,如:

  • 带HTML标签的HTML 文本
  • 变量
  • 单复数形式
  • 货币
  • 日期

html中引用资源包里的文字

a.纯文字,使用intl.get()

<div> {intl.get('SIMPLE')} </div>复制代码

b.带html模板的文字,使用intl.getHTML()方法

例如资源包里是这样定义的

{ 
   "SIMPLE": "This is <span style='color:red'>HTML</span>" 
}复制代码

引用时需使用getHTML()方法获取文字

<div>{intl.getHTML('SIMPLE')}</div>
复制代码

数字形式和千分位分隔符

下例中的变量为num,给它标记为plural后,它的值只能为数字。当num值为0时,显示"no photos.";当值为1时,显示"one photo.";当值为其他数字比如25000时,显示“25,000 photos.”,这里的'#'表示给num的值添加千分位分隔符后显示

{ 
   "PHOTO": "You have {num, plural, =0 {no photos.} =1 {one photo.} other {# photos.}}" 
}复制代码

引用结果如下:

intl.get('PHOTO', {num:0}); // "You have no photos."
intl.get('PHOTO', {num:1}); // "You have one photo."
intl.get('PHOTO', {num:1000000}); // "You have 1,000,000 photos."复制代码

显示货币格式

具体语法为{变量名, 类型, 格式化},下例中变量名为"price",它的类型是number,"USD"表示在值前面加上美元符号($)

{ 
   "SALE_PRICE": "The price is {price, number, USD}" 
}复制代码

引用及显示结果如下:

intl.get('SALE_PRICE', {price:123456.78}); // The price is $123,456.78复制代码

显示日期

语法同上:{变量名, 类型, 格式化},当类型为"date"时,格式化有以下几个选项:short,medium,long,full,也可不格式化

{
  "SALE_START": "Sale begins {start, date}",
  "SALE_END": "Sale ends {end, date, long}"
}复制代码

引用及显示:

intl.get('SALE_START', {start:new Date()}); // Sale begins 4/19/2017
intl.get('SALE_END', {end:new Date()}); // Sale ends April 19, 2017复制代码

配置默认message

当遇到比如因拼写错误导致无法匹配到资源包里的文字时,可以事先配置默认的message,这时当无法匹配的资源包时会显示默认message

//"defaultMessage()"可简写为"d()"
intl.get('not-exist-key').defaultMessage('没有找到这句话');复制代码

同理亦可配置带html模板的默认message

intl.getHTML('not-exist-key').d(<h2>没有找到这句话</h2>)复制代码

带变量的message

资源包里的配置如下

{
    "HELLO": "Hello, {name}. Welcome to {where}!" 
}复制代码

在html中引用时

<div> intl.get('HELLO', {name:'banana', where:'China'}) </div>复制代码

显示的结果为:Hello, banana. Welcome to China!

尾声

到此 react-intl-universal 基本的使用方法介绍完毕了,如果以上达不到你的需求请前往git翻看更多readme文档和api文档。

git地址: github.com/alibaba/rea…

antd/antd-mobile 国际化方案

LocaleProvider国际化

组件LocaleProvider 用于全局配置国际化文案

ant.design/components/…

为组件内建文案提供统一的国际化支持

使用

LocaleProvider 使用 React 的context 特性,只需在应用外围包裹一次即可全局生效。

import { LocaleProvider } from 'antd';
import zh_CN from 'antd/lib/locale-provider/zh_CN';
import moment from 'moment';
import 'moment/locale/zh-cn';

moment.locale('zh-cn');
...

return <LocaleProvider locale={zh_CN}><App /></LocaleProvider>;复制代码

提供了英语,中文,俄语,法语,德语等多种语言支持,所有语言包可以在 这里 找到。

注意:如果你需要使用 UMD 版的 dist 文件,应该引入 antd/dist/antd-with-locales.js ,同时引入 moment 对应的 locale,然后按以下方式使用:

const { LocaleProvider, locales } = window.antd;

...

return <LocaleProvider locale={locales.en_US}><App /></LocaleProvider>;复制代码

到此今天的国际化分享大全就结束了,我个人感觉还是 react-intl-universal 比较好用,如果对你有帮助记得点点关注哦,

案例已上传到 github ,有相关需求的可以去看看,第一次写勿喷,如果有问题请指正!


以上所述就是小编给大家介绍的《React项目国际化(antd)多语言开发》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!

查看所有标签

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

Programming in Haskell

Programming in Haskell

Graham Hutton / Cambridge University Press / 2007-1-18 / GBP 34.99

Haskell is one of the leading languages for teaching functional programming, enabling students to write simpler and cleaner code, and to learn how to structure and reason about programs. This introduc......一起来看看 《Programming in Haskell》 这本书的介绍吧!

URL 编码/解码
URL 编码/解码

URL 编码/解码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

RGB CMYK 转换工具
RGB CMYK 转换工具

RGB CMYK 互转工具