当前位置: 首页 > news >正文

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 'loadsh'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'
const Welcome = () => {const commonStore = useSelector(state => state.commonStore)return (<div className="welcome"><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// ...
})

相关文章:

React如何实现国际化?

目录 一、Redux准备工作 commonTypes.js commonActions.js commonReducer.js rootReducer.js 二、然后定义SelectLang组件 index.js index.less 三、创建语言包 welcomeLocale.js index.js 四、使用 react的入口文件 App.js welcome.js 附 关于如何实现国际…...

netrw模拟nerdtree的go命令连续打开多个文件

vim9自带的文件浏览器netrw功能很强大。过去用惯了nerdtree的我&#xff0c;对netrw的文件操作还要适应一些时间。 使用netrw一段时间后发现它没有nerdtree的go命令的替代操作&#xff0c;今天就自制一个。 一、制作go命令&#xff1a; nerdtree的go命令功能&#xff1a;就是…...

算法通关村第十九关——动态规划高频问题(白银)

算法通关村第十九关——动态规划高频问题&#xff08;白银&#xff09; 前言1 最少硬币数2 最长连续递增子序列3 最长递增子序列4 完全平方数5 跳跃游戏6 解码方法7 不同路径 II 前言 摘自&#xff1a;代码随想录 动态规划五部曲&#xff1a; 确定dp数组&#xff08;dp tabl…...

Matlab如何导入Excel数据并进行FFT变换

如果你发现某段信号里面有干扰&#xff0c;想要分析这段信号里面的频率成分&#xff0c;就可以使用matlab导入Excel数据后进行快速傅里叶变换&#xff08;fft&#xff09;。 先直接上使用方法&#xff0c;后面再补充理论知识。 可以通过串口将需要分析的数据发送到串口助手&a…...

华为mate60 上线 媒介盒子多家媒体报道

为什么你的品牌营销不见效&#xff1f;如何能推动品牌破圈&#xff1f;让媒介盒子给你一些启发。本期盒子要跟大家分享地新机上市&#xff0c;数码科技行业企业该如何做线上宣传。 HUAWEI Mate 60系列8月29日官宣发布&#xff0c;出色的拍照功能、强大的性能表现和持久的续航能…...

Java知识总结(持续更新)

一、JDK、JRE、JVM三者之间的关系&#xff1f; 1. **JDK (Java Development Kit)**&#xff1a; JDK 是 Java 开发工具包&#xff0c;它包含了用于开发 Java 应用程序的所有必要工具和库。这包括 Java 编译器&#xff08;javac&#xff09;、Java 核心类库、开发工具&#x…...

缓存技术:加速应用,提高用户体验

本文总结前期某个系统中使用到的缓存使用经验—仅此而已,效果还不错。 缓存技术在系统架构设计中扮演着至关重要的角色,它不仅可以显著提高系统的性能,还可以改善用户体验。在本文章中,我们将探讨不同类型的缓存、缓存失效以及缓存淘汰等关键概念,帮助在后期的架构设计中…...

MySQL中分区与分表的区别

MySQL中分区与分表的区别 一、分区与分表的区别 分区和分表是在处理大规模数据时的两种技术手段&#xff0c;尽管它们的目标都是提升系统的性能和数据管理的效率&#xff0c;但它们的实现方式和应用场景略有不同。 1. 分区 分区是将一个大表分割为多个更小的子表&#xff0c…...

Redis主从复制集群的介绍及搭建

在现代的软件开发中&#xff0c;数据的可靠性和可用性是至关重要的。Redis&#xff0c;作为一个开源的、内存中的数据结构存储系统&#xff0c;以其出色的性能和灵活的数据结构&#xff0c;赢得了开发者们的广泛喜爱。而 Redis 的主从复制功能&#xff0c;更是为我们提供了一种…...

MAC M1芯片安装mounty读写移动硬盘中的文件

因为移动硬盘中的文件是微软公司NTFS格式&#xff0c;MAC只支持自己的APFS或者HFS&#xff0c;与微软的NTFS不兼容&#xff0c;所以需要第三方的软件来支持读写硬盘中的文件&#xff0c;经过一上午的折腾&#xff0c;最终选择安装mounty这个免费的第三方软件 工具网址连接&am…...

