uniapp-Vue项目如何实现国际化,实现多语言切换,拒绝多套开发,一步到位,看这篇就够

news2024/11/15 8:47:04

一  安装

找到自己的项目,输入cmd进入命令行,输入安装命令,点击回车进行下载:

npm install vue-i18n@next

下载完将在项目的配置文件中看到:

二  使用

2.1 在项目中创建一个文件夹如:lang 用于存放不同语言的包。这些语言文件通常为JSON格式

2.2 在项目main.js文件中引入并初始化VueI18n。这包括引入上述创建的语言文件,并配置VueI18n:

import i18n from '@/lang/index' // 引入国际化配置

//这行代码是 Vue 2 的标准写法,不要使用 Vue 3 的 createApp 语法。
// Vue.prototype.$store = store
// Vue.config.productionTip = false


// 创建 Vue 实例,并注入 i18n
const app = new Vue({
	i18n, // 注入国际化
	store,
	render: h => h(App)
})

在lang下创建 en.js  zh.js  index.js 分别写入下面代码

index.js

import Vue from 'vue';
import VueI18n from 'vue-i18n';
import zh from './zh';
import en from './en';
// 需要什么语言都要导入

// 使用 Vue 2 的 VueI18n
Vue.use(VueI18n);

const i18n = new VueI18n({
  locale: localStorage.getItem('language') || 'zh', // 默认语言为中文
  messages: {
    zh,
    en,

  },
});

export default i18n;

英文包:en.js

//en.js
export default {
  language:{
   // 这里面放 所有的英文替换词
  }
}

中文包:zh.js

//en.js
export default {
  language:{
   // 这里面放 所有的中文替换词
  }
}

三 以登录界面为例

3.1 首先找好图标,对界面加个图标做个触发

		// 切换语言 逻辑处理
			switchLanguage() {
				const newLanguage = this.$i18n.locale === 'zh' ? 'en' : 'zh';
				this.$i18n.locale = newLanguage;
				localStorage.setItem('language', newLanguage);
				this.languageIcon = newLanguage === 'en' ? '/static/china.png' : '/static/en.png';
			},

3.2 对页面需要国际化的每个组件都可以使用 $t 方法来获取国际化文本。

在 zh.js 和 en.js 文件中添加对应的语言内容

// en.js 登录内容如下

export default {
	language: {
		//login 登录界面
		welcome: "Smart Education Platform",
		phonePlaceholder: "Please enter your phone number",
		codePlaceholder: "Please enter the verification code",
		getCode: "Get Code",
		login: "Login",
		cancelLogin: "Cancel Login",
		loginSuccess: "Login Successful",
		phoneError: "Invalid phone number format!",
		phoneEmpty: "Phone number cannot be empty!",
		codeError: "Invalid verification code format!",
		codeEmpty: "Verification code cannot be empty!",
		codeSent: "Verification code sent",
		loginFailed: "Login failed, please try again",
  }
}
// zh.js 登录界面元素需国际化的内容如下
export default {
	language: {
		// login 登录界面
		welcome: "智教平台",
		phonePlaceholder: "请输入手机号",
		codePlaceholder: "请输入验证码",
		getCode: "获取验证码",
		login: "登 录",
		cancelLogin: "取消登录",
		loginSuccess: "登录成功",
		phoneError: "手机号格式不正确!",
		phoneEmpty: "手机号不能为空!",
		codeError: "验证码格式不正确!",
		codeEmpty: "验证码不能为空!",
		codeSent: "验证码已发送",
		loginFailed: "登录失败,请重试",
     }
}

其他页面同理.只需要都写在对应的语言包文件下进行说明即可

同理也可以添加其它语言,做好语言选择的切换

界面完整代码:

