前端不使用 i18n,如何优雅的实现多语言?

news2025/1/24 8:29:27

前言:

        关于ERP管理系统的多语言,或者其他应用的多语言一直是我们比较麻烦的问题,大部分是使用 i18n 在代码里进行配置,如果想要修改语言就要自己去改代码!

        今天我们分享一下如何不使用 i18n 去实现多语言,用到以下的技术栈

                ERP管理系统:Vue + 若依 + Element-ui

                微信小程序 :uniapp + uView

一、业务需求

1. 确定业务

最近要实现多语言的 ERP,以及对应的H5、小程序;但是因为语言可能不确定,需求是客户自己去添加、修改自己想要的语言,所以就需要在 ERP 上实现 一个叫 language(可以定义语言) 的功能,可以去给客户提供一个可以添加默认语言、添加新的语言、修改、删除当前语言的平台,如果当前语言没有加过翻译则用 [ key ] 这种方式去提醒客户,该 key 未加多语言!然后我们的ERP、H5、小程序就可以使用当前的全局多语言...

2.  实现思路

思路其实比较简单,但是复杂的需求往往离不开后端大佬支持!下面我们一起来捋一捋我们的实现思路(假设我们现在的需求是三个地区的语言:简体中文、繁体中文、英文)!

① 既然我们再 ERP 上需要有一个 language 的功能供客户去操作语言,考虑到客户还可能设置默认语言,添加多种不同地区的语言,所以我们的 UI 可以像下图设计的那样;

 ② 新增完地区语言以后我们该如何让去修改、新增的不同地区的语言呢?我们这个时候就需要 一个子页面,负责新增当前 key 的多语言,查询当前 key 的多语言去做修改,看完下图你就会明白啦!!! 

 ③经过以上两个步骤我们已经成功的让客户实现了想要的效果,但是我们要怎么把后端大哥保存好的东西拿过来用呢

1. 保存时的数据结构:

{
 key: "Status"
 texts:[
   {
     "languageName": "en-GB",
     "text": "Status"
   },
   {
     "languageName": "zh-CN",
     "text": "状态"
   },
   {
     "languageName": "zh-HK",
     "text": "狀態"
   }
 ]
}

关于ERP 查询时的数据结构这里就不一一列举了,和上面类似!

2. ERP | H5 | 微信小程序 用时查询的数据结构:

// ERP | H5 | 微信小程序 用时的查询
// language_texts 是我们再 SQL Table 中存储的所有多语言集合

language_texts : {
    key : 当前语言的value, // 如何知道当前语言,我们稍后再说
    key : value,
    key : value,
    ... : ...
    ... : ...
}

3. 前端如何使用已经保存好的数据结构呢?

    其实有了上面查询我们就可以用到 language_texts[ key ] 的方式去取出来我们想要的语言数据;使用的话也比较简单,js html 中的不同使用方法下面给大家一 一讲解 ;

    值得我们思考的问题是 我们该何时把 当前语言集全部查询出来?

我这里采用的方案是在 new Vue 之前去调用我们当前的 VFrame方法,这样我们可以确保 我们的多语言所有的 [ key ] [ value ] 可以成功加载,具体步骤请看下方!

二、实现步骤

   1. 新建 VFrame.js 文件 

         我这里的 VFrame.js 是直接建在Src 目录下的

import axiso from 'axios'
import { getAll } from '@/api/uxretail/application.js'
const format = require('string-format')


export default class VFrame {

    static host;
    static wsUrl;

    /**
     * 在vue实例化之前调用异步start方法
     */
    static start() {
        return new Promise((resolve, reject) => {
            axiso.request({
                url: "/static/appconfig.json",
                method: "get",
            }).then(result => {
                VFrame.host = (result.host || window.location.host);
                VFrame.wsUrl = "ws://" + VFrame.host + ":" + result.wsPort + "/ws/notify/";
                VFrame.getAll(resolve);
            }).catch(error => {
                reject(error);
            });
        });
    }

