Claude
Skills
Sign in
Back

i18n-rtl

Included with Lifetime
$97 forever

MUI internationalization, RTL support, locale customization, and bidirectional text

General

What this skill does


# MUI Internationalization & RTL Support

## 1. RTL Setup

Set the document direction and configure the MUI theme:

```tsx
// index.html — set dir on <html>
<html dir="rtl" lang="ar">

// theme.ts
import { createTheme } from '@mui/material/styles';

const rtlTheme = createTheme({
  direction: 'rtl',
});
```

Install the Emotion RTL plugin for automatic style flipping:

```bash
npm install stylis-plugin-rtl stylis
```

Wrap the app with the RTL-aware cache provider:

```tsx
import { CacheProvider } from '@emotion/react';
import createCache from '@emotion/cache';
import { ThemeProvider } from '@mui/material/styles';
import rtlPlugin from 'stylis-plugin-rtl';
import { prefixer } from 'stylis';

const cacheRtl = createCache({
  key: 'muirtl',
  stylisPlugins: [prefixer, rtlPlugin],
});

function App() {
  return (
    <CacheProvider value={cacheRtl}>
      <ThemeProvider theme={rtlTheme}>
        {/* All MUI components now render RTL */}
        <MyApplication />
      </ThemeProvider>
    </CacheProvider>
  );
}
```

## 2. Emotion RTL Cache

The RTL cache intercepts all Emotion-generated styles and flips directional properties (`margin-left` becomes `margin-right`, `padding-left` becomes `padding-right`, etc.).

```tsx
import createCache from '@emotion/cache';
import rtlPlugin from 'stylis-plugin-rtl';
import { prefixer } from 'stylis';

// RTL cache — use for Arabic, Hebrew, Persian, Urdu
const rtlCache = createCache({
  key: 'muirtl',
  stylisPlugins: [prefixer, rtlPlugin],
});

// LTR cache — use for English, French, German, etc.
const ltrCache = createCache({
  key: 'muiltr',
  stylisPlugins: [prefixer],
});
```

Key points:
- The `key` must be unique per cache instance (e.g. `'muirtl'` vs `'muiltr'`).
- `prefixer` adds vendor prefixes and should always be included.
- `rtlPlugin` must come after `prefixer` in the array.

## 3. Dynamic Direction Switching

Toggle between LTR and RTL at runtime using React state:

```tsx
import { useState, useMemo } from 'react';
import { createTheme, ThemeProvider } from '@mui/material/styles';
import { CacheProvider } from '@emotion/react';
import createCache from '@emotion/cache';
import rtlPlugin from 'stylis-plugin-rtl';
import { prefixer } from 'stylis';
import CssBaseline from '@mui/material/CssBaseline';
import IconButton from '@mui/material/IconButton';
import FormatTextdirectionLToRIcon from '@mui/icons-material/FormatTextdirectionLToR';
import FormatTextdirectionRToLIcon from '@mui/icons-material/FormatTextdirectionRToL';

const rtlCache = createCache({
  key: 'muirtl',
  stylisPlugins: [prefixer, rtlPlugin],
});

const ltrCache = createCache({
  key: 'muiltr',
  stylisPlugins: [prefixer],
});

function App() {
  const [direction, setDirection] = useState<'ltr' | 'rtl'>('ltr');

  const theme = useMemo(
    () => createTheme({ direction }),
    [direction],
  );

  const toggleDirection = () => {
    const newDir = direction === 'ltr' ? 'rtl' : 'ltr';
    setDirection(newDir);
    document.dir = newDir; // sync <html> dir attribute
  };

  return (
    <CacheProvider value={direction === 'rtl' ? rtlCache : ltrCache}>
      <ThemeProvider theme={theme}>
        <CssBaseline />
        <IconButton onClick={toggleDirection}>
          {direction === 'ltr'
            ? <FormatTextdirectionRToLIcon />
            : <FormatTextdirectionLToRIcon />}
        </IconButton>
        <MyApplication />
      </ThemeProvider>
    </CacheProvider>
  );
}
```

Important: always sync `document.dir` with the theme direction so native browser layout matches MUI.

## 4. Component Localization

MUI ships built-in locale strings for 50+ languages. Pass a locale object as the second argument to `createTheme`:

```tsx
import { createTheme } from '@mui/material/styles';
import { deDE } from '@mui/material/locale';

// German locale — translates MUI component strings
// (e.g. TablePagination "Rows per page" -> "Zeilen pro Seite")
const theme = createTheme(
  {
    palette: {
      primary: { main: '#1976d2' },
    },
  },
  deDE, // locale object as second argument
);
```

