Vue-i18n - проблема с динамическими локализациями из HTTP-запроса.

Я пытаюсь загрузить локализацию из HTTP-вызова, поскольку я хочу, чтобы языки были динамическими и управляемыми, а не отправляли ее вместе с приложением.

Я поработал над примером SSR и некоторыми из моих собственных реализаций. Но при первоначальном рендере язык не загружается. При изменении маршрута обновляются вещи на стороне клиента.

i18n.js

import Vue from 'vue'
import VueI18n from 'vue-i18n'
import en from './en.json'
import ar from './ar.json'
import axios from 'axios'

Vue.use(VueI18n)

const fallbackLocale = 'en'
let defaultLocale = 'ar'

export const i18n = new VueI18n({
  locale: defaultLocale, // set locale
  fallbackLocale: fallbackLocale,
  messages: {
    'en': en
  }
})

export function createI18n () {
  return i18n
}

Маршрутизатор - router.beforeEach

router.beforeEach((to, from, next) => {
    if (router.app.$store) {
        router.app.$store
          .dispatch('getI18nData')
          .then(function(){
            router.app.$i18n.setLocaleMessage('ar',router.app.$store.getters.getLocale)
            return next()
          })
          .catch(() => console.log('getI18nData-error'))
      } else {
        next()
      }
  })

Действие магазина - получить языковой стандарт

getI18nData ({ commit }) {
   try {
     axios.get('http://localhost:8080/lang?lang=ar')
    .then(function (response) {
      let locale = response.data
      commit('setLocale', { locale })
    })
    .catch(function (error) {
      console.log('Error:getI18nData')
    })
   } catch (error) {
     console.error(error);
   }
 }

Выводы: i18n инициализируется до router.beforeEach, тогда как он должен инициализироваться после router.beforeEach.

Ссылка на проблему Github


person Fahid Mohammad    schedule 10.06.2018    source источник
comment
Вернуть обещание от getI18nData. return axios.get(... работает, или сделайте его асинхронным другими способами, например async getI18nData(...){... и await axios.get. Прямо сейчас он продолжается сразу после запуска отправки, потому что обещание не было возвращено.   -  person ippi    schedule 10.06.2018


Ответы (1)


Хорошо, чтобы быть более подробным: вы не хотите смешивать try / catch с цепочкой обещаний, но вам нужно вернуть обещание от getI18nData, иначе отправка не будет ждать. Итак, вы либо:

getI18nData ({ commit }) {
    // axios.get() returns a promise already, so we can just return the whole thing:
    return axios
      .get('http://localhost:8080/lang?lang=ar')
      .then(function (response) {
        let locale = response.data
        commit('setLocale', { locale })
      })
      .catch(function (error) {
        console.log('Error:getI18nData')
      });
}

Или вы используете async / await (что позволяет try / catch):

async getI18nData ({ commit }) {
  try {
    let response = await axios.get('http://localhost:8080/lang?lang=ar');
    let locale = response.data
    commit('setLocale', { locale })
  } catch (error) {
    console.error(error);
  }
}

Я хотел бы добавить, что мне больше нравится вариант async / await, но в vuex-land это обычно приводит к тому, что вам нужно делать все async / await (если вы используете вложенные вызовы диспетчеризации). Поэтому, в зависимости от остальной части вашего кода, может быть проще просто вернуть обещание.

person ippi    schedule 10.06.2018
comment
Спасибо, что указали на недостаток, хотя я отправил обещание, оно не сработало. Итак, вместе с отправкой обещания мне пришлось внести еще одно изменение в код, который router.beforeEach, мне пришлось заменить его на router.beforeResolve, и теперь, похоже, все работает нормально. - person Fahid Mohammad; 10.06.2018