How to convert table headings in Bootstrap-Vue.js

For a few nights now, I've been struggling to translate the table header in my vue.js component. It seems like I'm missing something as I'm new to Vue.js and can't seem to figure out what's wrong. Translating within the HTML works perfectly fine, but when I attempt to translate attributes within the script tag (such as data attributes), I encounter console errors stating that certain fields cannot be found.

Here's what I've done: I initialized the i18n component in the main.js file.

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 the script tag of the Users component, I'm trying to translate the table header. However, I keep 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
    }

You can view the full file 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 greatly appreciate any help or guidance on how to properly translate these types of texts. Google hasn't provided a definitive answer, so any assistance would be invaluable.

Answer №1

As stated in the official documentation:

The fields prop is essential for customizing table column headings and determining the order in which data columns are displayed. The keys within the field object are crucial for extracting values from each item row...

This implies that the value of keys in your fields property should correspond to the keys in your items. For instance, first_name:

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

If you wish to personalize your headers with translated titles, you can utilize 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') }
  }
}

Answer №2

var dataUsers = null;
import localization from 'your-path/localization';
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 {
      info_data: [],
      fields: [
        {key: localization.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.fetch.getAll()
      .then(response => {
        //this.$log.debug("Data loaded: ", response.data) 
        this.info_data = response.data
      }).catch(error => {  
      //this.$log.debug(error)  
      this.error = "Failed to load todos"  
    }) 
  },
  computed: {
    items: function () { 
      return this.info_data;
    }
  },
  methods: {
    getStatusBadge (status) {
      return status === 'Active' ? 'success'
        : status === 'Inactive' ? 'secondary'
          : status === 'Pending' ? 'warning'
            : status === 'Banned' ? 'danger' : 'primary'
    },
    getTotalRowCount (items) {
      return items.length
    },
    userRedirectLink (id) {
      return `users/${id.toString()}`
    },
    rowSelect (item) {
      const userDataLink = this.userRedirectLink(item.id)
      this.$router.push({path: userDataLink})
    }

  }
}
<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="rowSelect">
          <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="getStatusBadge(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>

Answer №3

Utilize the Computed Property to Enhance Efficiency:

    input 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 },

    ]
  }
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

The hydration error in next js is causing this code to malfunction

Why am I encountering a hydration error with this code in NextJS? The Items variable is an array of ReactNode's. Any suggestions for an alternative approach? I've searched extensively for information but haven't found anything related to Nex ...

Autocomplete feature in Material-UI does not trigger the onChange event when a chip

I've encountered a quirk with the Material UI Autocomplete component. It seems that when I delete a tag directly from the chip using the (x) button, the onchange function of the autocomplete isn't triggered. Does anyone know how I can ensure that ...

Ways to conceal a button using Javascript

Due to my limited JavaScript experience, I am struggling with understanding the event flow. This was written in haste, and further editing may be needed. I am working on creating a stack of cards (Bootstrap cards) along with a load button. To keep it inde ...

"Multiple instances of JavaScript files seem to be present when using Ajax navigation

Having some difficulties with AJAX navigation. The issue is that the JavaScript files loaded remain in the browser even after the new content is loaded, even when they are no longer in the DOM. These files appear as VM files in the browser console and cont ...

Applying conditional logic within computed properties results in a failure to update

I have two different fiddles: Fiddle A and Fiddle B (both using Vuejs version 2.2.4) In my code, I have a computed property that can be changed programmatically by utilizing the get and set methods. Expectations for the Computed Property: If the def ...

Having trouble retrieving information from the local API in React-Native

Currently, I have a web application built using React and an API developed in Laravel. Now, I am planning to create a mobile app that will also utilize the same API. However, I'm encountering an issue where I cannot fetch data due to receiving the err ...

How can I use Jquery to loop through each combobox on the page and delete those with a specific class name?

I am currently dealing with a page that contains multiple combo-boxes. Each combo-box has a default option set as empty, which is given the class name 'hide'. This functionality seems to work perfectly in Chrome and Firefox, as the hidden options ...

Execute a function using a click event within a statement

Is it possible to trigger a function with parameters based on the result of a statement? For example, can we achieve something like this: (click)="datavalue.elementDataCollection.length > 1 ? AddNewDialog (datavalue,datavalue.COCLabel,mainindex,i) : r ...

How can I organize data from A to Z in alphabetical order in React Native when the user chooses the A to Z option from the dropdown menu?

I am working on a screen that can display up to 1000 data retrieved from the API. Here is the image: Now, I have implemented a drop-down box where users can select alphabetically from A to Z. After selecting an alphabetical order, the data will be arrang ...

How can I use a dropdown with checkbox to toggle the visibility of a specific div in React?

I have come across a relevant question, but I am struggling to apply it to multiple divs. I haven't found a solution that quite fits my needs. Show or hide element in React Currently, I am using the dropdown with checkboxes from MUI. I am seeking a ...

Firefox 3 fails to utilize cache when an ajax request is made while the page is loading

Upon loading the page DOM, I utilize jQuery to fetch JSON data via ajax like so: $(document).ready(function(){ getData(); }); ...where the function getData() executes a basic jQuery ajax call similar to this: function getData(){ $.ajax({cache: t ...

Navigating JSON Data with ES6 Iteration

Issue Description There are two APIs I am working with. The first one, let's call it API #1, provides JSON data related to forum posts as shown below: [{ "userId": 1, "id": 10, "title": "Tt1", "body": "qBb2" }, { "userId": 2, ...

Troubleshoot my code for clustering markers on a Google map

I'm currently working on a piece of code to generate a Google map that contains 3 hidden points within one marker. The idea is that when the main marker is clicked, these points will either merge into one or expand into 3 separate markers. However, I& ...

How can I trigger a CSS animation to replay each time a button is clicked, without relying on a timeout function?

I am having trouble getting a button to trigger an animation. Currently, the animation only plays once when the page is refreshed and doesn't repeat on subsequent clicks of the button. function initiateAnimation(el){ document.getElementById("anima ...

Exploring the implementation of if statements within the array map function in the context of Next.js

Is there a way to wrap certain code based on the remainder of the index number being 0? I attempted the following approaches but encountered syntax errors. {index % 3 === 0 ? ... : ...} {index % 3 === 0 && ...} export default function UserPosts() { / ...

Tips on displaying substitute text in Angular when an Iframe fails to load the content located at the src

Currently, I am working on an Angular 12 application and have a requirement to fetch content from an external site and display it within a modal popup. To achieve this, I am using the <iframe src="url"> tag to retrieve the content from a se ...

Uncover and control nested objects in JSON data

Having a dynamic foo object with the possibility of nested parent objects raises the question of how to effectively: 1) Determine the last object that has a parent? 2) Create an array containing all nested parent objects along with the initial obj (foo.o ...

How to access the api variable in JavaScript

When attempting to retrieve variables from an API object, I encountered the obstacle of them being nested inside another object named "0" in this particular case. Here is a screenshot from the console: enter image description here Below is the JavaScrip ...

My experience with jquery addClass and removeClass functions has not been as smooth as I had hoped

I have a series of tables each separated by div tags. Whenever a user clicks on a letter, I want to display only the relevant div tag contents. This can be achieved using the following jQuery code: $(".expand_button").on("click", function() { $(th ...

Concealing the URL Once Links are Accessed

I have a Movie / TV Shows Streaming website and recently I've noticed visitors from other similar sites are coming to my site and copying my links. Is there a way to hide the links in the address bar to make it more difficult for them to access my con ...