Common locale imports:

```tsx
import { enUS } from '@mui/material/locale'; // English (default)
import { frFR } from '@mui/material/locale'; // French
import { esES } from '@mui/material/locale'; // Spanish
import { jaJP } from '@mui/material/locale'; // Japanese
import { zhCN } from '@mui/material/locale'; // Chinese (Simplified)
import { arSA } from '@mui/material/locale'; // Arabic (Saudi Arabia)
import { heIL } from '@mui/material/locale'; // Hebrew (Israel)
import { koKR } from '@mui/material/locale'; // Korean
import { ptBR } from '@mui/material/locale'; // Portuguese (Brazil)
import { trTR } from '@mui/material/locale'; // Turkish
```

For RTL languages, combine direction with locale:

```tsx
import { arSA } from '@mui/material/locale';

const arabicTheme = createTheme(
  {
    direction: 'rtl',
    typography: {
      fontFamily: '"Noto Sans Arabic", "Roboto", sans-serif',
    },
  },
  arSA,
);
```

## 5. MUI X Localization

MUI X components (DataGrid, DatePicker, TreeView) have their own locale strings, imported separately:

```tsx
import { createTheme } from '@mui/material/styles';
import { deDE as coreDeDE } from '@mui/material/locale';
import { deDE as dataGridDeDE } from '@mui/x-data-grid/locales';
import { deDE as datePickerDeDE } from '@mui/x-date-pickers/locales';

// Combine core + DataGrid + DatePicker locales
const theme = createTheme(
  {
    palette: { primary: { main: '#1976d2' } },
  },
  dataGridDeDE,    // DataGrid locale
  datePickerDeDE,  // DatePicker locale
  coreDeDE,        // Core MUI locale (last to allow overrides)
);
```

DataGrid locale strings cover:

- Column menu labels (`columnMenuLabel`, `columnMenuSortAsc`, `columnMenuFilter`)
- Toolbar labels (`toolbarColumns`, `toolbarFilters`, `toolbarExport`)
- Pagination (`MuiTablePagination` labels)
- Filter panel labels (`filterPanelOperator`, `filterPanelColumns`, `filterPanelInputLabel`)
- No rows overlay (`noRowsLabel`, `noResultsOverlayLabel`)

DatePicker locale strings cover:

- Field placeholders and labels
- Calendar navigation (`previousMonth`, `nextMonth`)
- Toolbar labels (`datePickerToolbarTitle`, `timePickerToolbarTitle`)
- Action bar labels (`okButtonLabel`, `cancelButtonLabel`, `clearButtonLabel`)

## 6. Custom Locale

Override individual translation strings by deep-merging with a built-in locale:

```tsx
import { createTheme } from '@mui/material/styles';
import { enUS } from '@mui/material/locale';
import { enUS as dataGridEnUS } from '@mui/x-data-grid/locales';
import deepmerge from 'deepmerge';

// Custom locale: override specific DataGrid strings
const customDataGridLocale = deepmerge(dataGridEnUS, {
  components: {
    MuiDataGrid: {
      defaultProps: {
        localeText: {
          noRowsLabel: 'No records found',
          footerRowSelected: (count: number) =>
            count === 1
              ? '1 record selected'
              : `${count.toLocaleString()} records selected`,
          toolbarExport: 'Download',
          toolbarExportCSV: 'Download as CSV',
          toolbarExportPrint: 'Print view',
        },
      },
    },
  },
});

// Custom locale: override core MUI strings
const customCoreLocale = deepmerge(enUS, {
  components: {
    MuiTablePagination: {
      defaultProps: {
        labelRowsPerPage: 'Items per page:',
        labelDisplayedRows: ({ from, to, count }: { from: number; to: number; count: number }) =>
          `Showing ${from}-${to} of ${count !== -1 ? count : `more than ${to}`}`,
      },
    },
    MuiAlert: {
      defaultProps: {
        closeText: 'Dismiss',
      },
    },
  },
});

const theme = createTheme(
  { palette: { primary: { main: '#1976d2' } } },
  customDataGridLocale,
  customCoreLocale,
);
```

Per-component override (without theme-level locale):

```tsx
import { DataGrid } from '@mui/x-data-grid';

<DataGrid
  rows={rows}
  columns={columns}
  localeText={{
    noRowsLabel: 'Nothing here yet',
    too

Related in General