[Vuejs]-How to change language of primevue filters

0👍

this away by vuetify3:

<script>
export default {
  data() {
    return {
      search: '',
      tableHeaders: [
        {
          align: 'start',
          key: 'name',
          sortable: false,
          title: this.$t('nutrition.dessertHeader'),
        },
        {
          key: 'calories',
          title: this.$t('nutrition.caloriesHeader'),
        },
        {
          key: 'fat',
          title: this.$t('nutrition.fatHeader'),
        },
        {
          key: 'carbs',
          title: this.$t('nutrition.carbsHeader'),
        },
        {
          key: 'protein',
          title: this.$t('nutrition.proteinHeader'),
        },
        {
          key: 'iron',
          title: this.$t('nutrition.ironHeader'),
        },
      ],
      desserts: [
        {
          name: 'Frozen Yogurt',
          calories: 159,
          fat: 6.0,
          carbs: 24,
          protein: 4.0,
          iron: 1,
        },
        //...
      ],
    };
  },
  created() {
    // Set translations as data properties
    this.$data.nutrition = {
      title: this.$t('nutrition.title'),
      search: this.$t('nutrition.search'),
      dessertHeader: this.$t('nutrition.dessertHeader'),
      caloriesHeader: this.$t('nutrition.caloriesHeader'),
      fatHeader: this.$t('nutrition.fatHeader'),
      carbsHeader: this.$t('nutrition.carbsHeader'),
      proteinHeader: this.$t('nutrition.proteinHeader'),
      ironHeader: this.$t('nutrition.ironHeader'),
    };
  },
};
</script>
<template>
  <v-card>
    <v-card-title>
      {{ $t('nutrition.title') }}
      <v-spacer></v-spacer>
      <v-text-field
        v-model="search"
        append-icon="mdi-magnify"
        :label="$t('nutrition.search')"
        single-line
        hide-details
      ></v-text-field>
    </v-card-title>
    <v-data-table :headers="tableHeaders" :items="desserts" :search="search"></v-data-table>
  </v-card>
</template>

0👍

After a long journey through the source code of PrimeVue v3.28.0, I finally found the method for labeling custom filters, although it is still a clumsy solution.

As you can see, there is a computed method called matchModes() in the definition of the ColumnFilter component, located at line 2153 in datatable.js.

matchModes() {
    return (
        this.matchModeOptions ||
        this.$primevue.config.filterMatchModeOptions[this.type].map((key) => {
            return { label: this.$primevue.config.locale[key], value: key };
        })
    );
}

This method is used as the options parameter for the Dropdown component at line 2360. The label attribute of the elements returned by matchModes() is what we ultimately want to display.

vue.createBlock(_component_CFDropdown, {
    key: 0,
    options: $options.matchModes,
    modelValue: fieldConstraint.matchMode,
    class: "p-column-filter-matchmode-dropdown",
    optionLabel: "label",
    optionValue: "value",
    "aria-label": $options.filterConstraintAriaLabel,
    "onUpdate:modelValue": $event => ($options.onMenuMatchModeChange($event, i))
  }, null, 8, ["options", "modelValue", "aria-label", "onUpdate:modelValue"])

However, according to the definition of the matchModes() method above, if the filter we define does not belong to any dataType defined in primevue.config.filterMatchModeOptions, it will directly return a plain string without a label, which results in no text being displayed.

A temporary solution, written using the Composition API, is as follows, assuming that I have registered a custom filter for a custom date field that uses moment.js:

In the <script> block:

import { usePrimeVue } from 'primevue/config';

const PrimeVue = usePrimeVue();

PrimeVue.config.filterMatchModeOptions.MomentDateTime = ['filterByDateTimeEquals'];

PrimeVue.config.locale.filterByDateTimeEquals = PrimeVue.config.locale.dateIs;

FilterService.register('filterByDateTimeEquals', (datetime, value) => {
    if (!value) return true;
    return TimeService.Backend.toJSDate(datetime).getTime() == value.getTime();
});

In the <template> block, part omitted:

<DataTable>
    ...
    <!--Here, a dataType is added-->
    <Column field="birthDate" header="Birth Date" dataType="MomentDateTime">
        <template #body="{ data }">
            {{ TimeService.Frontend.fromDate(data.birthDate) }}
        </template>
        <template #filter="{ filterModel }">
            <Calendar v-model="filterModel.value" dateFormat="yy/mm/dd" :placeholder="moment().format('YYYY/MM/DD')" />
        </template>
    </Column>
    ...
</DataTable>

However, this solution is still not elegant enough. I have already raised an issue on GitHub to request the development team to address this matter, waiting for their response.

Leave a comment