简体   繁体   中英

Translate header of table in Bootstrap-Vue.js

I'm already trying to translate my table header in a vue.js component for a few nights, but it doesn't work for me. Probably this is due the fact that I'm new to Vue.js and probably that I'm forgetting something but I'm not able to find the clue. The translation within the HTML wording is working fine, but as soon as I would like to translate an attribute within the script tag (eg data attributes) I'm getting console errors that certain fields cannot be found.

What I did, first I initialized the i18n component within the main.js

import Vue from 'vue'
import BootstrapVue from 'bootstrap-vue'
import App from './App'
import router from './router'
import axios from './api'
import VueAxios from 'vue-axios'
import VueI18n from 'vue-i18n'

Vue.use(BootstrapVue)
Vue.use(VueAxios, axios)
Vue.prototype.$axios = axios;

Vue.use(VueI18n)

// Ready translated locale messages
const messages = {
    en: require('./locales/en_GB.json'),
    nl: require('./locales/nl_NL.json')
}

  // Create VueI18n instance with options
  const i18n = new VueI18n({
    locale: 'nl', // set locale
    fallbackLocale: 'en',
    messages // set locale messages
  })

// TODO load messages async, otherwise all messages will be loaded at once: http://kazupon.github.io/vue-i18n/guide/lazy-loading.html

/* eslint-disable no-new */
new Vue({
  el: '#app',
  router,
  i18n,
  template: '<App/>',
  components: {
    App
  }
})

