# Localization

> Translate every string the grid shows and format numbers and dates for a locale, per grid.

Two props localize a grid. `locale` picks how numbers, prices and dates are formatted. `labels` replaces the text the grid writes itself: menu items, filter operators, the pager, the empty message and the names read out by screen readers. Both apply per grid, so two grids on one page can use two languages.

A grid in Vietnamese: `vi-VN` number formatting, translated pager and filter menu. Open a column's funnel, or page through the rows.

Example: Vietnamese labels and formats (localization.svelte)

```svelte
<script lang="ts">
  import { Grid, type ColumnDef, type GridLabels } from 'bo-grid';
  import { quotes } from './data';

  const columns: ColumnDef[] = [
    { type: 'text', key: 'symbol', header: 'Mã', width: 90 },
    { type: 'text', key: 'name', header: 'Công ty', width: 160 },
    { type: 'price', key: 'price', header: 'Giá' },
    { type: 'percent', key: 'change', header: '+/- %' },
    { type: 'volume', key: 'volume', header: 'Khối lượng', flex: 1 },
  ];
  let rows = $state(quotes());

  // Only the strings that change; the rest stay English. Interpolated
  // entries are functions, so a translation can reorder the parts.
  const labels: Partial<GridLabels> = {
    apply: 'Áp dụng',
    clear: 'Xóa',
    rowsPerPage: 'Số dòng mỗi trang',
    previous: '‹ Trước',
    next: 'Sau ›',
    firstPage: 'Trang đầu',
    lastPage: 'Trang cuối',
    noRows: 'Không có dòng nào khớp',
    filterFor: (h) => `Lọc cột ${h}`,
    pageOf: (p, n, total, locale) => `Trang ${p} / ${n} · ${total.toLocaleString(locale)} dòng`,
  };
</script>

<Grid {rows} {columns} height={180} locale="vi-VN" {labels} filterMenu pageSize={5} />
```

data.ts:

```ts
// Small, fixed data for the docs' examples: every example reads the same
// symbols, so a reader compares features, not datasets.
// A type, not an interface: it then fits GridRow's index signature.
export type Quote = {
  id: number;
  symbol: string;
  name: string;
  sector: string;
  price: number;
  change: number;
  volume: number;
};

const BASE: Omit<Quote, 'id'>[] = [
  { symbol: 'VNM', name: 'Vinamilk', sector: 'Consumer', price: 68.5, change: 1.2, volume: 1_204_000 },
  { symbol: 'FPT', name: 'FPT Corp', sector: 'Technology', price: 132, change: -0.4, volume: 860_500 },
  { symbol: 'HPG', name: 'Hoa Phat', sector: 'Materials', price: 27.35, change: 0.74, volume: 3_412_900 },
  { symbol: 'VCB', name: 'Vietcombank', sector: 'Financials', price: 91.5, change: 0.55, volume: 1_986_200 },
  { symbol: 'MWG', name: 'Mobile World', sector: 'Consumer', price: 51.4, change: -1.1, volume: 2_250_400 },
  { symbol: 'SSI', name: 'SSI Securities', sector: 'Financials', price: 33.3, change: -0.45, volume: 4_104_700 },
  { symbol: 'VIC', name: 'Vingroup', sector: 'Real estate', price: 44.15, change: -0.11, volume: 1_530_100 },
  { symbol: 'GAS', name: 'PV Gas', sector: 'Energy', price: 71.8, change: 0.3, volume: 645_800 },
  { symbol: 'MSN', name: 'Masan', sector: 'Consumer', price: 76.2, change: 2.05, volume: 1_120_300 },
  { symbol: 'TCB', name: 'Techcombank', sector: 'Financials', price: 23.9, change: 0.84, volume: 5_870_000 },
  { symbol: 'VHM', name: 'Vinhomes', sector: 'Real estate', price: 41.6, change: -0.72, volume: 2_904_600 },
  { symbol: 'POW', name: 'PV Power', sector: 'Energy', price: 12.25, change: 1.66, volume: 6_315_200 },
];

/** A fresh copy of the quotes, so one example's edits never reach another. */
export function quotes(): Quote[] {
  return BASE.map((q, i) => ({ id: i + 1, ...q }));
}
```

## Formats

`locale` is a BCP 47 tag (`'vi-VN'`, `'de-DE'`, `'ja-JP'`). It sets the default for the built-in `price`, `date`, `currency` and `relative` formatting, the selection's totals bar and the pager's row count. A column's own `locale` wins over the grid's:

```svelte
<Grid {rows} {columns} height={480} locale="vi-VN" />
```

```ts
{ type: 'currency', key: 'cost', header: 'Cost', currency: 'JPY', locale: 'ja-JP' }
```

Without `locale`, columns format in `en-US` and the grid's own counts use the browser's locale.

## Labels

Pass only the strings you change; they are merged over the English defaults:

```svelte
<Grid
  {rows}
  {columns}
  height={480}
  labels={{
    autosize: 'Vừa nội dung',
    noRows: 'Không có dòng nào khớp',
    filterFor: (h) => `Lọc cột ${h}`,
    pageOf: (p, n, total, locale) => `Trang ${p} / ${n} · ${total.toLocaleString(locale)} dòng`,
  }}
/>
```

Labels with values in them are functions rather than strings with placeholders, so a translation can put the parts in any order. `DEFAULT_LABELS` holds every key with its English text, a good starting point for a full translation, and the `GridLabels` type lists them for your editor:

```ts
import { DEFAULT_LABELS, type GridLabels } from 'bo-grid';

export const vi: Partial<GridLabels> = {
  apply: 'Áp dụng',
  clear: 'Xóa',
  // …
};
```

Accessible names are labels too (`selectRow`, `columnMenu`, `resizeColumn`, `rowNumber` and others), so a translated grid also speaks the reader's language to a screen reader.

## Reference

- `locale`: `string` (default `undefined`) — BCP 47 locale for the grid's own number formatting (aggregation bar, pager row count), and the default for each column's `locale`. Unset, the runtime's locale.
- `labels`: `Partial<GridLabels>` (default `{}`) — Override any string the grid renders itself (menus, filter editor, pager, aria labels). Merged over English defaults — pass only what changes. Interpolated entries are functions so translations can reorder the parts. Resolved per grid.

  ```svelte
  <Grid {rows} {columns} height={480} labels={{ noRows: 'Không có dữ liệu', sortAscending: 'Tăng dần' }} />
  ```

- `emptyMessage`: `string` (default `labels.noRows`) — Message shown when there are no rows.

- `locale`: `string` (default `undefined`) — BCP 47 locale for this column's built-in formatting (`price`, `date`, `currency`, `relative`). Unset, the grid's `locale`, then `en-US`.

---
Page: https://bonguynvan.github.io/bo-grid/docs/localization/ · All pages: https://bonguynvan.github.io/bo-grid/llms.txt
