Appearance
Localization
The grid contains texts in English (en, default) and German (de):
ts
const options: GridOptions = { locale: "de" };The demo switches the language of the grid texts (filter row and filter popups, column menu, context menu, group panel, pagination, status bar). The header texts and the number and date formats are part of the column definitions, so the demo translates them itself. The checkbox adds a few overrides with localeText.
Source
vue
<template>
<div class="demo">
<div class="demo-toolbar">
<select v-model="locale" aria-label="Language">
<option value="en">English</option>
<option value="de">Deutsch</option>
</select>
<label><input type="checkbox" v-model="customTexts" /> Custom texts (localeText)</label>
</div>
<Datagrid :columns="columns" :rows="rows" :options="options" />
</div>
</template>
<script setup lang="ts">
import { computed, ref } from "vue";
import { Datagrid, type ColumnConfig, type GridOptions } from "@datagrid/vue-ui";
import { createEmployees, type Employee } from "./data";
type Locale = "en" | "de";
const rows = createEmployees(200);
// header texts are part of the column definitions and translated by the application
const headers = {
en: { name: "Name", department: "Department", city: "City", startDate: "Start date", salary: "Salary", active: "Active" },
de: { name: "Name", department: "Abteilung", city: "Stadt", startDate: "Eintritt", salary: "Gehalt", active: "Aktiv" },
};
// overrides for single texts of the built-in translations
const overrides = {
en: {
hint_drag_columns: "Drag the Department or City header here to group the employees",
page_info: "Employees {from}–{to} of {total}",
empty: "No employees found",
},
de: {
hint_drag_columns: "Abteilung oder Stadt hierher ziehen, um die Mitarbeiter zu gruppieren",
page_info: "Mitarbeiter {from}–{to} von {total}",
empty: "Keine Mitarbeiter gefunden",
},
};
const locale = ref<Locale>("de");
const customTexts = ref(false);
const columns = computed<Array<ColumnConfig<Employee>>>(() => {
const text = headers[locale.value];
// number and date formats are defined by the value formatters of the columns
const currency = new Intl.NumberFormat(locale.value, { style: "currency", currency: "EUR", maximumFractionDigits: 0 });
const date = new Intl.DateTimeFormat(locale.value, { dateStyle: "medium" });
return [
{ id: "name", text: text.name, flex: 1.5, valueGetter: ({ data }) => `${data.firstName} ${data.lastName}` },
{ field: "department", text: text.department, filterType: "set", groupable: true, flex: 1.3 },
{ field: "city", text: text.city, groupable: true },
{ field: "startDate", text: text.startDate, type: "date", valueFormatter: ({ value }) => date.format(new Date(value)) },
{ field: "salary", text: text.salary, type: "number", aggFunc: "sum", valueFormatter: ({ value }) => currency.format(value) },
{ field: "active", text: text.active, type: "boolean" },
];
});
const options = computed<GridOptions<Employee>>(() => ({
locale: locale.value,
localeText: customTexts.value ? overrides[locale.value] : undefined,
selection: "Cell",
singleSelect: false,
columnMenu: true,
contextMenu: true,
statusBar: true,
pagination: { enabled: true, pageSize: 50, pageSizes: [50, 100] },
defaultColumn: { flex: 1, sortable: true, filterable: true, resizeable: true },
}));
</script>tsx
import { useMemo, useState } from "react";
import { Datagrid, type ColumnConfig, type GridOptions } from "@datagrid/react-ui";
import { createEmployees, type Employee } from "../data";
type Locale = "en" | "de";
const rows = createEmployees(200);
// header texts are part of the column definitions and translated by the application
const headers = {
en: { name: "Name", department: "Department", city: "City", startDate: "Start date", salary: "Salary", active: "Active" },
de: { name: "Name", department: "Abteilung", city: "Stadt", startDate: "Eintritt", salary: "Gehalt", active: "Aktiv" },
};
// overrides for single texts of the built-in translations
const overrides = {
en: {
hint_drag_columns: "Drag the Department or City header here to group the employees",
page_info: "Employees {from}–{to} of {total}",
empty: "No employees found",
},
de: {
hint_drag_columns: "Abteilung oder Stadt hierher ziehen, um die Mitarbeiter zu gruppieren",
page_info: "Mitarbeiter {from}–{to} von {total}",
empty: "Keine Mitarbeiter gefunden",
},
};
export default function Localization() {
const [locale, setLocale] = useState<Locale>("de");
const [customTexts, setCustomTexts] = useState(false);
const columns = useMemo<Array<ColumnConfig<Employee>>>(() => {
const text = headers[locale];
// number and date formats are defined by the value formatters of the columns
const currency = new Intl.NumberFormat(locale, { style: "currency", currency: "EUR", maximumFractionDigits: 0 });
const date = new Intl.DateTimeFormat(locale, { dateStyle: "medium" });
return [
{ id: "name", text: text.name, flex: 1.5, valueGetter: ({ data }) => `${data.firstName} ${data.lastName}` },
{ field: "department", text: text.department, filterType: "set", groupable: true, flex: 1.3 },
{ field: "city", text: text.city, groupable: true },
{ field: "startDate", text: text.startDate, type: "date", valueFormatter: ({ value }) => date.format(new Date(value)) },
{ field: "salary", text: text.salary, type: "number", aggFunc: "sum", valueFormatter: ({ value }) => currency.format(value) },
{ field: "active", text: text.active, type: "boolean" },
];
}, [locale]);
const options = useMemo<GridOptions<Employee>>(
() => ({
locale,
localeText: customTexts ? overrides[locale] : undefined,
selection: "Cell",
singleSelect: false,
columnMenu: true,
contextMenu: true,
statusBar: true,
pagination: { enabled: true, pageSize: 50, pageSizes: [50, 100] },
defaultColumn: { flex: 1, sortable: true, filterable: true, resizeable: true },
}),
[locale, customTexts]
);
return (
<div className="demo">
<div className="demo-toolbar">
<select value={locale} onChange={(e) => setLocale(e.target.value as Locale)} aria-label="Language">
<option value="en">English</option>
<option value="de">Deutsch</option>
</select>
<label>
<input type="checkbox" checked={customTexts} onChange={(e) => setCustomTexts(e.target.checked)} /> Custom
texts (localeText)
</label>
</div>
<Datagrid columns={columns} rows={rows} options={options} />
</div>
);
}Overriding texts
Single texts are overridden with localeText:
ts
const options: GridOptions = {
locale: "de",
localeText: {
empty: "Keine Mitarbeiter gefunden",
hint_drag_columns: "Spalte hierher ziehen",
},
};Adding languages
Register a new language once with registerLocale. Missing keys fall back to English.
ts
import { registerLocale } from "@datagrid/vue-ui";
registerLocale("fr", {
empty: "Aucune ligne",
loading: "Chargement…",
filter_placeholder: "Filtrer…",
// ...
});Alternatively provide a translation function with localize: (key) => i18n.t(\grid.${key}`)`.
Keys
All keys can be found in the English translation (packages/core/src/i18n/en.ts). Some texts contain placeholders, e.g. page_info: "{from}–{to} of {total}".
| Group | Keys |
|---|---|
| general | empty, loading, hint_drag_columns, total, true, false, select_all, select_row, expand, collapse, search |
| filter | filter, filter_placeholder, filter_clear, filter_apply, filter_select_all, filter_blank, filter_search, filter_and, filter_or, filter_to, filter_true, filter_false, filter_all |
| operators | op_contains, op_notContains, op_equals, op_notEqual, op_startsWith, op_endsWith, op_blank, op_notBlank, op_lessThan, op_lessThanOrEqual, op_greaterThan, op_greaterThanOrEqual, op_inRange |
| column menu | menu_sort_asc, menu_sort_desc, menu_sort_clear, menu_pin_left, menu_pin_right, menu_unpin, menu_autosize, menu_autosize_all, menu_group, menu_ungroup, menu_hide, menu_columns, menu_reset_columns |
| pagination | page_first, page_previous, page_next, page_last, page_size, page_info, page_of |
Number and date formats are controlled by the formatters of the columns, see formatting.