gridcn1.2.2

I18n & RTL

Every string through typed labels, with per-locale direction (English, Deutsch, and Arabic in one grid).

The demo carries three locales: English, Deutsch, and Arabic. Each locale brings its strings and its text direction: labels, column headers, and hint text translate through deep-merged labels overrides, and the Arabic locale flips the grid to RTL through the direction prop. Pick a language and the direction follows it.

Pick a language — direction follows it.
Name
Email
Role
Age
Silent Tiger
user0@example.com
Viewer
63
Quick Lion
user1@example.com
Viewer
67
Swift Wolf
user2@example.com
Manager
40
Eager Lion
user3@example.com
User
50
Eager Tiger
user4@example.com
Viewer
45
Silent Wolf
user5@example.com
User
24
Swift Lion
user6@example.com
Viewer
34
Eager Lion
user7@example.com
Manager
21
Eager Eagle
user8@example.com
Editor
25
Bold Tiger
user9@example.com
Editor
19
pnpm dlx shadcn@latest add @gridcn/data-grid-i18n-demo

The labels prop

Every user-facing string lives in one typed DataGridLabels object with English defaults. Pass a partial override to DataGridProvider (or DataGrid). It deep-merges over DEFAULT_LABELS. Only the keys you specify change:

<DataGridProvider
  labels={{
    toolbar: { searchPlaceholder: "Rechercher…" },
    contextMenu: { copy: "Copier", paste: "Coller" },
  }}
  {...grid}
  columns={columns}
/>

Interpolated strings are functions that receive real arguments:

searchMatches: (current: number, total: number) => `${current}/${total}`,

RTL

Direction is layout state, not a string: derive it from the locale the way a real app does, and pass it to the root:

<DataGridRoot direction={locale.dir} /> // "ltr" | "rtl"

The grid's inline-axis math (scroll normalization, pointer-to-cell translation, arrow-key mirroring, pin zones) runs through the direction utilities, so RTL flips the interaction axis too: pinning, selection, and keyboard navigation follow it. Set dir on the wrapping element as well, so the surrounding page chrome matches.

Which i18n library?

gridcn takes plain strings, so it composes with whatever you already run. There is no adapter. next-intl and react-i18next both hand you typed strings per locale. The pattern is the same for either: keep one labels object per locale (or build it per locale in a hook) and pass it:

const { labels } = useTranslations("grid"); // next-intl
// or: const t = useTranslation().t; build the DeepPartialLabels from t("grid.*")

<DataGridProvider labels={labelsForLocale(locale)}>
  <DataGridRoot direction={dirForLocale(locale)} />
</DataGridProvider>;

The full merge model (which keys replace vs merge, function labels, DeepPartialLabels) is on the i18n guide, and the per-group coverage table is under Coverage by group.

  • I18n: the DataGridLabels reference and a full German example
  • Styling: appearance when the theme changes instead

On this page