Customization

Localization

Twelve languages ship with the package. Hand the grid the ones your app offers and it picks between them; the same tag drives Intl, so numbers and dates follow the language rather than drifting from it.

Switching Language

Change the language below and watch three things move at once: the toolbar and footer strings, the currency format, and the date format. The sort, the filter and the page stay where they were, because the language is state on the grid rather than a remount.

Hoang Kowalski
Design
€127,691.00
Mar 6, 2024
Bruno Nguyen
Growth
€105,146.00
Mar 6, 2024
Bruno Dubois
Design
€86,538.00
Feb 5, 2021
Farid Haddad
Growth
€76,443.00
May 4, 2022
Jonas Yilmaz
Core
€129,812.00
Nov 13, 2024
24 rows
1–5 of 24
// locale forces a tag rather than following the page
createDataGrid<Person>({ columns, data, getRowId, locales, locale: 'vi-VN' });

// Assigning it switches in place, keeping the sort, filter and selection
grid.locale = 'ja-JP';

// The same tag drives Intl, so number, currency and date columns that name
// no locale of their own reformat with it.
{ id: 'salary', type: 'currency', typeOptions: { currency: 'EUR' } }

// A tag nobody answers for falls back to English, and 'vi' is answered by
// the 'vi-VN' pack.

Loading Packs

There is no "all languages" export on purpose: a pack nobody imports is a pack nobody ships. The grid below ships one pack, viVN, and the three tags show the whole rule. The exact tag matches. A bare vi is answered by the vi-VN pack. A tag no pack answers for falls back to English, which is built in and needs no import.

Hoang Kowalski
Design
€127,691.00
Mar 6, 2024
Bruno Nguyen
Growth
€105,146.00
Mar 6, 2024
Bruno Dubois
Design
€86,538.00
Feb 5, 2021
Farid Haddad
Growth
€76,443.00
May 4, 2022
Jonas Yilmaz
Core
€129,812.00
Nov 13, 2024
5 rows
1–5 of 5
import { createDataGrid } from '@sv5ui/datagrid';
import { enUS, jaJP, viVN } from '@sv5ui/datagrid/locales';

// Hand the grid the languages it may use. It picks one from the page's own
// language, so nothing else needs configuring. A pack nobody imports is
// never bundled, which is why there is no "all languages" export.
const grid = createDataGrid<Person>({
  columns,
  data,
  getRowId,
  locales: [enUS, viVN, jaJP]
});

The Twelve Packs

From @sv5ui/datagrid/locales, named after their tag: enUS, viVN, zhCN, jaJP, koKR, frFR, deDE, esES, ptBR, ruRU, idID, thTH.

TagLanguage
en-USEnglish
vi-VNVietnamese
zh-CNChinese, simplified
ja-JPJapanese
ko-KRKorean
fr-FRFrench
de-DEGerman
es-ESSpanish
pt-BRPortuguese, Brazil
ru-RURussian
id-IDIndonesian
th-THThai

Overriding Single Strings

labels replaces individual strings on top of the chosen pack. The grid below is English with four of them changed: the search placeholder, the empty text, the selection count and the page-size label.

Hoang Kowalski
Design
€127,691.00
Bruno Nguyen
Growth
€105,146.00
Bruno Dubois
Design
€86,538.00
5 rows
1–3 of 5
// labels replaces single strings on top of the chosen pack, any subset
createDataGrid<Person>({
  columns,
  data,
  getRowId,
  locales: [enUS],
  labels: {
    search: 'Find a member',
    noData: 'Nobody here yet',
    // Functions where a value is interpolated, so a language can put the
    // number where it needs it.
    selectedRows: (count) => `${count} chosen`,
    pageRange: (from, to, total) => `${from} to ${to} of ${total}`,
    // Operator maps override one entry at a time
    textOps: { contains: 'has' }
  },
  // The same for what the live region speaks
  announcer: {
    sorted: (column, direction) => `${column}, ${direction}ending`
  }
});

What the Labels Cover

Every string the grid renders, grouped by where it appears. A label is a plain string, or a function where a value is interpolated.

AreaKeys
Toolbarsearch, activeFilters, removeFilter, clearAllFilters, chooseColumns, rowDensity, densityCompact, densityStandard, densityComfortable
Header and column menucolumnMenu, resizeColumn, resizeGroup, sortAscending, sortDescending, clearSort, pinLeft, pinRight, unpin, openFilter, autosize, hideColumn, collapseGroup, expandGroup
Filter panel and filter rowfilterColumn, filterOperator, filterValue, filterRowValue, filterUpperBound, valuePlaceholder, upperBoundPlaceholder, searchValues, blankValue, anyValue, combineConditions, addCondition, removeCondition, matchCase, apply, clear, and, or, yes, no, and the three operator maps textOps, numberOps and dateOps
RowsselectRow, selectAllRows, rowActions, dragRow, expandRow, collapseRow
Footer and statusrowsPerPage, pageSizeOption, pageRange, totalRows, filteredRows, selectedRows, noData, retry
Menuscopy, copyWithHeaders, exportCsv, exportAllRows, exportLoadedRows, exportSelectedRows, clearSelection

Writing a Pack

A pack says what it has. English answers for the rest, so a pack of five strings works, and one written against this version keeps working when the next names a string it has never heard of: that string arrives in English rather than as a blank or as a build that will not run. Every key it does say is typed, so a translation cannot land on a name the grid does not have.

Which makes spreading enUS.labels into a pack unnecessary, and worse than unnecessary: it freezes today's English into the pack, so a string added later arrives translated to whatever English said when the pack was written.

The second option below is a pack written in this file, four labels deep. Switch to it and watch the search box, the footer's page-size label and the column chooser change while everything left untranslated stays English.

Hoang Kowalski
Design
€127,691.00
Mar 6, 2024
Bruno Nguyen
Growth
€105,146.00
Mar 6, 2024
Bruno Dubois
Design
€86,538.00
Feb 5, 2021
3 rows
1–3 of 3
import type { DataGridLocalePack } from '@sv5ui/datagrid';

// A pack is { tag, labels, announcer } and says what it has. English
// answers for the rest, so two labels is a working pack, and a string the
// grid adds next release arrives in English rather than as a blank.
export const svSE: DataGridLocalePack = {
  tag: 'sv-SE',
  labels: { search: 'Sok...', noData: 'Inga rader' },
  announcer: { sortCleared: () => 'Sortering rensad' }
};

// Every key it does say is typed, so a translation cannot land on a name
// the grid does not have, and a label function keeps its signature.

createDataGrid<Person>({ columns, data, getRowId, locales: [svSE] });

// Layered in this order, so the narrowest wins:
//   English -> the pack for grid.locale -> this app's own labels/announcer
createDataGrid<Person>({
  columns, data, getRowId,
  locales: [svSE],
  labels: { search: 'Sok medlemmar...' }   // over the pack, over English
});

Options

OptionDefault
locales[]
localethe page language
labels-
announcer-