<template>
	<view class="tp-login-box tp-flex tp-flex-col tp-box-sizing">

		<!-- 语言切换按钮 -->
		<view class="language-switch">
			<image :src="languageIcon" @tap="switchLanguage" class="language-icon" />
		</view>

		<view class="tp-pd-t-b-30"></view>

		<view class="tp-flex tp-login-welcome tp-flex-col tp-mg-t-b-50">
			<view class="fishTitle">{{ $t('language.welcome') }}</view>
			<!-- 添加的Logo -->
			<view class="tp-mg-t-b-20">
				<image src="/static/image/Logo.png" alt="logo" class="logo" />
			</view>
		</view>

		<!-- 手机号输入框 -->
		<view
			class="tp-ipt tp-box-sizing tp-mg-t-b-20 tp-pd-t-b-15 tp-pd-l-r-30 tp-flex tp-flex-row tp-flex-j-l tp-flex-a-c"
			:class="{'shake': phoneError}">
			<view class="inputicon">
				<image src="/static/shoujihao.png" alt="">
			</view>
			<input type="text" placeholder-class="tp-plc" :placeholder="$t('language.phonePlaceholder')"
				v-model="phoneNumber" @blur="validatePhoneNumber" />
		</view>
		<view v-if="phoneError" class="error-msg">{{ phoneErrorMsg }}</view>

		<!-- 验证码输入框 -->
		<view
			class="tp-ipt tp-box-sizing tp-mg-t-b-20 tp-pd-t-b-15 tp-pd-l-r-30 tp-flex tp-flex-row tp-flex-j-l tp-flex-a-c"
			:class="{'shake': codeError}">
			<view class="inputicon">
				<image src="/static/yanzhengma-.png" alt="">
			</view>
			<input type="text" placeholder-class="tp-plc" :placeholder="$t('language.codePlaceholder')"
				v-model="verificationCode" @blur="validateVerificationCode" />
			<view class="inputcode" @tap="requestVerificationCode">
				{{ $t('language.getCode') }}
			</view>
		</view>
		<view v-if="codeError" class="error-msg">{{ codeErrorMsg }}</view>

		<!-- 登录按钮 -->
		<view class="btn">
			<button class="tp-btn tp-mg-t-50" :loading="loading"
				@tap="doLoginSubmit">{{ $t('language.login') }}</button>
		</view>
		<view class="tp-getpwd tp-mg-t-40 tp-flex tp-flex-row tp-flex-j-c tp-flex-a-c" @tap="doLoginCancel">
			{{ $t('language.cancelLogin') }}
		</view>

		<!-- 授权登录 -->
		<uni-popup ref="authPopup" type="bottom">
			<authorize @getuserinfo="getAuth" @cancel="toCloseLogin"></authorize>
		</uni-popup>

		<!-- 登录成功提示框 -->
		<uni-popup ref="successPopup" type="center" :mask="true" :maskClick="false">
			<view class="popup-content">{{ $t('language.loginSuccess') }}</view>
		</uni-popup>
	</view>
</template>