原生Js Canvas去除视频绿幕背景

Js去除视频背景 注&#xff1a; 这里的去除视频背景并不是对视频文件进行操作去除背景 如果需要对视频扣除背景并导出可以使用ffmpeg等库&#xff0c;这里仅作播放用所以采用这种方法 由于uniapp中的canvas经过封装&#xff0c;且 uniapp 的 drawImage 无法绘制视频帧画面&…...

Vue知识系列(1)每天10个小知识点

目录 系列文章目录知识点**1. Vue修饰符**的概念、作用、原理、特性、优点、缺点、区别、使用场景**2. 双向数据绑定**的概念、作用、原理、特性、优点、缺点、区别、使用场景**3. MVVM、MVC、MVP** 的概念、作用、原理、特性、优点、缺点、区别、使用场景**4. slot** 的概念、…...

Elasticsearch(三)聚合基本使用

基础概念 bucket 数据分组&#xff0c;一些数据按照某个字段进行bucket划分&#xff0c;这个字段值相同的数据放到一个bucket中。可以理解成Java中的Map<String, List>结构&#xff0c;类似于Mysql中的group by后的查询结果。 metric&#xff1a; 对一个数据分组执行…...

单片机C语言实例:14、音频输出

一、喇叭发声原理 程序实例1&#xff1a; #include<reg52.h> //包含头文件&#xff0c;一般情况不需要改动&#xff0c;头文件包含特殊功能寄存器的定义sbit SPK P1^2; //定义喇叭端口 /*------------------------------------------------函数声明 --------------…...

docker 和 podman的区别

Podman 和 Docker 都是用于容器化应用程序的工具&#xff0c;它们在很多方面非常相似&#xff0c;但也有一些关键区别&#xff1a; 1. 架构和权限&#xff1a; - Docker&#xff1a;Docker 使用守护进程&#xff08;dockerd&#xff09;来管理容器&#xff0c;它需要在操作…...

苹果手机远程控制安卓手机,为什么不能发起控制?

这位用户想要用iOS设备远程控制安卓设备&#xff0c;在被控端安装好AirDroid之后&#xff0c;就在控制端的苹果手机上也安装了AirDroid&#xff0c;然而打开控制端的软件&#xff0c;却没有在手机界面上看到【远程控制】按钮&#xff0c;于是提出了以上疑问。 解答 想要让iOS设…...

Gradle 配置国内镜像

我们在使用gradle构建项目的时候&#xff0c;每当需要build或者刷新依赖的时候&#xff0c;由于gradle需要从服务器下载各种依赖包&#xff0c;速度非常慢&#xff0c;根本原因是由于gradle服务器在国外&#xff0c;而国内有些一些大厂和高校(比如阿里&#xff0c;华为&#xf…...

Spring AOP使用指南: 强大的面向切面编程技术

&#x1f337;&#x1f341; 博主猫头虎&#xff08;&#x1f405;&#x1f43e;&#xff09;带您 Go to New World✨&#x1f341; &#x1f984; 博客首页——&#x1f405;&#x1f43e;猫头虎的博客&#x1f390; &#x1f433; 《面试题大全专栏》 &#x1f995; 文章图文…...

Spring Boot集成Elasticsearch实战

文章目录 一、简介二、安装与配置Elasticsearch三、集成Spring Boot与Elasticsearch1. 添加依赖与配置文件2. 创建Elasticsearch数据模型3. 定义Elasticsearch仓库接口4. 实现Elasticsearch数据操作 四、基本查询与索引操作1. 插入与更新数据2. 删除数据与索引3. 条件查询与分页…...

【python零基础入门学习】python基础篇之文件对象open、模块以及函数的使用(三)

本站以分享各种运维经验和运维所需要的技能为主 《python》&#xff1a;python零基础入门学习 《shell》&#xff1a;shell学习 《terraform》持续更新中&#xff1a;terraform_Aws学习零基础入门到最佳实战 《k8》暂未更新 《docker学习》暂未更新 《ceph学习》ceph日常问题解…...

蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练

前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1)&#xff1a;从基础到实战的深度解析-CSDN博客&#xff0c;但实际面试中&#xff0c;企业更关注候选人对复杂场景的应对能力&#xff08;如多设备并发扫描、低功耗与高发现率的平衡&#xff09;和前沿技术的…...

学习STC51单片机31(芯片为STC89C52RCRC)OLED显示屏1

每日一言 生活的美好&#xff0c;总是藏在那些你咬牙坚持的日子里。 硬件&#xff1a;OLED 以后要用到OLED的时候找到这个文件 OLED的设备地址 SSD1306"SSD" 是品牌缩写&#xff0c;"1306" 是产品编号。 驱动 OLED 屏幕的 IIC 总线数据传输格式 示意图 …...

高危文件识别的常用算法:原理、应用与企业场景

高危文件识别的常用算法&#xff1a;原理、应用与企业场景 高危文件识别旨在检测可能导致安全威胁的文件&#xff0c;如包含恶意代码、敏感数据或欺诈内容的文档&#xff0c;在企业协同办公环境中&#xff08;如Teams、Google Workspace&#xff09;尤为重要。结合大模型技术&…...

Rust 异步编程

Rust 异步编程 引言 Rust 是一种系统编程语言,以其高性能、安全性以及零成本抽象而著称。在多核处理器成为主流的今天,异步编程成为了一种提高应用性能、优化资源利用的有效手段。本文将深入探讨 Rust 异步编程的核心概念、常用库以及最佳实践。 异步编程基础 什么是异步…...

今日科技热点速览

&#x1f525; 今日科技热点速览 &#x1f3ae; 任天堂Switch 2 正式发售 任天堂新一代游戏主机 Switch 2 今日正式上线发售&#xff0c;主打更强图形性能与沉浸式体验&#xff0c;支持多模态交互&#xff0c;受到全球玩家热捧 。 &#x1f916; 人工智能持续突破 DeepSeek-R1&…...

嵌入式学习笔记DAY33(网络编程——TCP)

一、网络架构 C/S &#xff08;client/server 客户端/服务器&#xff09;&#xff1a;由客户端和服务器端两个部分组成。客户端通常是用户使用的应用程序&#xff0c;负责提供用户界面和交互逻辑 &#xff0c;接收用户输入&#xff0c;向服务器发送请求&#xff0c;并展示服务…...

android RelativeLayout布局

<?xml version"1.0" encoding"utf-8"?> <RelativeLayout xmlns:android"http://schemas.android.com/apk/res/android"android:layout_width"match_parent"android:layout_height"match_parent"android:gravity&…...

保姆级【快数学会Android端“动画“】+ 实现补间动画和逐帧动画!!!

目录 补间动画 1.创建资源文件夹 2.设置文件夹类型 3.创建.xml文件 4.样式设计 5.动画设置 6.动画的实现 内容拓展 7.在原基础上继续添加.xml文件 8.xml代码编写 (1)rotate_anim (2)scale_anim (3)translate_anim 9.MainActivity.java代码汇总 10.效果展示 逐帧…...

大数据治理的常见方式

大数据治理的常见方式 大数据治理是确保数据质量、安全性和可用性的系统性方法&#xff0c;以下是几种常见的治理方式&#xff1a; 1. 数据质量管理 核心方法&#xff1a; 数据校验&#xff1a;建立数据校验规则&#xff08;格式、范围、一致性等&#xff09;数据清洗&…...

【深尚想】TPS54618CQRTERQ1汽车级同步降压转换器电源芯片全面解析

1. 元器件定义与技术特点 TPS54618CQRTERQ1 是德州仪器&#xff08;TI&#xff09;推出的一款 汽车级同步降压转换器&#xff08;DC-DC开关稳压器&#xff09;&#xff0c;属于高性能电源管理芯片。核心特性包括&#xff1a; 输入电压范围&#xff1a;2.95V–6V&#xff0c;输…...