    static getAll(resolve) {
        getAll().then(res => {
            VFrame.applicationResource = res
            resolve()
        });
    }


    static l(key, ...args) {
        if (localStorage.getItem("ux_debug_language")) {
            return `[${key}]`
        }

        if (!VFrame.applicationResource) {
            return key
        }
        if (VFrame.applicationResource.language_texts) {
            let res = VFrame.applicationResource.language_texts[key];
            if (res) {
                return format(res, args);
            } else {
                return `[${key}]`
            }
        }
        return key;
    }
}

2. main.js 中 使用我们新建的 VFrame.js

上面我们说到 VFrame 的执行时机,我们可以看下面代码! 

import Vue from "vue";
import App from "./App";
import store from "./store";
import router from "./router";
import VFrame from "./framework/VFrame";


Vue.prototype.l = VFrame.l;


// 这个为了方便用 VFrame ,并没有其他用途
Vue.prototype.$ux = {
  v: VFrame
}


// 重要的就是这一步,VFrame 的执行时机
VFrame.start().then(() => {
  //set layout to store
  store.commit("dragLayout/initLayout")
  new Vue({
    el: "#app",
    router,
    store,
    render: h => h(App)
  });
});

3. html js 中使用我们配置好的多语言 

    Html 中使用: 【 l("Key") 】

<div> {{ l('ManyLanguage') }} </div>

<el-form :model="item" :rules="tableRules">
    <el-form-item :label="l("ManyLanguage")" prop="language">
        <el-input v-model="item.language"></el-input>
    </el-form-item>

</el-form>

    js 中使用: 【 this.l("Key") 】

export default{

  data(){
    return {
        language:this.l("ManyLanguage")
    }
  },

  created(){
  
    console.log(this.l("MyLanguage"))
  },
}

经过上面一番操作我们已经可以在管理系统中成功的调用当前多语言了;

那么我们 VFrame 中的 getAll() API 调用时 如何返回我们刚好我们想要的语言呢?

  我们就要处理 【 request.js 】中的封装,在请求拦截中去携带我们自定义的请求头信息,后端大佬去对应的处理即可!

import Cookies from "js-cookie";
import axios from "axios";


axios.defaults.headers["Content-Type"] = "application/json;charset=utf-8";
// 创建axios实例
const service = axios.create({
  // axios中请求配置有baseURL选项,表示请求URL公共部分
  baseURL: process.env.VUE_APP_BASE_API,
  // 超时
  timeout: 120000
});


service.interceptors.request.use(
  config => {

    var cultureName = Cookies.get(CONSTANT.UX_LANGUAGE);
    if (cultureName) {
      config.headers[CONSTANT.UX_LANGUAGE] = cultureName; // 让每个请求携带自定义token 请根据实际情况自行修改
    }

})

三、微信小程序中使用 

      实现步骤就像上面写的步骤一样,那么注意点是什么呢( 本文用的是uniapp去开发的微信小程序,也是基于 vue 的语法 )?

        在 uniapp 里面我们不能写的像我们上面那样,因为 uniapp 是不支持的,那么这个时候我们如何去确保页面加载完成时,多语言可以全部返回呢?

        答:做一个预加载页,当我们多语言成功返回以后跳转至业务页面

 1. 完成上方基础 VFrame 创建,main.js 中挂载,但是不要在用 new vue 勿动(不然会报错)!

       因为小程序有 Tabbar 所以我们的  VFrame.js 需要多一个方法; 

import {
	request
} from "util/request.js";
export default class VFrame {
	static applicationResource;

	/**
	 * 在vue实例化之前调用异步start方法
	 */
	static start() {
		return new Promise((resolve, reject) => {
			request({
				url: '/application/getAppAll', //activityType=0 查询全部
				method: 'GET',
				hideLoading: true,
				data: {
					orgId: uni.getStorageSync('companyOrgId')
				}
			}).then(res => {
				VFrame.applicationResource = res.data.result
				resolve(res)
			});
		});
	}