<script>
	export default {
		data() {
			return {
				loading: false, // 按钮的加载状态
				phoneNumber: '', // 存储用户的手机号
				verificationCode: '', // 存储验证码
				phoneError: false, // 手机号输入框错误标记
				phoneErrorMsg: '', // 手机号错误信息
				codeError: false, // 验证码输入框错误标记
				codeErrorMsg: '', // 验证码错误信息
				languageIcon: localStorage.getItem('language') === 'en' ? '/static/china.png' : '/static/en.png' // 语言切换图标
			}
		},
		methods: {
			// 切换语言
			switchLanguage() {
				const newLanguage = this.$i18n.locale === 'zh' ? 'en' : 'zh';
				this.$i18n.locale = newLanguage;
				localStorage.setItem('language', newLanguage);
				this.languageIcon = newLanguage === 'en' ? '/static/china.png' : '/static/en.png';
			},
			// 验证手机号输入框
			validatePhoneNumber() {
				const phoneRegex = /^1[3-9]\d{9}$/;
				if (!this.phoneNumber) {
					this.phoneError = true;
					this.phoneErrorMsg = this.$t('language.phoneEmpty');
					return false;
				} else if (!phoneRegex.test(this.phoneNumber)) {
					this.phoneError = true;
					this.phoneErrorMsg = this.$t('language.phoneError');
					return false;
				}
				this.phoneError = false;
				this.phoneErrorMsg = '';
				return true;
			},
			// 验证验证码输入框
			validateVerificationCode() {
				const codeRegex = /^\d{4}$/; // 假设验证码为4位数字
				if (!this.verificationCode) {
					this.codeError = true;
					this.codeErrorMsg = this.$t('language.codeEmpty');
					return false;
				} else if (!codeRegex.test(this.verificationCode)) {
					this.codeError = true;
					this.codeErrorMsg = this.$t('language.codeError');
					return false;
				}
				this.codeError = false;
				this.codeErrorMsg = '';
				return true;
			},
			// 请求验证码的API
			requestVerificationCode() {
				if (!this.validatePhoneNumber()) return;

				// 调用发送验证码的API
				uni.request({
					url: 'http://192.168.0.180:8090/v1/api/system/send_captcha', // 发送验证码的API地址
					method: 'POST',
					data: {
						phone: this.phoneNumber // 传递手机号
					},
					success: (res) => {
						console.log(res.data);
						if (res.data.code == 2000) {
							this.codeErrorMsg = this.$t('language.codeSent');
							this.codeError = true;
						} else {
							this.codeErrorMsg = res.data.message || this.$t('language.loginFailed');
							this.codeError = true;
						}
					},
					fail: (err) => {
						this.codeErrorMsg = this.$t('language.loginFailed');
						this.codeError = true;
					}
				});
			},
			// 处理登录过程
			doLoginSubmit() {
				if (!this.validatePhoneNumber() || !this.validateVerificationCode())
					return;

				this.loading = true;

				// 调用登录的API
				uni.request({
					url: 'http://192.168.0.180:8090/v1/api/system/login', // 登录的API地址
					method: 'POST',
					header: {
						'Content-Type': 'application/json'
					},

					data: {
						phone: this.phoneNumber, // 传递手机号
						code: this.verificationCode // 传递验证码
					},
					success: (res) => {
						console.log(res.data);
						if (res.data.code == 2000) {
							uni.setStorageSync('access_token', res.data.data.token); // 存储访问令牌
							this.$refs.successPopup.open(); // 显示登录成功提示框
							setTimeout(() => {
								uni.switchTab({
									url: '/pages/deviceManage/deviceManage' // 登录成功后跳转到首页
								});
							}, 1000);
						} else {
							this.phoneErrorMsg = res.data.message || this.$t('language.loginFailed');
							this.phoneError = true;
						}
					},
					fail: (err) => {
						this.phoneErrorMsg = this.$t('language.loginFailed');
						this.phoneError = true;
					},
					complete: () => {
						this.loading = false;
					}
				});
			},
			// 取消登录并返回上一页
			doLoginCancel() {
				uni.navigateBack(-1);
			},
		}
	}
</script>


<style>
	@import url("@/common/login.css");

	.language-switch {
		position: absolute;
		top: 20px;
		right: 20px;
		z-index: 100;
	}

	.language-icon {
		width: 30px;
		height: 30px;
	}


	/* 抖动动画 */
	@keyframes shake {

		0%,
		100% {
			transform: translateX(0);
		}

		20%,
		60% {
			transform: translateX(-10px);
		}

		40%,
		80% {
			transform: translateX(10px);
		}
	}

	.shake {
		animation: shake 0.5s ease;
	}

	.error-msg {
		color: red;
		font-size: 12px;
		text-align: center;
		margin-top: -10px;
		margin-bottom: 10px;
	}

	.popup-content {
		font-size: 18px;
		color: #000;
		padding: 20px;
		text-align: center;
	}
</style>

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

YoloV8损失函数篇(代码加理论)

首先yolov8中loss的权重可以在ultralytics/cfg/default.yaml修改 损失函数定义ultralytics/utils/loss.py 回归分支的损失函数 DFL(Distribution Focal Loss)&#xff0c;计算anchor point的中心点到左上角和右下角的偏移量IoU Loss&#xff0c;定位损失&#xff0c;采用CIoU…

