#vue.js #vue-i18n
#vue.js #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?
Ответ №1:
Ну, вам нужно передать текст дочернему компоненту, используя 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>amp;<c-child/amp;></code> contained in <code>amp;<c-parent/amp;></code>.
<code>amp;<c-parent/amp;></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>
Комментарии:
1. Это решение, но, боюсь, оно недостаточно хорошо масштабируется для более чем нескольких сообщений. Спасибо, что ответили так быстро!
2. Я думаю, чтобы хорошо масштабировать его, вы можете определить язык на корневом уровне и определить данные компонента сами по себе.
3. Ну, вы можете передавать несколько сообщений с объектом.
4. Я использую это в более крупном SPA, где каждая страница является компонентом верхнего уровня. Я надеялся, что смогу получить все переводы для страницы в этом компоненте верхнего уровня и использовать их во всех дочерних компонентах, составляющих страницу, без необходимости передавать переводы на несколько уровней ниже.
5. Что ж, в этом случае вы можете передать его как объект соответствующим дочерним элементам вместо того, чтобы передавать его отдельно. Я надеюсь, что это поможет вам принять ответ.
Ответ №2:
Что я делаю, так это использую 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, возможно, вы можете сделать это с помощью хука родительского компонента mounted() (еще не пробовал)
Ответ №3:
У меня была такая же ситуация с i18n.
Допустим, у нас есть объект «card» prop, который включает в себя необходимый язык (был моим случаем), который мы будем использовать в компоненте CardModal.vue, который будет родительским. Итак, что я сделал, так это получил необходимый файл locale json (основанный на языке prop) и добавил эти сообщения в prop card.
Итак, в родительском компоненте мы будем иметь:
<template>
<div id="card-modal">
<h1> {{ card.locales.title }} </h1>
<ChildComponent card="card" />
</div>
</template>
<script>
export default {
name: 'CardModal',
props: {
card: {
type: Object,
required: true,
}
}
data() {
return {
locale: this.card.language, //'en' or 'es'
i18n: {
en: require('@/locales/en'),
es: require('@/locales/es'),
},
}
},
created() {
this.card.locales = this.i18n[this.locale].card_modal
}
}
</script>
Обратите внимание, что мы больше не полагаемся на функцию плагина ( $ t()), и мы только меняем локаль в текущем компоненте. Я сделал это таким образом, потому что я не хотел использовать тег «i18n» в каждом дочернем компоненте и хотел сохранить все сообщения о локали в одном файле json для каждого языка. Я уже использовал card prop во всех дочерних компонентах, поэтому я добавил локали к этому объекту.
Если вам нужен способ изменить языковой стандарт с помощью тега select в компоненте, мы можем использовать средство просмотра для свойства locale data, как показано в документах