	static l(key, args) {
		if (VFrame.applicationResource && VFrame.applicationResource.language_texts) {
			let res = VFrame.applicationResource.language_texts[key];
			if (res) {
				return res;
			} else {
				return `[${key}]`
			}
		}
		return key;
	}

	static tabbarLanguage(tabbarList) {
		let language = uni.getStorageSync('language') || 'zh-CN'
		if (language) {
			switch (language) {
				case 'en-GB':
					tabbarList[0].text = "Coupons"
					tabbarList[1].text = "Stamp"
					tabbarList[2].text = "Account"
					tabbarList[3].text = "Discount"
					tabbarList[4].text = "Favourite"
					break
				case 'zh-CN':
					tabbarList[0].text = "电子优惠券"
					tabbarList[1].text = "电子印花"
					tabbarList[2].text = "我的账户"
					tabbarList[3].text = "优惠奖赏"
					tabbarList[4].text = "我的最爱"
					break
				case 'zh-HK':
					tabbarList[0].text = "電子優惠券"
					tabbarList[1].text = "電子印花"
					tabbarList[2].text = "我的賬戶"
					tabbarList[3].text = "優惠獎賞"
					tabbarList[4].text = "我的最愛"
					break
			}
		}
		return tabbarList
	}

}

2. 预加载页面的制作 

  新建 preload.vue 

<template>
	<view class="preload">fashion-cue</view>
</template>

<script>
import { mapMutations } from 'vuex';
import VFrame from '@/util/VFrame';
export default {
	name: 'Preload', // 预加载动画页面
	data() {
		return {};
	},
	methods: {
		...mapMutations(['setAppAll'])
	},
	onLoad(e) {
		console.log('onLoad', e);
		VFrame.start().then(res => {
			if (res && res.data.result.brandList && res.data.result.categoryList) {
				this.setAppAll(res.data.result);
			}
			getApp().globalData.isLoaded = true;
			uni.switchTab({
				url: e.redirect ? '/' + e.redirect : '/platforms/mp-weixin/discount/discount'
			});
		});
	}
};
</script>

<style>
.preload {
	width: 100%;
	font-weight: bold;
	font-family: 'Arial', 'Microsoft YaHei', '黑体', '宋体', sans-serif;
	font-size: 2.5rem;
	text-align: center;
	background-image: -webkit-linear-gradient(left, black, transparent 25%, black 50%, transparent 75%, black);
	-webkit-text-fill-color: transparent;
	-webkit-background-clip: text;
	-webkit-background-size: 200% 100%;
	-webkit-animation: masked-animation 2s infinite linear;
	position: absolute;
	top: 50%;
	left: 50%;
	transform: translate(-50%, -140%);
}
@-webkit-keyframes masked-animation {
	0% {
		background-position: 0 0;
	}
	100% {
		background-position: -100% 0;
	}
}
</style>

3. 切换语言

    切换语言是再次调用我们的 VFrame.js 中的 start() 方法即可;

    但是小程序切换要注意几个点:

        ① 自定义请求头的特殊处理

        ② 切换完成以后需要刷新当前页面

        ③ Tabbar 页面需要再 onShow 时处理


结语:

        其实实现步骤略微有些繁琐,但是并不难,主要还是后端大佬的配合!

好了,本文到此结束,有需要的朋友可以私信~~~~~~~~ 

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

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

相关文章

web前端面试高频考点——Vue的基本使用(一文掌握Vue最基础的知识点)

系列文章目录 内容参考链接Vue基本使用Vue的基本使用&#xff08;一文掌握Vue最基础的知识点&#xff09;Vue通信和高级特性Vue组件间的通信及高级特性&#xff08;多种组件间的通信、自定义v-model、nextTick、插槽&#xff09;Vue高级特性Vue的高级特性&#xff08;动态组件…

ES6遍历方法,forEach、for...in,for..of

