preface

In this paper, for the international translation data, coexist in the server, the optimization of the situation, and write a plug-in github.com/jmx16449196… , for your reference or use. If there is anything that needs to be improved, I hope you can correct it.

Demand background

The internationalization function of our single page application has two points that can be optimized:

  • The internationalized translation data is stored in the database. Each time the language is changed or the page is reloaded, the interface needs to be requested once. The interface takes about 1s, which greatly affects the user experience, especially the first screen loading.

  • Since all data is stored in the database, there is no translated data available until the requesting interface when the first screen loads.

Optimization scheme

For the first problem, use caching

For the second question, I divided the translation data into two parts:

Static translation data: write dead in JS, used to exist some basic translation data, even if the network is down, the user can also see the normal page.

Dynamically translated data: obtained from the interface, this part of the data can be modified by the user through the relevant configuration page.

When entering the optimized page, it can be divided into the following stages:

The key code

// Create an instance and call const translateManager = new translateManager ({/* pass parameters */}) translatemanager.update ('en', (res) => {// Trigger the corresponding update view logic // for example, in vue, using vue-i18n, you can i18n.setLocalemessage (res.data); }); class TranslateManager { STORAGE_KEY: string expireTime: number requestFn: Function | null staticTranslateData: /** * constructor * @param params */ constructor() constructorParams) { this.expireTime = params.expireTime || Infinity; / / the front-end cache valid time. STORAGE_KEY = params. StorageKey | |'TranslateManager';
    this.requestFn = params.requestFn;
    this.staticTranslateData = params.staticTranslateData || {};
  }
  setRequestFn(fn: Function) { this.requestFn = fn; } /** * set cache * @param {String} language */setCache(language: string, data: object) {// Cache after request 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(); // The cache is only two hoursif (now - time <= this.expireTime) {
        returnstorageData[language] || null; }}returnnull; } /** * getDynamicTranslateData(language: string) {if(! this.requestFn) { console.error('setRequestFn! ');
      return Promise.reject();
    }
    return this.requestFn({language}).then((res: object) => {
      this.setCache(language, res);
      returnres; }); } @param {*} language */ getMergeTranslateData(language: string) {// Start request without cachereturnthis.getDynamicTranslateData(language).then((res: any) => { const data = this.staticTranslateData[language] || {}; Merge (res, data) merge(res, data)if (isEmptyResult(res)) {
        return Promise.reject(new Error('locale empty !! '))}returnres; Update (string, callback: Function) {/** * callback (string, Function) {/** * callback (string, Function) {letstaticData = this.staticTranslateData[locale]; const cacheData = this.getCache(locale) || {}; // Use the union of static and cached data to trigger the first view update merge(cacheData, staticData); callback(cacheData,'first'); // Returns a collection of static and dynamic datareturnEnclosing getMergeTranslateData (locale). Then ((res: object) = > {/ / get the data and dynamic data inconsistencyif(res && ! isEqual(res, cacheData)) { callback(res,'second')}})}}Copy the code

extension

Using the above approach, has been very good to achieve the desired effect. As I write this article, I suddenly realize that there is a further direction of optimization: dynamic data can be divided into different modules and loaded step by step. Based on the service logic, for example, based on user permissions. When I have low user permission and can only look at the home page, I only load the translation data of the home page module. When I have high user authority and enter the corresponding page, then download the corresponding module data.

conclusion

The optimization idea provided this time is not difficult, but it takes some time to realize, I made a wheel according to the optimization idea, it is very convenient to use, including the use of demo and notes, welcome star: github.com/jmx16449196… . If you found this article helpful, please give it a thumbs up. Thank you

For more front-end technology sharing, please subscribe to wechat public account “Front-end technology Dry Goods Sharing circle”