i18n-rtl
MUI internationalization, RTL support, locale customization, and bidirectional text
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',
tooRelated in General
modeling-omnistudio-epc-catalog
IncludedSalesforce Industries CME EPC product-modeling skill for Product2-based catalog creation. Use when creating EPC products, configuring product attributes, building offer bundles with Product Child Items, or reviewing EPC DataPack JSON metadata for product catalog changes. TRIGGER when: user creates or updates Product2 EPC records, AttributeAssignment payloads, AttributeMetadata/AttributeDefaultValues, Offer bundles, or ProductChildItem relationships. DO NOT TRIGGER when: designing OmniScripts/FlexCards/Integration Procedures (use building-omnistudio-omniscript, building-omnistudio-flexcard, or building-omnistudio-integration-procedure), implementing Apex business logic (use generating-apex), or troubleshooting deployment pipelines (use deploying-metadata).
relationship-science-coach
IncludedUse this skill for direct, practical adult relationship coaching: couples conflict, repair, trust, marriage, dating, flirting, attachment patterns, emotional connection, sex, desire differences, eroticism, kink negotiation, affection, love languages, breakups, and long-term passion. Draw on Gottman, EFT and Hold Me Tight, attachment science, modern sex research, Perel, Nagoski, Kerner, Schnarch, Love and Stosny, and flexible love-language tools. Be concrete and low-hedge. Redirect only for imminent danger, abuse, coercive control, minors, non-consent, self-harm, stalking, or medical/legal/psychiatric decisions.
building-sf-integrations
IncludedSalesforce integration architecture and runtime plumbing with 120-point scoring. Use this skill to set up Named Credentials, External Credentials, External Services, REST/SOAP callout patterns, Platform Events, and Change Data Capture. TRIGGER when: user sets up Named Credentials, External Services, REST/SOAP callouts, Platform Events, CDC, or touches .namedCredential-meta.xml files. DO NOT TRIGGER when: Connected App/OAuth config (use configuring-connected-apps), Apex-only logic (use generating-apex), or data import/export (use handling-sf-data).
venue-templates
IncludedAccess comprehensive LaTeX templates, formatting requirements, and submission guidelines for major scientific publication venues (Nature, Science, PLOS, IEEE, ACM), academic conferences (NeurIPS, ICML, CVPR, CHI), research posters, and grant proposals (NSF, NIH, DOE, DARPA). This skill should be used when preparing manuscripts for journal submission, conference papers, research posters, or grant proposals and need venue-specific formatting requirements and templates.
let-fate-decide
IncludedDraws the 12 Houses of the Zodiac Tarot spread to inject entropy into planning when prompts are vague, ambiguous, or casually delegated. Interprets the spread to guide next steps. Use when the user says 'let fate decide', 'YOLO', 'whatever', 'idk', or other nonchalant phrases, makes Yu-Gi-Oh references, or when you are about to arbitrarily pick between multiple reasonable approaches. Prefer over ask-questions-if-underspecified when the user's tone is casual or playful rather than precision-seeking.
net-ops
IncludedCross-platform network troubleshooting (Windows, macOS, Linux) via local or remote shell. Use for: DNS broken, can't resolve hostnames, nslookup/dig works but apps fail, NRPT, WFP, scutil, /etc/resolver, systemd-resolved, /etc/resolv.conf, NetworkManager, VPN DNS leak residue (ProtonVPN/Mullvad/WireGuard/AnyConnect), AV/firewall blocking DNS or DoH, Tailscale DNS interaction, intermittent connectivity, remote diagnostics over SSH.