Then within my script tag of the Users component I'm trying to translate the table header that is defined in there. However for some reason I'm getting console errors like TypeError: "o is undefined" .

  data: () => {
    return {
      items_data: [],
      fields: [
        {key: this.$i18n.t('next')}, //<-- Translate table header values
        {key: 'name'},
        {key: 'registered'},
        {key: 'role'},
        {key: 'status'}
      ],
      currentPage: 1,
      perPage: 5,
      totalRows: 0
    }

See full file here below:

<template>
  <b-row>
    <b-col cols="12" xl="6">
      <transition name="slide">
      <b-card :header="caption">
        <b-table :hover="hover" :striped="striped" :bordered="bordered" :small="small" :fixed="fixed" responsive="sm" :items="items" :fields="fields" :current-page="currentPage" :per-page="perPage" @row-clicked="rowClicked">
          <template slot="id" slot-scope="data">
            <strong>{{data.item.id}}</strong>
          </template>
          <template slot="name" slot-scope="data">
            <strong>{{data.item.name}}</strong>
          </template>
          <template slot="status" slot-scope="data">
            <b-badge :variant="getBadge(data.item.status)">{{data.item.status}}</b-badge>
          </template>
        </b-table>
        <nav>
          <b-pagination size="sm" :total-rows="5" :per-page="perPage" v-model="currentPage" :prev-text="$t('previous')" :next-text="$t('next')" hide-goto-end-buttons/>
        </nav>
      </b-card>
      </transition>
    </b-col>
  </b-row>
</template>

<script>
var usersData = null;
export default {

  name: 'Test Users',
  props: {
    caption: {
      type: String,
      default: 'Users 2'
    },
    hover: {
      type: Boolean,
      default: true
    },
    striped: {
      type: Boolean,
      default: true
    },
    bordered: {
      type: Boolean,
      default: false
    },
    small: {
      type: Boolean,
      default: false
    },
    fixed: {
      type: Boolean,
      default: false
    }
  },
  data: () => {
    return {
      items_data: [],
      fields: [
        {key: this.$i18n.t('next')}, //<-- Translate table header values
        {key: 'name'},
        {key: 'registered'},
        {key: 'role'},
        {key: 'status'}
      ],
      currentPage: 1,
      perPage: 5,
      totalRows: 0
    }
  },
  mounted() {
    this.axios.getAll()
      .then(response => {
        //this.$log.debug("Data loaded: ", response.data) 
        this.items_data = response.data
      }).catch(error => {  
      //this.$log.debug(error)  
      this.error = "Failed to load todos"  
    }) 
  },
  computed: {
    items: function () { 
      return this.items_data;
    }
  },
  methods: {
    getBadge (status) {
      return status === 'Active' ? 'success'
        : status === 'Inactive' ? 'secondary'
          : status === 'Pending' ? 'warning'
            : status === 'Banned' ? 'danger' : 'primary'
    },
    getRowCount (items) {
      return items.length
    },
    userLink (id) {
      return `users/${id.toString()}`
    },
    rowClicked (item) {
      const userLink = this.userLink(item.id)
      this.$router.push({path: userLink})
    }

  }
}
</script>

<style scoped>
.card-body >>> table > tbody > tr > td {
  cursor: pointer;
}
</style>

I would be very thankful when someone could help me to tell how I should translate these type of texts. I tried to find my solution via Google, but according to Google this is more or less how it should work.

According to the documentation :

The fields prop is used to customize the table columns headings, and in which order the columns of data are displayed. The field object keys are used to extract the value from each item row...

meaning in your fields property, the key's value needs to match the items keys.
For example, first_name :

fields: [
  { key: 'first_name'}
],
items: [
  { first_name: 'John' },
  { first_name: 'Jane' }
]

If you want to customize your headers, like translated titles, you can use label :

fields: {
  {
    next: { label: this.$i18n.t('next') },
    name: { label: this.$i18n.t('name') },
    registered: { label: this.$i18n.t('registered') },
    role: { label: this.$i18n.t('role') },
    status: { label: this.$i18n.t('status') }
  }
}

 var usersData = null; import i18n from 'your-path/i18n'; export default { name: 'Test Users', props: { caption: { type: String, default: 'Users 2' }, hover: { type: Boolean, default: true }, striped: { type: Boolean, default: true }, bordered: { type: Boolean, default: false }, small: { type: Boolean, default: false }, fixed: { type: Boolean, default: false } }, data: () => { return { items_data: [], fields: [ {key: i18n.t('next')}, //<-- Add Like this, you need to recreate your component {key: 'name'}, {key: 'registered'}, {key: 'role'}, {key: 'status'} ], currentPage: 1, perPage: 5, totalRows: 0 } }, mounted() { this.axios.getAll() .then(response => { //this.$log.debug("Data loaded: ", response.data) this.items_data = response.data }).catch(error => { //this.$log.debug(error) this.error = "Failed to load todos" }) }, computed: { items: function () { return this.items_data; } }, methods: { getBadge (status) { return status === 'Active' ? 'success' : status === 'Inactive' ? 'secondary' : status === 'Pending' ? 'warning' : status === 'Banned' ? 'danger' : 'primary' }, getRowCount (items) { return items.length }, userLink (id) { return `users/${id.toString()}` }, rowClicked (item) { const userLink = this.userLink(item.id) this.$router.push({path: userLink}) } } }
 <script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script> <template> <b-row> <b-col cols="12" xl="6"> <transition name="slide"> <b-card :header="caption"> <b-table :hover="hover" :striped="striped" :bordered="bordered" :small="small" :fixed="fixed" responsive="sm" :items="items" :fields="fields" :current-page="currentPage" :per-page="perPage" @row-clicked="rowClicked"> <template slot="id" slot-scope="data"> <strong>{{data.item.id}}</strong> </template> <template slot="name" slot-scope="data"> <strong>{{data.item.name}}</strong> </template> <template slot="status" slot-scope="data"> <b-badge :variant="getBadge(data.item.status)">{{data.item.status}}</b-badge> </template> </b-table> <nav> <b-pagination size="sm" :total-rows="5" :per-page="perPage" v-model="currentPage" :prev-text="$t('previous')" :next-text="$t('next')" hide-goto-end-buttons/> </nav> </b-card> </transition> </b-col> </b-row> </template>

Use the Computed Property For This,Its more Efficient:

    enter code here
<b-table :fields="fields" />

...

methods: {
  translateCol (colName) {
    return this.$i18n.t('.fields.' + colName + '.label')
  }
},
computed: {
  fields () {
    return [
      { key: 'id', label: this.translateCol('id'), sortable: true },
      { key: 'name', label: this.translateCol('name'), sortable: true },
      { key: 'description', label: this.translateCol('description'), sortable: true },

    ]
  }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM