当前,React是web前端开发最流行的Javascript库之一。随着国家间的交流日益紧密,web前端需要有多语言版本,也就是国际化。通行的做法是根据用户的浏览器来自动判断用户使用的语言,显示对应的文本;但同时也提供一个语言切换按钮。本教程从零开始,介绍了React下web前端实现多语言的过程。使用Vue的同学可以自己对照进行修改。
为了简化,本教程只实现了中/英双语言。本教程需要提前安装好node和React,参考地址为:https://reactjs.org/。同时也需要一个编辑器或者IDE(推荐Atom或者Visual Studio Code)。
一、创建一个React项目在工作目录下执行以下命令并等待完成。该命令用来创建一个名为multilanguage的React项目。
npx create-react-app multilanguage
下载完所有的文件后,会有下一步操作的提示:
cd multilanguage
npm start
执行上述命令后,会在本地打开一个浏览器窗口访问http://localhost:3000/
。它显示一个React页面,只有一个大大的React Logo和学习React的超链接。恭喜你,你已经成功建立了一个React项目! 小提示:如果你的电脑3000端口被占用了,它会提示你是否使用3001端口。
让我们先按Ctrl + C键来关掉开发服务器的运行以便进行代码编写。 在Javascript中,我们通常使用i18next
库来进行多语言的开发,想详细研究的同学请点击https://www.i18next.com/。我们这里不做介绍直接使用就行。使用常用的编辑器打开刚才创建的工程,在src/
下创建一个新文件叫i18n.js
,代码如下:
import i18next from 'i18next'
import {initReactI18next} from 'react-i18next'
import XHR from 'i18next-xhr-backend'
import LanguageDetector from 'i18next-browser-languagedetector'
i18next.use(XHR).use(LanguageDetector).use(initReactI18next).init({
backend: {
loadPath:'./locales/{{lng}}.json'
},
react: {
useSuspense: true
},
fallbackLng: 'en',
preload: [
'en', 'zh','zh-cn'
],
keySeparator: false,
interpolation: {
escapeValue: false
}
})
export default i18next
简要解释一下,这个js文件主要是初始化i18next
库。i18next
库预先装载一些预定的json文件,然后根据使用的语言将标记字符串替换成对应的语言文本。这段代码定义了json路径,预装载语言等。
然后再编辑src/index.js
。首先,将第一行代码改为import React, {Suspense} from 'react';
。然后在导入语句里增加这么一行:import "./i18n";
。最后将输出的元素用Suspense
包装一下。修改完成的代码如下:
import React, {Suspense} from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import './i18n';
ReactDOM.render(
, document.getElementById('root'));
// If you want your app to work offline and load faster, you can change
// unregister() to register() below. Note this comes with some pitfalls.
// Learn more about service workers: https://bit.ly/CRA-PWA
serviceWorker.unregister();
此时项目还不能运行,我们需要安装i18n.js
中导入的库,在项目根目录下(记住不是源码根目录src
)使用命令行依次运行:
npm install i18next --save
npm install react-i18next --save
npm install i18next-xhr-backend --save
npm install i18next-browser-languagedetector --save
小提示:类似Atom或者Visual Studio Code这种IDE有终端插件,可以直接在编辑器里打开命令行,并且默认就为项目根目录。
三、生成多语言文档 从i18n.js
中我们可以看到,它需要装载网页主目录下的locales
目录下对应的json文件。这里我们使用python
来转换excel
表格以生成相应的json文件。在项目根目录下的public目录里(也就是网页根目录)新建locales
文件夹,然后打开你的office或者wps office来新建一个multilanguage.xlsx
文档(excel表格)。内容如下:
将该excel文件复制或者保存在
locales
文件夹下,然后再在该文件夹下新建一个文件convert.py
。该.py
文件的作用是将excel表格里的内容转成json并保存,代码为:
import xlrd # 引入xlrd模块
import json # 引入json模块
def convert():
file = xlrd.open_workbook('multilanguage.xlsx') # 打开excel文件对象
table = file.sheets()[0] # 通过索引顺序获取表格
rows = table.nrows # 总的行数
en = {}
zh = {}
for r in range(1,rows): # 去除表头所有从第一行开始
rowData = table.row_values(r) # 获取每一列的数据
str = rowData[0]
en_str = rowData[1]
zh_str = rowData[2]
en[str] = en_str
zh[str] = zh_str
return en,zh
def main():
en,zh = convert()
# Writing JSON data
with open('en.json', 'w') as f:
json.dump(en, f)
with open('zh-cn.json', 'w', encoding='utf-8') as f2:
json.dump(zh, f2,ensure_ascii=False)
with open('zh.json', 'w', encoding='utf-8') as f3:
json.dump(zh, f3,ensure_ascii=False)
print("convert to json success")
main()
随后在命令行里切换到locales
目录,运行python3 convert.py
。看到convert to json success
提示后,localse
目录下会生成三个json文件。
这里需要提前安装python3和相应的python库。Python3安装链接:https://www.python.org/downloads/release/python-381/,库安装推荐使用pip
工具。
应用多语言就是进行对应的文本替换。打开src/App.js
,在导入语句里增加一行import { useTranslation } from 'react-i18next';
,然后在函数组件App里增加一行const {t} = useTranslation();
。接着进行文本替换,修改完成后的代码如下:
import React from 'react';
import logo from './logo.svg';
import './App.css';
import { useTranslation } from 'react-i18next';
function App() {
const {t} = useTranslation();
return (
{t('edit')} src/App.js {t('save_load')}
{t('learn_react')}
);
}
export default App;
这时我们在项目根目录下使用终端再次运行npm start
,页面就变成中文啦。
现在我们已经实现中英文双界面了(如果你把你的语言设置改成英文,就会显示英文)。但是光是这样还不够,还需要提供一个按钮让用户可以自由切换语言并保存用户的选择。这里,我们使用了React下的Material UI的多语言图标。
首先,让我们再次按下Ctrl + C键来关闭开发服务器的运行。接着,我们在/src
目录下新建components\LanguageBtn\index.js
。 将下方的代码直接复制到刚刚生成的js文件中。
import React, {useState} from 'react'
import TranslateIcon from "@material-ui/icons/Translate"
import DownIcon from '@material-ui/icons/KeyboardArrowDown';
import MenuItem from "@material-ui/core/MenuItem";
import Button from "@material-ui/core/Button";
import Menu from "@material-ui/core/Menu";
import PropTypes from "prop-types";
import {reactLocalStorage} from 'reactjs-localstorage'
import i18next from 'i18next'
const tokenId = "multilanguage_demo";
const options = ['English', "中文"];
const lngOptions = ['en', 'zh'];
function LanguageBtn({fontColor}) {
let userProfile = reactLocalStorage.getObject(tokenId) || {};
const language = userProfile['lng'] || i18next.language;
const indexInit = (language === 'zh' || language === 'zh-CN' || language === 'zh-cn') ? 1 : 0;
const [selectedIndex, setSelectedIndex] = useState(indexInit);
const [anchorEl, setAnchorEl] = React.useState(null);
const handleClick = event => {
setAnchorEl(event.currentTarget);
};
const handleClose = () => {
setAnchorEl(null);
};
const handleCloseProfile = index => async event => {
if (index === selectedIndex) {
return;
}
setAnchorEl(null);
await i18next.changeLanguage(lngOptions[index])
userProfile['lng'] = lngOptions[index]
reactLocalStorage.setObject(tokenId, userProfile)
setSelectedIndex(index)
};
return (
{options[selectedIndex].toUpperCase()}
{options.map((option,index) => (
{option}
))}
)
}
LanguageBtn.propTypes = {
classes: PropTypes.object
};
export default LanguageBtn;
简单解释一下,这里编写了一个函数组件,它包含一个多语言按钮和一个选择菜单。点击多语言按钮后会显示选择菜单,点击菜单后会根据用户选择的语言重新显示文本并保存用户的选择。按钮有一个属性叫fontColor
,它用来设置按钮文本的颜色,以对应不同背景色下文字的显示问题。使用reactLocalStorage
将用户的选项保存在本地存储中。这里同样需要先安装material ui库,在项目根目录下使用命令行依次运行:
npm install @material-ui/core --save
npm install @material-ui/icons --save
npm install reactjs-localstorage --save
我们的语言切换按钮组件已经编写好了,可以应用到本项目任何页面的任何地方了。
六、应用切换按钮 现在可以将我们的多语言切换按钮显示到我们的主页面了。修改src/App.js
,导入我们刚才编写好的组件。
import LanguageBtn from './components/LanguageBtn';
然后在输出中加入我们编写好的组件:
这里只进行了很简单的页面修改和css设置,主要是演示按钮的功能。
修改后的App.js
最终代码如下:
import React from 'react';
import logo from './logo.svg';
import './App.css';
import { useTranslation } from 'react-i18next';
import LanguageBtn from './components/LanguageBtn';
function App() {
const {t} = useTranslation();
return (
{t('edit')} src/App.js {t('save_load')}
{t('learn_react')}
);
}
export default App;
好了,所有工作都已经完成了,让我们来再次运行npm start
进行测试。点击页面右上角的按钮,可以自由切换语言哟。
打包发布时也有几点需要注意:
- 修改项目根目录下的package.json,在依赖属性
dependencies
上面增加一行"homepage":".",
,意思为放在任意目录下。 - 在项目根目录下新建
.env
文件,里面写上这么一行:GENERATE_SOURCEMAP=false
,该行指令的意思是打包后的工程不显示源代码。
最后运行npm run build
,它将在build
文件夹下生成打包好的发布版本,把该目录下所有文件复制到Apache网页根目录或者任意二级目录下(比如multilanguagedemo
)。
在浏览器中访问,显示结果如下图。
以上就是从零构建React下的多语言实现的所有流程。
由于自身水平有限,难免会出现错误或者有不完善的地方,恳请大家留言指正和改进。基于同样的原因,这个完整的示例就不放在github上了,而是把它放在码云上。 示例码云地址:=> https://gitee.com/TianCaoJiangLin/multilanguage