Background:

The project I am working on is an overseas e-commerce project, involving more than 20 translation files from different countries. If all the translation files are packed into the deployment package, the rendering of the first screen of the page will be slow.

The project is deployed in multiple regions. In different regions, it only serves the business of several countries. If all the translation files are packaged into the deployment package, some translation files will not be used.

As the translation content often does not meet the requirements of first-line operations, dynamic modification of translation files is needed, that is, modification of translation terms from the configuration console, and then generation of corresponding translation files and release to THE CDN.

Scheme analysis:

Based on the above problems, the translation file cannot be typed into the specific deployment package during package output. The corresponding translation file needs to be asynchronously loaded according to the language information in the cookie during page initialization. During language switching, the corresponding translation file is asynchronously loaded according to the expected language information.

The following three ways are listed, all of which have their own advantages and disadvantages, and can be selected according to their own project situation:

One, synchronous loading version

In main.js, reference the i18N configuration file. When creating a vue instance, register it:

import Vue from 'vue'
import i18n from './language/index'new Vue({  i18n,}).$mount('#app')
Copy the code

In the SRC /language/index.js file, reference vue-i18n plug-in and write all the supported language information and corresponding translation content in i18n.messages

import Vue from 'vue'import VueI18n from 'vue-i18n'

Vue.use(VueI18n)const DEFAULT_LANG = 'en_PH'

const locales = {
    en_PH: require('./cust/en_PH'),
    ja_JP: require('./cust/ja_JP'),
    ...
}
const i18n = new VueI18n({  locale: DEFAULT_LANG,  messages: locales,})
export default i18n
Copy the code

The SRC /language/cust/ en_ph. js file format is as follows, and the translated content is exported as a module

export const msgObj = {  "confirm":"\u0043\u006f\u006e\u0066\u0069\u0072\u006d", // Confirm
  "cancel":"\u0043\u0061\u006e\u0063\u0065\u006c", // Cancel
  ...
}
Copy the code

The SRC /language/cust/ ja_jp. js file format is as follows, and the translated content is exported as a module

Export const msgObj = {"confirm":"\u78ba\ U8a8d ", // confirm" cancel":"\ u30AD \ u30E3 \ u30F3 \ u30BB \ u30EB ", // beauf ャ / default add... }Copy the code

All registered translations and content are packaged into a SRC /dist/js/index.js file.

This parameter is used when the number of translation files is small or the number of translation files is small and the deployed server needs to fully support languages.

Two, asynchronous loading version

Here the official website gives a simple example Vue I18n lazy loading translation

Refer to the example on the official website and modify it as follows:

//index.js import Vue from 'vue' import VueI18n from 'vue-i18n' import axios from 'axios' Vue.use(VueI18n) const DEFAULT_LANG = 'en_PH' const locales = { en_PH: require('./cust/en_PH'), ... } const i18n = new VueI18n({locale: DEFAULT_LANG, // set locale messages: locales, }) const loadedLanguages = [DEFAULT_LANG] // Function setI18nLanguage (lang) {i18n.locale = lang axios.defaults.headers.common['Accept-Language'] = lang document.querySelector('html').setAttribute('lang', lang) return lang } export function loadLanguageAsync (lang) { if (i18n.locale ! == lang) { if (! Loadedlanguages.includes (lang)) {return import(' @/language/cust/${lang} ') Then (MSGS => {// to import the corresponding translation file i18n.setLocaleMessage(lang, MSGS); // Set i18N language message to this loadedlanguages.push (lang); // set i18N language message to this loadedlanguages.push (lang); Return setI18nLanguage(lang)}). Catch (() => {console.log(' async import language ')  failed`) }) } return Promise.resolve(setI18nLanguage(lang)) } return Promise.resolve(lang) } export default i18nCopy the code

You can see that i18N. setLocaleMessage is pairwise configured by (language identifier, corresponding translation file contents), which is equivalent to extending the i18N. messages object

When a project is packaged, the default language information is packaged into an index.js file.

Here we use Webpack’s require loading file to load the translation file asynchronously; During language switch, if dynamic information such as commodity information does not involve multiple languages, you can directly call loadLanguageAsync to load and set the corresponding language information. If the dynamic information involves multiple languages, you need to call the corresponding data interface after calling loadLanguageAsync to refresh the dynamic data.

The preceding methods can be used when translation files need to be loaded asynchronously and translation problems are released through patches.

When you need to implement a hot patch translation problem, use the following methods:
export function loadLanguageAsync (lang) { if (i18n.locale ! == lang) { if (! Loadedlanguages.includes (lang)) {const SDK = document.createElement('script') sdK.type = 'text/javascript' sdk.src = '${window.cdnpath}static/language/${lang}.js' // Request data content sdk.onload = function() { I18n.setlocalemessage (lang, {// extend i18N.messages msgObj: window.msgobj, // msgObj is provided by the corresponding translation file, so the translation file needs to be adjusted here,}); // Set i18n's language message to this loadedlanguages.push (lang); // Add loadedLanguages // set language setI18nLanguage(lang); Resolve (lang)} sdk.onerror = function() {console.log(' get language ')  failed`) return Promise.reject(lang) } document.body.appendChild(sdk) } return Promise.resolve(setI18nLanguage(lang)) }  return Promise.resolve(lang) }Copy the code

The format of resource files such as SRC /language/cust/ en_ph. js is modified as follows, using JS code

window.msgObj = {
  "confirm":"\u0043\u006f\u006e\u0066\u0069\u0072\u006d", // Confirm
  "cancel":"\u0043\u0061\u006e\u0063\u0065\u006c", // Cancel
  ...
}
Copy the code

This is equivalent to extending the i18N. messages object.

As for when to call loadLanguageAsync, it is recommended to do so in route Guard

router.beforeEach((to, from, next) => {
  const lang = to.params.lang
  loadLanguageAsync(lang).then(() => next())
})
Copy the code

The parameters on the destination route need to be loaded and set with language information, which is suitable for page initialization or when the routing information changes. Language information can also be obtained from cookies, eliminating the operation of routing with parameters.

conclusion

When the content of the translation files is small or the translation files are small and the deployed server needs to support all languages, the first method is directly used.

The second method can be used when asynchronous loading of translation files is needed and the translation problem is solved by releasing patch packages.

The third method is used when the translation file needs to be loaded in one step and the translation information of different sites can be dynamically modified in the configuration center.

If there is insufficient welcome to correct, have ideas welcome to discuss together.