开源网络安全大模型 - SecGPT

网络安全大模型是指使用大量数据和参数来训练的人工智能模型&#xff0c;它可以理解和生成与网络安全相关的内容&#xff0c;例如漏洞报告、利用代码、攻击场景等。 目前各家网络安全厂商也纷纷跟进在大模型方面的探索&#xff0c;但可供广大从业者研究的特有网络安全大模型…

2013-2023年 中国MOD17A3H植被净初级生产力(NPP)数据

中国MOD17A3H植被净初级生产力&#xff08;NPP&#xff09;数据是基于NASA的MODIS卫星遥感数据计算得出的&#xff0c;这些数据对于评估生态系统碳收支、碳循环以及气候变化的影响具有重要意义。NPP数据可以反映植被通过光合作用固定大气中二氧化碳并转化为有机物质的能力&…

OpenStack组件介绍(2)

cinder 提供块存储服务&#xff0c;管理openstack中的块存储资源&#xff0c;为云平台提供持久的块存储服务&#xff0c;通过驱动的方式可以接入不同种类的后端存储。 cinder对接nfs 关闭防火墙和selinux [rootlocalhost yum.repos.d]# systemctl stop firewalld [rootlocal…

对想学习人工智能或者大模型技术从业者的建议

“ 技术的价值在于应用&#xff0c;理论与实践相结合才能事半功倍” 写这个关于AI技术的公众号也有差不多五个月的时间了&#xff0c;最近一段时间基本上都在保持日更状态&#xff0c;而且写的大部分都是关于大模型技术理论和技术方面的东西。‍‍‍‍‍‍‍‍‍ 然后最近一段…

网络安全售前入门04——审计类产品了解

目录 1.前言 2.数据库审计介绍 2.1产品架构功能 2.2应用场景 2.3部署形式 2.4产品价值 2.5选型依据 1.前言 为方便初接触网络安全售前工作的小伙伴了解网安行业情况,我制作一系统售前入门(安全产品,安全服务,法律法规等)文章介绍,希望能给初进网安职场的小伙伴提供…

STL中的stack与queue

前言&#xff1a; stack与queue是STL中的容器适配器&#xff0c;而不是容器。何为适配器&#xff1f;给手机充电的充电器就是一种适配器&#xff0c;将高电压变成低电压。适配器是用来做转化的&#xff0c;不用来直接管理数据&#xff0c;而是在其他容器的基础上去封装转换。 …

WordNet介绍——一个英语词汇数据库

传统语义知识库最常见的更新方法是依赖人工手动更新&#xff0c;使用这种更新方法的语义知识库包括最早的 WordNet、FrameNet和 ILD&#xff0c;以及包含丰富内容的 ConceptNet和 DBPedia。此类语义知识库的特点是以单词作为语义知识库的基本构成元素&#xff0c;以及使用预先设…

C++ | Leetcode C++题解之第376题摆动序列

题目&#xff1a; 题解&#xff1a; class Solution { public:int wiggleMaxLength(vector<int>& nums) {int n nums.size();if (n < 2) {return n;}int prevdiff nums[1] - nums[0];int ret prevdiff ! 0 ? 2 : 1;for (int i 2; i < n; i) {int diff n…

记一次NULL与空字符串导致的分组后产生重复数据

目录 一&#xff0c;场景说明二&#xff0c;实现功能三&#xff0c;修改原实现方法四&#xff0c;说明 一&#xff0c;场景说明 想实现这样一个功能&#xff0c;统计人员信息中不同性别的人的总工资。 实现方式&#xff1a;将数据group by 分组后累加。 二&#xff0c;实现功…

叉车(工业车辆)安全管理系统,云端监管人车信息运营情况方案

近年来&#xff0c;国家和各地政府相继出台了多项政策法规&#xff0c;从政策层面推行叉车智慧监管&#xff0c;加大叉车安全监管力度。同时鼓励各地结合实际&#xff0c;积极探索智慧叉车建设&#xff0c;实现作业人员资格认证、车辆状态认证、安全操作提醒、行驶轨迹监控等&a…