前言 js中遍历方法很多&#xff0c;在ES6新特性中出现了很多新的遍历方法&#xff0c;使遍历数组和对象更加方便&#xff0c;下面开始列举各种方法。 1.遍历对象 1.1.for…in…循环遍历对象自身和继承的可枚举的属性&#xff08;不包括Symbol&#xff0c;因为symbol的实例是…

微信小程序开发入门与实战(数据、事件、条件)

作者 : SYFStrive 博客首页 : HomePage &#x1f4dc;&#xff1a; 微信小程序 &#x1f4cc;&#xff1a;个人社区&#xff08;欢迎大佬们加入&#xff09; &#x1f449;&#xff1a;社区链接&#x1f517; &#x1f4cc;&#xff1a;觉得文章不错可以点点关注 &#x1f4…

layui 的数据表单的defaultToolbar参数中筛选列,图标,打印,三个功能,调用单独拿出使用

项目场景&#xff1a; 参数之defaultToolbar&#xff1a; 在使用layui开发的过程中&#xff0c;常常会用到 数据表单 这一关键模块&#xff0c;在这里讲一下defaultToolbar:[filter,exports print]-------“头部工具栏右侧图标”&#xff0c;如何将这三个按钮调用出来&#x…

【vscode】vscode常用插件介绍

1、Angular Snippets&#xff08;angular片段&#xff09; 这个扩展为 TypeScript 和 HTML 添加了 Angular 的代码片段。 2、Auto Close Tag&#xff08;自动闭合标签&#xff09; 自动添加 HTML/XML 关闭标记。 3、Auto Rename Tag&#xff08;自动重命名标签&#xff09; 自…

Three.js基础入门系列(九)--导入3D模型

先来学习今天的知识——Three.js导入3D模型 复杂的3D模型&#xff08;比如制作一个飞机模型&#xff09;一般都是用第三方建模工具生成&#xff0c;然后加载到Three.js中。 01 常用建模制作工具 3Dmax 链接地址&#xff1a;https://www.autodesk.com.cn/products/3ds-max/over…

启动vue-element-admin 安装npm install报错npm ERR! code 128npm ERR! An unknown git error occurre

使用vue-element-admin前端项目&#xff0c;前提是有nodejs环境&#xff0c;对于此环境的安装可以参考网上的博客。此博客用于记录启动项目以及遇到的问题、并解决问题的过程。1、介绍vue-element-admin是基于element-ui 的一套后台管理系统集成方案 。功能&#xff1a;https:/…

Vue基础教程(下篇)

&#x1f60a;作者简介&#xff1a;大家好&#xff0c;我是是你的大头呢&#xff0c;一名大三学生&#xff0c;考研备考中。让我们一起加油&#xff0c;一起努力&#xff01; &#x1f9d1;‍&#x1f4bb;博客主页&#xff1a;是你的大头呢 &#x1f970;欢迎关注&#x1f38a…

javascript 中搜索数组的四种方法

前端经常要通过 javaScript 来处理数组中的数据&#xff0c;其中就包括检查数组中是否包含满足特定搜索条件的单个或者多个值&#xff0c;这就需要我们关于用于确认的布尔值、数组中值得位置索引或包含所有搜索结果的单独数组等。 在 ECMAScript6 之前&#xff0c;最常用的方法…

Vue中 this.$set的用法

一、this.$set能够实现什么功能 官方解释&#xff1a;向响应式对象中添加一个属性&#xff0c;并确保这个新属性同样是响应式的&#xff0c;且触发视图更新。它必须用于向响应式对象上添加新属性&#xff0c;因为 Vue无法探测普通的新增属性 (比如 this.myObject.newProperty …

pdf在线预览 pdf.js的使用

1.官网&#xff1a;https://mozilla.github.io/pdf.js/ 2、使用方法 1&#xff09; 通过官网&#xff0c;下载pdfJs插件包&#xff0c;放至项目中&#xff1b; window.open("./js/pdfJS/web/viewer.html?fileAngularJS权威指南.pdf" );2&#xff09;将下载的pdfJS…

uniapp封装axios?大可不必那么麻烦。

最近群里的一个小明同学问 uniapp可以使用axios请求吗&#xff1f;我当时就一愣 反问为什么要使用axios&#xff0c;是 uni.request 不香了吗&#xff1f; 小明&#xff1a;因为axios可以像vue的项目一样&#xff0c;在request里面封装巴拉巴拉一堆。 我&#xff1a;那uni.re…

微信小程序开发使用onreachBottom实现页面触底加载及分页

目录 一 简要介绍一下onreachBottom事件 二 实例展示 三 遇到的一些问题 一 简要介绍一下onreachBottom事件 onreachBottom和onLoad以及onShow一样&#xff0c;都属于小程序的生命周期事件&#xff0c;作用就是在页面下拉到底部时触发这个事件&#xff0c;一般适用于数据比较…

一次跨域的坑Faild to load response data: No resourse with given identifier found

有一个导出接口&#xff0c;前后端都没有动过&#xff0c;之前也测试过没有问题。上到测试环境后&#xff0c;测试环境加了证书&#xff0c;报错了。 先是后端小朋友和我说了这个问题&#xff1a; 浏览器控制台打印信息(聊天记录中那张图)&#xff1a;然后我问他操作了哪个页面…

vue3.0教程——搭建Vue脚手架【简化版】

目录 哈喽&#xff0c;大家好丫&#xff0c;你们的小郭子又来啦 ~ 一、环境要求 &#xff08;1&#xff09;node安装&#xff08;前端开发环境&#xff09; &#xff08;2&#xff09;vue-cli脚手架安装 二、安装依赖 &#xff08;1&#xff09;使用命令行安装以下依赖 &a…

Vue 之 vue-seamless-scroll 实现简单自动无缝滚动,且添加对应点击事件的简单整理

Vue 之 vue-seamless-scroll 实现简单自动无缝滚动&#xff0c;且添加对应点击事件的简单整理 目录 Vue 之 vue-seamless-scroll 实现简单自动无缝滚动&#xff0c;且添加对应点击事件的简单整理 一、简单介绍 二、安装和使用 三、效果图 四、vue-seamless-scroll 点击事件…

(网页开发/前端)配置VsCode,让您拥有更舒适的开发环境

vscode&#xff0c;微软旗下的一款强大的IDE集成开发环境&#xff0c;现在&#xff0c;越来越多的网页开发人员选择使用vscode来敲代码。 但是&#xff0c;在不添加任何扩展的vscode中&#xff0c;想要享受“丝滑”的开发体验是比较困难的。所以&#xff0c;接下来&#xff0c;…

js从地址栏获取参数

一、过程分四步&#xff1a; 1.获取地址栏&#xff1b; var loclocation.href; 2.获取地址栏的长度 var n1loc.length; 3.获取地址栏中第一个等号的位置&#xff1b; var n2loc.indexOf()&#xff1b; 4.以等号位置&#xff0c;截取后面的内容&#xff1b; var strloc.slice(n2…

Object.entries()

Object.entries() 方法返回一个给定对象自身可枚举属性的键值对数组。 其排列与使用 for...in 循环遍历该对象时返回的顺序一致&#xff08;区别在于 for-in 循环还会枚举原型链中的属性&#xff09;。 语法 Object.entries(obj) 参数 obj&#xff1a;可以返回其可枚举属性…

VS2022(Visual Studio)发布ASP.NET Core Web API应用到Web服务器(IIS)

概述 写完代码后&#xff0c;最常用、简单的发布方式&#xff0c;就是将应用发布到文件夹&#xff0c;然后将publish文件夹复制到要部署的机器上&#xff08;本地、局域网服务器、云服务器等&#xff09;。 但是在实际工作中&#xff0c;可能会遇到需要频繁地发布&#xff0c…