Как использовать VueI18n для интернационализации на основе экземпляра компонента?

Я создаю приложение Vue без использования npm. Поскольку существует слишком много руководств, относящихся к npm, я не могу им правильно следовать. Итак, я просто включил такие скрипты:

    <script src="/js/bluebird.min.js"></script>
    <script src="/js/vue.js"></script>
    <script src="/js/vue-i18n.js"></script>
    <script src="/js/axios.min.js"></script>
    <script src="/js/components.js"></script>
    <script src="/js/app.js"></script>

Пока я пытаюсь показать список кнопок, загружая их из файла json. Этот файл содержит массив объектов с информацией о кнопке, включая ее текст на разных языках. Итак, пока я не могу понять, как заставить vue-i18n загружать сообщения из этого файла. Основной код:

            <buttons-list inline-template>
                <div class="buttons-list">
                    <big-button inline-template
                        :class="[button.position, button.number]"
                        v-for="button in buttons"
                        :key="button.id"
                        :button="button">
                        <div class="big-button">{{ $t(button.text) }}</div>
                    </big-button>
                </div>
            </buttons-list>

Код компонента buttonsList:

Vue.component('buttons-list', {
    data: function() {
        return {
            buttons: []
        }
    },
    created: function() {
        this.loadButtons()
    },
    methods: {
        loadButtons: function() {
            const list = this;
            axios.get('/json/buttons.json')
            .then(function(response) {
                list.buttons = response.data
            })
        }
    }
})

Здесь я читаю файл json при создании компонента, поэтому при создании bigButton свойство button будет иметь всю необходимую информацию. Код компонента bigButton:

Vue.component('big-button', {
    data: function() {
        return {
            text: ''
        }
    },
    props: ['button'],
    created: function() {            
        this.$i18n.setLocaleMessage('en', this.button.messages.en)
        this.$i18n.setLocaleMessage('ru', this.button.messages.ru)
    },
    i18n: {
        messages: {}
    }
})

Здесь, в функции created, я попытался установить экземпляр i18n.messages в данные из файла json. В принципе, это работает, за исключением того, что он сбрасывает messages для всех кнопок до текущих данных, в результате чего все кнопки имеют одинаковый текст последней кнопки. Можно ли работать с экземплярами компонентов в vue-i18n? Или есть другие способы, которые мне не хватает?


РЕШЕНИЕ

Я изменил код компонента bigButton на:

Vue.component('big-button', {
    data: function() {
        return {
            text: ''
        }
    },
    props: {
        button: {
            type: Object,
            default: function() {return {}}
        },
    },
    created: function() {
        this.$i18n.setLocaleMessage('en', this.button.messages.en)
        this.$i18n.setLocaleMessage('ru', this.button.messages.ru)
    },
    i18n: {
        //i18n stops working when this block removed
    }
})

и это сработало!


person Jakupov    schedule 11.07.2018    source источник


Ответы (1)


VueI18n поддерживает локализацию для каждого компонента — это объясняется в официальной документации. Просто определите i18nobject с сообщениями внутри вашего компонента — документация точно показывает, как это сделать:

// setup locale info for root Vue instance
const i18n = new VueI18n({
  locale: 'ja',
  messages: {
    en: {
      message: {
        hello: 'hello world',
        greeting: 'good morning'
      }
    },
    ja: {
      message: {
        hello: 'こんにちは、世界',
        greeting: 'おはようございます'
      }
    }
  }
})

// Define component
const Component1 = {
  template: `
    <div class="container">
     <p>Component1 locale messages: {{ $t("message.hello") }}</p>
     <p>Fallback global locale messages: {{ $t("message.greeting") }}</p>
   </div>`,
  i18n: { // `i18n` option, setup locale info for component
    messages: {
      en: { message: { hello: 'hello component1' } },
      ja: { message: { hello: 'こんにちは、component1' } }
    }
  }
}

// template
<div id="app">
  <p>{{ $t("message.hello") }}</p>
  <component1></component1>
</div>

ОБНОВИТЬ

Как инициализировать компонент уникальными строками локализации:

const Component1 = {
  template: `
    <div class="container">
     <p>Component1 locale messages: {{ $t("message.hello") }}</p>
     <p>Fallback global locale messages: {{ $t("message.greeting") }}</p>
   </div>`,
  i18n: { // `i18n` option, setup locale info for component
    messages: uniqueLocalization
  },
  props:
  {
    uniqueLocalization:
    {
      type: Object,
      default: () => ({})
    }
  }
}

<template>
  <div>
    <comp :unique-localization="locale_1"/>
    <comp :unique-localization="locale_2"/>
    <comp :unique-localization="locale_3"/>    
  </div>
</template>

<script>
import component1 from '@/components/component1.vue'

export default
{
  components:
  {
    comp: component1
  },
  data()
  {
    return {
      locale_1:
      {
        en:
        {
          message:
          {
            hello: 'Greetings',
            bye: 'Farewell'
          }
        },
        ru:
        {
          message:
          {
            hello: 'Привет',
            bye: 'До свидания'
          }
        }
      },
      locale_3:
      {
        en:
        {
          message:
          {
            hello: 'Greetings, buddy',
            bye: 'Farewell, dude'
          }
        },
        ru:
        {
          message:
          {
            hello: 'Привет, ребята',
            bye: 'До свидания, мужики'
          }
        }
      },
      locale_3:
      {
        en:
        {
          message:
          {
            hello: 'Godd day, team',
            bye: 'Bye-bye, darling'
          }
        },
        ru:
        {
          message:
          {
            hello: 'Здравствуйте, братушки',
            bye: 'Пока'
          }
        }
      }
    };
  }
}
</script>
person IVO GELOV    schedule 11.07.2018
comment
Допустим, у меня есть 10 экземпляров Component1 одновременно, текст на английском языке какого из них будет «привет, компонент1»? Мне нужно, чтобы каждый из них имел разный текст, и локализация для каждого компонента не помогает. - person Jakupov; 11.07.2018
comment
Это помогает, но вы должны инициализировать объекты i18n для каждого компонента с разными значениями - через реквизиты, AJAX или что-то еще. Или, если вы настаиваете на том, чтобы каждый из 10 компонентов был уникальным — просто создайте 10 разных компонентов в 10 разных .vue файлах, каждый со своим текстом локализации. - person IVO GELOV; 11.07.2018
comment
Вот и вопрос, как инициализировать компонент с разными значениями? Я пытался написать i18n: {messages: this.button.messages} безуспешно. - person Jakupov; 11.07.2018
comment
Странно, с this.button.messages не работает, а с this.localization работает при передаче button.messages в компонент напрямую через :localization. Спасибо за помощь! - person Jakupov; 12.07.2018
comment
Этот код работал, но не напрямую. Это не работает, когда данные загружаются из файла json, и, конечно, я не перечислял все компоненты напрямую, только через v-for. Похоже, эта проблема возникла, когда я пытался передать props как массив. Когда я изменил его на объект, как в этом примере, это сработало как шарм! - person Jakupov; 12.07.2018