探秘Facebook的人工智能战略:如何用智能技术重塑社交网络

人工智能&#xff08;AI&#xff09;正以前所未有的速度渗透到各个领域&#xff0c;社交网络也不例外。作为全球最大的社交平台之一&#xff0c;Facebook&#xff08;现Meta&#xff09;正利用人工智能技术重塑其网络环境&#xff0c;提升用户体验。本文将深入探讨Facebook的人…

对SpringBoot项目Jar包进行加密防止反编译

最近项目要求部署到其他公司的服务器上,但是又不想将源码泄露出去,要求对正式环境的启动包进行安全性处理,防止客户直接通过反编译工具将代码反编译出来,本文介绍了如何对SpringBoot项目Jar包进行加密防止反编译,需要的朋友可以参考下 场景: 最近项目要求部署到其他公司的服…

华为HCIP-datacom 真题 (2024年下半年最新题库)

备考HCIP-datacom的小伙伴注意啦 2024年下半年8月份最新题库带解析,有需要的小伙伴移动至文章末 1.BGP 邻居建立过程的状态存在以下几种&#xff1a;那么建立一个成功的连接所经历的状态机顺序是 A、3-1-2-5-4 B、1-3-5-2-4 C、3-5-1-2-4 D、3-1-5-2-4 答案&#xff1a;D 解析…

界面控件DevExpress VCL v24.2路线图预览——增强云集成、简化应用程序皮肤等

DevExpress VCL Controls是Devexpress公司旗下老牌的用户界面套包&#xff0c;所包含的控件有&#xff1a;数据录入、图表、数据分析、导航、布局等。该控件能帮助您创建优异的用户体验&#xff0c;提供高影响力的业务解决方案&#xff0c;并利用您现有的VCL技能为未来构建下一…

el-pagination 下拉条目数最后一个样式改成全部

2024.08.27今天我学习了如何把el-pagination的下拉条目数修改&#xff0c;效果如下&#xff1a; 我们需要把最后一条选择换成全部展示&#xff0c;其实传给后端的还是总的数量&#xff0c;只是换了一个content&#xff0c; 通过f12查看元素可以拿到.el-select-dropdown__item …

华为鸿蒙NEXT大揭秘:微信版功能曝光,简洁界面回归

在科技界&#xff0c;每一次操作系统的更新迭代都是一场期待与猜测的盛宴。华为的鸿蒙系统自问世以来&#xff0c;就以其独特的设计理念和强大的功能吸引了全球的目光。而今&#xff0c;随着微信版鸿蒙NEXT的曝光&#xff0c;我们似乎又将迎来一次科技的飞跃。但这一次&#xf…

【多系统萎缩患者必看!】营养补给站,守护健康每一刻✨

Hey小伙伴们~ 今天我们来聊聊一个需要特别关爱的话题——多系统萎缩&#xff08;MSA&#xff09;患者的营养补充秘籍&#xff01;&#x1f31f; MSA是一种复杂的神经系统疾病&#xff0c;它影响我们的多个身体系统&#xff0c;让每一天的生活都充满了挑战。但别担心&#xff0c…

【工具】轻松解锁SQLite数据库,一窥微信聊天记录小秘密

前言 &#x1f34a;缘由 SQLite里藏秘密&#xff0c;微信聊天有痕迹 &#x1f423;闪亮主角 大家好&#xff0c;我是JavaDog程序狗 今天跟大家分享一个开源小工具PyWxDump&#xff0c;是一个用于获取 wx 账户信息&#xff08;昵称/账户/电话/电子邮件/数据库密钥&#xff0…

利用autoDecoder工具在数据包加密+签名验证站点流畅测试

站点是个靶场 https://github.com/0ctDay/encrypt-decrypt-vuls 演示地址http://39.98.108.20:8085/ 不是仅登录位置暴力破解的那种场景&#xff0c;使用autoDecoder&#xff08;https://github.com/f0ng/autoDecoder&#xff09;的好处就是每个请求自动加解密&#xff0c;测…