React如何实现国际化?

目录

 一、Redux准备工作

commonTypes.js 

commonActions.js 

commonReducer.js 

rootReducer.js 

 二、然后定义SelectLang组件

index.js 

index.less 

 三、创建语言包

welcomeLocale.js 

 index.js

四、使用

react的入口文件

App.js 

 welcome.js


关于如何实现国际化,有很多方法,比如 vue-i18n  react-i18next  umi 中的 useIntl 等等,网上有很多的资料可以参看,今天不想使用这些库,于是乎打算自己写一个,期初设计是写两个语言文件,每次改变时把语言标识存 localStorage 中,然后刷新页面获取对应的语言文件,但是,本着提供良好的用户体验原则,否则了这一想法。于是想到了使用全局状态容器 Redux ,这样就可以在不刷新页面的情况下更新页面。尝试一下,效果还可以。以React为例,Vue实现也类似,具体代码如下:

 一、Redux准备工作

为例防止文件过大,对Redux进行了拆分目录如下:

commonTypes.js 

// commonTypes.js
export const SET_LANGUAGE = 'set_language'
export const SET_LANGUAGE_OBJ = 'set_language_obj'

commonActions.js 

// commonActions.js
import {SET_LANGUAGE,SET_LANGUAGE_OBJ
} from '../actionTypes/commonTypes'export const setLanguage = payload => {return {type: SET_LANGUAGE,payload}
}export const setLanguageObj = payload => {return {type: SET_LANGUAGE_OBJ,payload}
}

commonReducer.js 

// commonReducer.js
import {SET_LANGUAGE,SET_LANGUAGE_OBJ
} from '../actionTypes/commonTypes'
let lang = 'zh_CN'
if (localStorage.getItem('language') === 'zh_CN' ||localStorage.getItem('language') === 'en_US'
) {// 防止莫名出现其他值lang = localStorage.getItem('language')
}
const initState = {language: lang,languageObj: {}
}
const commonReducer = (state = initState, action) => {const { type, payload } = actionswitch (type) {case SET_LANGUAGE:return {...state,language: payload}case SET_LANGUAGE_OBJ:return {...state,languageObj: payload}default:return {...state}}
}export default commonReducer

rootReducer.js 

// rootReducer.js
import commonReducer from './commonReducer'const rootReducer = {commonStore: commonReducer
}
export default rootReducer
// index.js
import { createStore, combineReducers } from 'redux'
import rootReducer from './reducers/rootReducer'
const store = createStore(combineReducers(rootReducer))
export default store

 二、然后定义SelectLang组件

样式参考的antd,目录如下:

index.js 

// index.js
import React from 'react'
import { useSelector, useDispatch } from 'react-redux'
import { setLanguage } from '../../redux/actions/commonActions'import './index.less'const SelectLang = props => {const language = useSelector(state => state.commonStore.language)const dispatch = useDispatch()const changeLanguage = () => {let lang = language === 'zh_CN' ? 'en_US' : 'zh_CN'localStorage.setItem('language', lang)dispatch(setLanguage(lang))}let selClassZH = language === 'zh_CN' ? 'acss-1nbrequ acss-1n10ay4' : 'acss-1nbrequ acss-3ew1dt'let selClassEN = language === 'en_US' ? 'acss-1nbrequ acss-1n10ay4' : 'acss-1nbrequ acss-3ew1dt'return (<div className="acss-llcihc" onClick={() => changeLanguage()}><span className={selClassZH}>中</span><span className={selClassEN}>En</span></div>)
}export default SelectLang

index.less 

