前言
本文针对国际化翻译数据多,并存放在服务器的情况,对优化进行了思考,并写了了一个插件github.com/jmx16449196…,供大家参考或使用。抛砖引玉,如果有需要改进的地方,希望大家指正。
需求背景
我司单页面应用中的国际化功能存在两个可优化的点:
-
国际化翻译数据存在了数据库中。每次切换语种或重新加载页面,都需要请求一次接口,接口大概会耽误1s,十分影响用户体验,特别是首屏加载。
-
由于所有数据都存放在数据库,所以首屏加载时,请求接口前都没有翻译数据可用。
优化方案
针对第一个问题,使用缓存
针对第二个问题,我把翻译数据分为了两份:
静态翻译数据:写死在js中,用于存在一些基础的翻译数据,即使断网了,用户也可以看到正常的页面。
动态翻译数据:从接口获得,这部分数据可以让用户通过相关配置页面去修改。
优化后的页面在进入时,可以分为以下阶段:
关键代码
// 创建实例并调用
const translateManager = new TranslateManager({/*传参*/})
translateManager.update('en', (res) => {
// 触发相应的更新视图的逻辑
// 例如在vue中,使用了vue-i18n,你可以
i18n.setLocaleMessage(res.data);
});
class TranslateManager {
STORAGE_KEY: string
expireTime: number
requestFn: Function | null
staticTranslateData: object
/** * 构造函数 * @param params */
constructor(params: constructorParams) {
this.expireTime = params.expireTime || Infinity; // 前端缓存有效时间
this.STORAGE_KEY = params.storageKey || 'TranslateManager';
this.requestFn = params.requestFn;
this.staticTranslateData = params.staticTranslateData || {};
}
setRequestFn(fn: Function) {
this.requestFn = fn;
}
/** * 设置缓存 * @param {String} language */
setCache(language: string, data: object) {
// 请求完成后缓存
const storageData = jsonParse(localStorage.getItem(this.STORAGE_KEY)) || {};
storageData[language] = data;
storageData['time'] = new Date().getTime();
localStorage.setItem(this.STORAGE_KEY, JSON.stringify(storageData));
}
/** * 从缓存中读取 * @param language 语种 */
getCache(language: string) {
const storageData = jsonParse(localStorage.getItem(this.STORAGE_KEY)) || {};
if (storageData && storageData['time'] && storageData[language]) {
const time = storageData['time'];
const now = new Date().getTime();
// 缓存只有两小时
if (now - time <= this.expireTime) {
return storageData[language] || null;
}
}
return null;
}
/** * 获取后端的静态国际化数据 */
getDynamicTranslateData(language: string) {
if (!this.requestFn) {
console.error('请先执行setRequestFn!');
return Promise.reject();
}
return this.requestFn({language}).then((res: object) => {
this.setCache(language, res);
return res;
});
}
/** * 获取前后端交集后的国际化数据 * @param {*} language */
getMergeTranslateData(language: string) {
// 没缓存就发起请求
return this.getDynamicTranslateData(language).then((res: any) => {
const data = this.staticTranslateData[language] || {};
// 部分国际化写在了前端,把前端的国际化文件合并到后端返回的数据中
merge(res, data)
if (isEmptyResult(res)) {
return Promise.reject(new Error('locale empty !!'))
}
return res;
})
}
/** * 主方法 * @param locale 语种 * @param callback 回调函数,用于订制自己触发的渲染逻辑 */
update(locale: string, callback: Function) {
let staticData = this.staticTranslateData[locale];
const cacheData = this.getCache(locale) || {};
// 使用静态数据和缓存数据的并集,触发第一次视图更新
merge(cacheData, staticData);
callback(cacheData, 'first');
// 返回静态和动态数据的合集
return this.getMergeTranslateData(locale).then((res: object) => {
// 获取数据是否和动态数据不一致
if (res && !isEqual(res, cacheData)) {
callback(res, 'second')
}
})
}
}
延伸
使用了上面的做法,已经很好的达到了预期效果。就在写这篇文章的时候,突然发现还有继续深入优化的方向:可以把动态数据划分不同的模块,分步加载。根据自身业务的逻辑,比如可以根据用户权限。当我用户权限低只可以看主页时,我只加载主页模块的翻译数据即可;当我用户权限高,并进入了相应页面,此时再去下载对应的模块数据。
总结
本次提供的优化方案思路并不难,只是实现起来需要些时间,我根据本次优化的思路造了个轮子,使用十分方便,内含使用demo和注释,欢迎star:github.com/jmx16449196…。如果觉得本文对你有所帮助,求点赞一下,谢谢~
更多前端技术分享请订阅微信公众号“前端技术干货分享圈”
今天的文章几分钟优化你的国际化分享到此就结束了,感谢您的阅读。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
如需转载请保留出处:https://bianchenghao.cn/21032.html