Использовать переводы на основе компонентов в дочерних компонентах в vue-i18n

Я использую vue-i18n для перевода сообщений в моем приложении vue. У меня есть несколько глобальных переводов, добавленных в new VueI18n(...), а также некоторые переводы на основе компонентов в компонент с именем c-parent. Компонент содержит дочерние компоненты с именем c-child. Теперь я хотел бы использовать компонентные переводы c-parent также в c-child.

Я сделал небольшой пример в этой скрипке: https://jsfiddle.net/d80o7mpL/

Проблема находится в последней строке вывода: сообщение в c-child не переводится с использованием переводов c-parent на основе компонентов.

Поскольку глобальные переводы «наследуются» всеми компонентами, я ожидал бы того же для переводов на основе компонентов (в их соответствующем поддереве компонентов). Есть ли способ добиться этого в vue-i18n?


person Simon    schedule 28.03.2019    source источник


Ответы (2)


Что ж, вам нужно передать текст дочернему компоненту с помощью props.

Глобальные переводы «наследуются» всеми компонентами. Но вы используете местный перевод в детском.

const globalMessages = {
  en: { global: { title: 'Vue i18n: usage of component based translations' } }
}

const componentLocalMessages = {
	en: { local: {
    title: "I\'m a translated title",
    text: "I\'m a translated text"
  }}
}

Vue.component('c-parent', {
	i18n: {
  	messages: componentLocalMessages
  },
	template: `
    <div>
      <div>c-parent component based translation: {{ $t('local.title') }}</div>
      <c-child :text="$t('local.title')"></c-child>
    </div>
  `
})

Vue.component('c-child', {
  props: ['text'],
	template: `
		<div>c-child translation: {{ text }}</div>
	`
})

Vue.component('app', {
	template: '<c-parent />'
})

const i18n = new VueI18n({
	locale: 'en',
  messages: globalMessages
})

new Vue({
  i18n,
  el: "#app",
})
body {
  background: #20262E;
  padding: 20px;
  font-family: Helvetica;
}

#app {
  background: #fff;
  border-radius: 4px;
  padding: 20px;
}

h5 {
  margin: 1em 0 .5em 0;
}
<script src="https://unpkg.com/vue"></script>
<script src="https://unpkg.com/vue-i18n"></script>

<div id="app">
  <h2>{{ $t('global.title') }}</h2>
  We define two Vue components: <code>&lt;c-child/&gt;</code> contained in <code>&lt;c-parent/&gt;</code>.
  <code>&lt;c-parent/&gt;</code> defines some component based translations. We would like to use the
  parent's translations in the child but it does not work.
  
  <h5>Example:</h5>
  <app />
</div>

person Varit J Patel    schedule 28.03.2019
comment
Это решение, но я боюсь, что оно плохо масштабируется для более чем нескольких сообщений. Спасибо, что ответили так быстро! - person Simon; 28.03.2019
comment
Я думаю, чтобы хорошо масштабировать его, вы можете определить язык на корневом уровне и определить данные компонентов сами по себе. - person Varit J Patel; 28.03.2019
comment
Что ж, вы можете передать несколько сообщений с помощью объекта. - person Varit J Patel; 29.03.2019
comment
Я использую это в более крупном SPA, где каждая страница является компонентом верхнего уровня. Я надеялся, что смогу иметь все переводы для страницы в этом компоненте верхнего уровня и использовать их во всех дочерних компонентах, составляющих страницу, без необходимости передавать перевод (-ы) на несколько уровней ниже. - person Simon; 29.03.2019
comment
Что ж, в этом случае вы можете передать его как объект соответствующим дочерним элементам, а не передавать его по отдельности. Надеюсь, это поможет вам принять ответ. - person Varit J Patel; 30.03.2019

Я использую i18n.mergeLocaleMessage в router.ts для объединения определенного .i18n.json файла перевода (путем установки свойства meta.i18n) для каждого маршрута:

const router = new Router({
[...]
    {
      path: '/settings',
      name: 'settings',
      component: () => import('./views/Settings.vue'),
      meta: {
        i18n: require('./views/Settings.i18n.json'),
      },
    },
[...]
});

router.beforeEach((to, from, next) => {
    // load view-scoped translations?
    if (!!to.meta.i18n) {
      Object.keys(to.meta.i18n).forEach((lang) => i18n.mergeLocaleMessage(lang, to.meta.i18n[lang]));
    }
    next();
});

Когда Settings.i18n.json выглядит так:

{
    "en": 
    {
        "Key": "Key"    
    },
    "es": 
    {
        "Key": "Clave"    
    }
}

Таким образом, все дочерние компоненты будут использовать один и тот же файл перевода.

Если вы не можете использовать vue-router, возможно, вы можете сделать это в connected () родительского компонента. крючок (не пробовал)

person jordisan    schedule 30.07.2019