/* index.less */
.acss-llcihc {position: relative;cursor: pointer;width: 1.3rem;height: 1.3rem;display: inline-block;.acss-1nbrequ {position: absolute;font-size: 1.3rem;line-height: 1;color: #ffffff;}.acss-1n10ay4 {left: -5%;top: 0;z-index: 1;color: #ffffff;-webkit-transform: scale(0.7);-moz-transform: scale(0.7);-ms-transform: scale(0.7);transform: scale(0.7);transform-origin: 0 0;}.acss-3ew1dt {right: -5%;bottom: 0;z-index: 0;-webkit-transform: scale(0.5);-moz-transform: scale(0.5);-ms-transform: scale(0.5);transform: scale(0.5);transform-origin: 100% 100%;}
}

 三、创建语言包

防止文件过大,可以按类别穿件文件,目录如下:

welcomeLocale.js 

// welcomeLocale.js
module.exports = {welcome: 'Welcome To System'
}

 index.js

// index.jsimport _ from 'lodash'const modulesFilesen = require.context('./en', true, /\.js$/)
const modulesen = modulesFilesen.keys().reduce((modules, modulePath) => {const moduleName = modulePath.replace(/^.\/(.*)\.js/, '$1')const value = modulesFilesen(modulePath)modules[moduleName] = valuereturn modules
}, {})const modulesFileszh = require.context('./zh', true, /\.js$/)
const moduleszh = modulesFileszh.keys().reduce((modules, modulePath) => {const moduleName = modulePath.replace(/^.\/(.*)\.js/, '$1')const value = modulesFileszh(modulePath)modules[moduleName] = valuereturn modules
}, {})// 动态读取文件并组合到一个对象中
export const languageObj = {zh_CN: moduleszh,en_US: modulesen
}// 判断语言包中是否存在该字段,没有返回空
export const formatMessage = (titles, storeState) => {let titleList = titles.split('.')let resObj = _.cloneDeep(storeState)for (let index = 0; index < titleList.length; index++) {const element = titleList[index]if (resObj[element]) {resObj = resObj[element]} else {resObj = ''}}return resObj.toString()
}

四、使用

react的入口文件

import React from 'react'
import ReactDOM from 'react-dom'
import { BrowserRouter } from 'react-router-dom'
import './index.less'
import App from './App'
import { languageObj } from './locale'
import store from './redux'
import { setLanguageObj } from './redux/actions/commonActions'
import { Provider } from 'react-redux'const state = store.getState()
const language = state.commonStore.language
if (language === 'zh_CN') {store.dispatch(setLanguageObj(languageObj['zh_CN']))
}
if (language === 'en_US') {store.dispatch(setLanguageObj(languageObj['en_US']))
}
ReactDOM.render(<Provider store={store}><BrowserRouter basename={process.env.PUBLIC_URL}><App /></BrowserRouter></Provider>,document.getElementById('root')
)

App.js 

// App.jsimport React, { useEffect, useState } from 'react'
import { Route, withRouter, Redirect } from 'react-router-dom'
import { ConfigProvider, App } from 'antd'
import { useSelector, useDispatch } from 'react-redux'
import dayjs from 'dayjs'
import 'dayjs/locale/zh-cn'
import zh_CN from 'antd/locale/zh_CN'
import en_US from 'antd/locale/en_US'
import { setLanguageObj } from './redux/actions/commonActions'
import { languageObj } from './locale'
import Welcome from './welcome'
import './App.less'
dayjs.locale('zh-cn')const AppPage = () => {const dispatch = useDispatch()const [locale, setLocal] = useState({})const languageState = useSelector(state => state.commonStore.language)useEffect(() => {if (languageState === 'zh_CN') {dayjs.locale('zh-cn')setLocal(zh_CN)}if (languageState === 'en_US') {dayjs.locale('en')setLocal(en_US)}}, [languageState])useEffect(() => {dispatch(setLanguageObj(languageObj[languageState]))}, [locale])return (<div><ConfigProviderlocale={locale}><App><Route exact path="/" component={Welcome} /></App></ConfigProvider></div>)
}export default withRouter(AppPage)

 welcome.js

 formatMessage 方法参数:

languageObj.welcomeLocale.welcome

  • languageObj:redux中的对象名
  • welcomeLocale: locale中的文件名
  • welcome:具体内容值

 commonStore :具体store, 可在formatMessage方法优化一下,就可以不用传了,自己处理尝试吧。

// welcome.jsimport React from 'react'
import { useSelector } from 'react-redux'
import { formatMessage } from '../locale'
import SelectLang from '../components/SelectLang'
const Welcome = () => {const commonStore = useSelector(state => state.commonStore)return (<div className="welcome"><SelectLang /><h2 className="welcome-text">{formatMessage('languageObj.welcomeLocale.welcome', commonStore)}</h2></div>)
}export default Welcome

如果遇到不能动态刷新,尝试可以一下 store.subscribe 

import store from './redux'
store.subscribe(() => {const state = store.getState()const language = state.commonStore.language// ...
})

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/131699.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

进程地址空间(Linux虚拟内存机制)

文章目录 一.Linux进程地址空间的结构二.Linux管理进程地址空间的方式三.Linux进程使用物理内存的模型四.进程地址空间的存在意义 本章理论基于32位平台的Linux–kernel 2.6.32版本内核 一.Linux进程地址空间的结构 为了保证内存安全,现代操作系统不允许应用程序(进程)直接访问…

Redis总结(二)

目录 Redis线程模型 Redis是单线程吗&#xff1f; Redis采用单线程为什么那么快&#xff1f; I/O多路复用模型 Redis持久化 Redis如何保证数据不丢失&#xff1f; AOF日志 AOF三种写回策略 AOF重写机制 触发机制 重写原理 RDB快照 执行快照时&#xff0c;数据能被…

实现 js 中所有对象的深拷贝(包装对象,Date 对象,正则对象)

通过递归可以简单实现对象的深拷贝&#xff0c;但是这种方法不管是 ES6 还是 ES5 实现&#xff0c;都有同样的缺陷&#xff0c;就是只能实现特定的 object 的深度复制&#xff08;比如数组和函数&#xff09;&#xff0c;不能实现包装对象 Number&#xff0c;String &#xff0…

180B参数的Falcon登顶Hugging Face,vs chatGPT 最好开源大模型使用体验

文章目录 使用地址使用体验test1:简单喜好类问题test2:知识性问题test3:开放性问题test4:中文支持test5:问题时效性test6:学术问题使用地址 https://huggingface.co/spaces/tiiuae/falcon-180b-demo 使用体验 相比Falcon-7b,Falcon-180b拥有1800亿的参数量

【Axure高保真原型】日历日期原型模板

今天和大家分享日历日期的原型模板&#xff0c;包括月计划、周计划、日计划的原型案例&#xff0c;以及日期、时间、月份、区间选择器……具体效果可以点击下方视频观看 【原型预览及下载地址】 Axure 原型 备用地址&#xff1a;Untitled Document 【原型效果】 【原型效果…

Unity技术手册-UGUI零基础详细教程-Canvas详解

点击跳转专栏>Unity3D特效百例点击跳转专栏>案例项目实战源码点击跳转专栏>游戏脚本-辅助自动化点击跳转专栏>Android控件全解手册点击跳转专栏>Scratch编程案例点击跳转>软考全系列点击跳转>蓝桥系列 &#x1f449;关于作者 专注于Android/Unity和各种游…

【Unity】Unity坑的集锦之RenderTexture打包黑屏

问题&#xff1a;Camera Output Texture设置RenderTexture后&#xff0c;打包用来Save PNG&#xff0c;黑屏 如果你打AB 包&#xff0c;然后是相机的OutputTexture是拖拽的话&#xff0c;记得将包一起打入 或者你可以代码赋值 Camera.targetTexture await Loader.LoadAsset&l…

【算法系列 | 8】深入解析查找算法之—二分查找

序言 心若有阳光&#xff0c;你便会看见这个世界有那么多美好值得期待和向往。 决定开一个算法专栏&#xff0c;希望能帮助大家很好的了解算法。主要深入解析每个算法&#xff0c;从概念到示例。 我们一起努力&#xff0c;成为更好的自己&#xff01; 今天第8讲&#xff0c;讲一…

IO day7

1->x.mind 2-> A进程 B进程

[Google DeepMind] LARGE LANGUAGE MODELS AS OPTIMIZERS

Large Language Models as Optimizers 文章链接 总体架构Optimization by PROmpting (OPRO)&#xff1a;最开始输入meta-prompt&#xff0c;这个初始的meta-prompt基本上只是对优化任务进行了描述(也会有few-shot example)。输入后LLM便会生成一个solution&#xff0c;这个sol…

Vue3:proxy数据取值proxy[Target]取值

vue3底层是使用proxy进行代理的&#xff0c;而proxy中[[Target]]才是想要的值。 获取target值的方式一&#xff1a; <script setup>//先引入toRawimport { toRaw } from vue;//再使用console.log(toRaw(数据名))</script> 获取target值的方式二&#xff1a; <…

NIO基础

一、NIO基础 Java New IO是从Java1.4版本开始引入的一个新的IO api&#xff0c;可以替代以往的标准IO&#xff0c;NIO相比原来的IO有同样的作用和目的&#xff0c;但是使用的方式完全不一样&#xff0c;NIO是面向缓冲区的&#xff0c;基于通道的IO操作&#xff0c;这也让它比传…

Java学习之--类和对象

&#x1f495;粗缯大布裹生涯&#xff0c;腹有诗书气自华&#x1f495; 作者&#xff1a;Mylvzi 文章主要内容&#xff1a;Java学习之--类和对象 类和对象 类的实例化&#xff1a; 1.什么叫做类的实例化 利用类创建一个具体的对象就叫做类的实例化&#xff01; 当我们创建了…

Vulnhub系列靶机---HarryPotter-Fawkes-哈利波特系列靶机-3

文章目录 信息收集主机发现端口扫描dirsearch扫描gobuster扫描 漏洞利用缓冲区溢出edb-debugger工具msf-pattern工具 docker容器内提权tcpdump流量分析容器外- sudo漏洞提权 靶机文档&#xff1a;HarryPotter: Fawkes 下载地址&#xff1a;Download (Mirror) 难易程度&#xff…

工厂除静电除尘设备--离子风枪

静电无处不在&#xff0c;区别在于静电的多少而已。特别是工业生产过程中&#xff0c;大量的静电会有很多危害。 静电的危害有几点&#xff1a;1.引起电子设备的故障或误动作&#xff0c;造成电磁干扰。2.击穿集成电路和精密的电子元件&#xff0c;或使元件老化&#xff0c;拉…

关于一个left join的易错点

很多人在学习mysql的时候应该都出现过很多问题&#xff0c;特别是连接方面的问题应该最多&#xff0c;希望这篇文章帮助到正在找bug的你 Java报错数据返回数量出现错误 遇到这种问题一定要看日志 很明显通过left join查询除了两条数据并且为空 马上思考错误的原因&#xff0c;…

【Java基础篇 | 面向对象】--- 聊聊什么是多态(上篇)

个人主页&#xff1a;兜里有颗棉花糖 欢迎 点赞&#x1f44d; 收藏✨ 留言✉ 加关注&#x1f493;本文由 兜里有颗棉花糖 原创 收录于专栏【JavaSE_primary】 本专栏旨在分享学习JavaSE的一点学习心得&#xff0c;欢迎大家在评论区讨论&#x1f48c; 目录 一、什么是多态二、多…

数据结构基础7:二叉树【链式结构】实现和递归思想。

二叉树的链式结构实现 一.二叉树链式结构的实现&#xff1a;1.前置说明&#xff1a;1.创建二叉树&#xff1a;2.二叉树的结构&#xff1a; 2.二叉树的遍历&#xff1a;1.二叉树的前中后序遍历&#xff1a;2.内容拓展&#xff1a; 二.二叉树链式(题目)题目一&#xff1a;计算节点…

小程序源码:多功能口袋工具箱微信小程序源码-带流量主|云开发(更新)

这里主要分享多功能口袋工具箱微信小程序源码&#xff0c;有带流量主&#xff0c;而且超多功能工具箱组合的微信小程序源码。无需服务器即可搭建&#xff0c;可以设置流量主赚取收益。 源码链接&#xff1a; 网盘源码 密码&#xff1a;hma8 工具箱的应用一览&#xff1a; 1…

【计算机网络】传输层协议——TCP(上)

文章目录 TCPTCP协议段格式报头和有效载荷如何分离&#xff1f;4位首部长度 TCP可靠性确认应答机制的提出序号和确认序号为什么序号和确认序号在不同的字段&#xff1f; 16位窗口大小 6个标志位标志位本质具体标志位PSHRSTURG 超时重传机制 文章目录 TCPTCP协议段格式报头和有效…