2019年4月28日 星期日

[Vue] Internationalization with vue-i18n and vue-router


 Vue.js   vue-18n   vue-router  


Introduction­


We will implement i18n with

n   vue-router: For getting current target culture from url, such as http://localhost/en-US/login

n   vue-i18n: Localize the content by local or remote i18n data





Related articles




Environment


Vue CLI 3.5.1 (with TypeScript 3.2.1)
vue-router 3.0.2
vue-i18n 8.9.0


Implement


Router

To create routes which can indicate current culture, such as,

http://localhost/zh-TW/login
http://localhost/en-US/about

The routes patterns are set as following,

router.ts

import Vue from 'vue';
import VueRouter from 'vue-router';

Vue.use(VueRouter);

const routes = [
  {
    name: 'home',
    path: '/',
    redirect: '/zh-tw/login',
  },
  {
    name: 'app',
    path: '/:lang',
    component: Home,
    children: [
      { path: 'login', name: 'login', component: Login },
      { path: 'about', name: 'about', component: About },
    ],
  },
];
export default new VueRouter({
  routes,
  mode: 'history',
});



Global Before Guards

We can use vue-router’s Global Before Guards to get current-culture value from user’s navigation url, and then set the right i18n data to vue-i18n.
Here is the sample code which will implement requesting i18n data,loadLanguageAsync(…), later.

router.beforeEach((to: any, from: any, next: any) => {
  const lang = to.params.lang;
  const key = to.query.key || to.name;

  if (supportedLanguages.indexOf(to.params.lang) >= 0) {
    loadLanguageAsync(lang, key).then((response) => {
      const msg = new LocaleMsg(lang, response.data);
      i18n.setLocaleMessage(msg.lang, msg.messages);
      next();
    });
  } else {
    // HACK: Alert not supporting the language
    next(false); // Fallback to "from"'s url
  }
});



The ajax method for i18n data is as following,

const loadedLanguages: string[] = []; // Default language that is preloaded if any

function loadLanguageAsync(lang: string, key: string): Promise<any> {
  if (loadedLanguages.indexOf(lang) < 0) {
    i18n.locale = lang;
    return getI18n(lang, key);
  } else {
    return Promise.resolve(() => {
      i18n.locale = lang;
    });
  }
}

function getI18n(lang: string, key: string): AxiosPromise<any> {
  const serverUrl: string = process.env.VUE_APP_HOST_BACKEND_URL!;
  const uri = serverUrl.concat(`api/locale/get/${lang}/?key=${key}`);
  return axios.get(uri);
}



i18n

Now we can create an i18n module to setup vue-i18n, and set the i18n option to Vue instance.

i18n.ts

import Vue from 'vue';
import axios from 'axios';
import VueI18n, { LocaleMessages } from 'vue-i18n';
import router from '@/router';

Vue.use(VueI18n);
axios.defaults.withCredentials = false;

const supportedLanguages = ['en-us', 'zh-tw', 'zh-cn'];

const i18n = new VueI18n({
  locale: process.env.VUE_APP_I18N_LOCALE || 'zh-tw',
  fallbackLocale: process.env.VUE_APP_I18N_FALLBACK_LOCALE || 'zh-tw',
});

// You can put the previous codes here…

export {supportedLanguages, i18n};




main.ts

import router from './router';
import { i18n } from '@/modules/i18n';

Vue.config.productionTip

new Vue({
  router,
  i18n,
  render: (h) => h(App),
}).$mount('#app');




Demo





Reference




沒有留言:

張貼留言