【问题标题】:Use component based translations in child components in vue-i18n在 vue-i18n 的子组件中使用基于组件的翻译
【发布时间】:2019-03-28 14:04:04
【问题描述】:

我正在使用 vue-i18n 在我的 vue 应用程序中翻译消息。我在new VueI18n(...) 中添加了一些全局翻译,以及在名为c-parent 的组件中添加了一些基于组件的翻译。该组件包含名为c-child 的子组件。现在,我想在c-child 中也使用c-parent 的基于组件的翻译。

我在这个小提琴中做了一个小例子:https://jsfiddle.net/d80o7mpL/

问题出在输出的最后一行:c-child 中的消息未使用基于组件的c-parent 翻译进行翻译。

由于所有组件都“继承”了全局翻译,我希望基于组件的翻译(在它们各自的组件子树中)也是如此。有没有办法在 vue-i18n 中实现这一点?

【问题讨论】:

    标签: vue.js 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>&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>

    【讨论】:

    • 这是一个解决方案,但恐怕它不能很好地扩展到少数消息。感谢您这么快回答!
    • 我想,为了更好地扩展它,您可以在根级别定义语言并在其自身中定义组件数据。
    • 好吧,你可以用对象传递少量消息。
    • 我在一个较大的 SPA 中使用它,其中每个页面都是顶级组件。我希望我可以在这个顶级组件中获得页面的所有翻译,并在构成页面的所有子组件中使用它们,而不必将翻译传递到几个级别。
    • 好吧,在这种情况下,您可以将它作为对象传递给相关的孩子,而不是单独传递。希望能帮助你接受答案。
    【解决方案2】:

    我正在做的是在router.ts 中使用i18n.mergeLocaleMessage每条路线合并特定的.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 也有同样的情况。

      假设我们有一个“卡片”对象道具,它包含我们将在作为父级的 CardModal.vue 组件中使用的所需语言(我的例子)。 所以我所做的是获取所需的语言环境 json 文件(基于道具语言)并在卡片道具中添加这些消息。

      所以在父组件中我们将拥有:

      <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 属性,这就是我将语言环境添加到该对象的原因。

      如果您需要使用组件中的选择标记更改语言环境,我们可以使用诸如docs shows 之类的语言环境数据属性的观察器

      【讨论】:

        猜你喜欢
        • 2021-03-05
        • 2019-10-14
        • 1970-01-01
        • 2016-10-10
        • 2021-04-26
        • 2019-06-13
        • 2022-08-20
        • 2020-01-17
        • 2019-04-19
        相关资源
        最近更新 更多