---
title: Localization Provider
subtitle: Defines the locale to use in the temporal components.
description: A localization provider component that defines the locale to use in the temporal components.
---

# Localization Provider

A localization provider component that defines the locale to use in the temporal components.

## Demo

### CSS Modules

This example shows how to implement the component using CSS Modules.

```tsx
/* index.tsx */
'use client';
import * as React from 'react';
import { format } from 'date-fns/format';
import { fr } from 'date-fns/locale/fr';
import { LocalizationProvider } from '@base-ui/react/localization-provider';
import { Calendar } from '@base-ui/react/calendar';
import { ChevronLeft, ChevronRight } from 'lucide-react';
import styles from './calendar.module.css';

export default function ExampleCalendar() {
  return (
    <LocalizationProvider temporalLocale={fr}>
      <MyCalendar />
    </LocalizationProvider>
  );
}

function MyCalendar() {
  return (
    <Calendar.Root className={styles.Root}>
      {({ visibleDate }) => (
        <React.Fragment>
          <header className={styles.Header}>
            <Calendar.DecrementMonth className={styles.DecrementMonth}>
              <ChevronLeft />
            </Calendar.DecrementMonth>
            <span className={styles.HeaderLabel}>
              {format(visibleDate, 'MMMM yyyy', { locale: fr })}
            </span>
            <Calendar.IncrementMonth className={styles.IncrementMonth}>
              <ChevronRight />
            </Calendar.IncrementMonth>
          </header>
          <Calendar.DayGrid className={styles.DayGrid}>
            <Calendar.DayGridHeader className={styles.DayGridHeader}>
              <Calendar.DayGridHeaderRow className={styles.DayGridHeaderRow}>
                {(day) => (
                  <Calendar.DayGridHeaderCell
                    value={day}
                    key={day.getTime()}
                    className={styles.DayGridHeaderCell}
                  />
                )}
              </Calendar.DayGridHeaderRow>
            </Calendar.DayGridHeader>
            <Calendar.DayGridBody className={styles.DayGridBody}>
              {(week) => (
                <Calendar.DayGridRow
                  value={week}
                  key={week.getTime()}
                  className={styles.DayGridRow}
                >
                  {(day) => (
                    <Calendar.DayGridCell
                      value={day}
                      key={day.getTime()}
                      className={styles.DayGridCell}
                    >
                      <Calendar.DayButton className={styles.DayButton} />
                    </Calendar.DayGridCell>
                  )}
                </Calendar.DayGridRow>
              )}
            </Calendar.DayGridBody>
          </Calendar.DayGrid>
        </React.Fragment>
      )}
    </Calendar.Root>
  );
}
```

```css
/* calendar.module.css */
.Root {
  border: 1px solid var(--calendar-root-border-color);
  border-radius: 8px;
  height: 312px;
  display: flex;
  flex-direction: column;

  --calendar-root-color: var(--color-gray-900);
  --calendar-root-border-color: var(--color-gray-500);
  --calendar-button-hover-bg-color: #e0f2fe;
  --calendar-button-focus-border-color: #0ea5e9;
  --calendar-day-grid-separator-bg-color: #9ca3af;
  --calendar-day-grid-header-color: var(--color-gray-500);

  --calendar-cell-selected-bg-color: #7dd3fc;
  --calendar-cell-outside-month-color: var(--color-gray-400);
  --calendar-cell-disabled-color: var(--color-gray-500);
  --calendar-cell-current-border-color: var(--color-gray-500);
  --calendar-cell-unavailable-color: #f87171;

  @media (prefers-color-scheme: dark) {
    --calendar-button-hover-bg-color: #075985;
    --calendar-cell-selected-bg-color: #0369a1;
  }
}

.Header {
  box-sizing: border-box;
  padding: 8px 12px;
  height: 40px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.HeaderLabel {
  color: var(--calendar-root-color);
}

.DecrementMonth,
.IncrementMonth {
  border: none;
  user-select: none;
  background-color: transparent;
  border-radius: 4px;
  color: var(--calendar-root-color);
  margin: 0 6px;
  padding: 0;
  display: flex;

  &:hover {
    background-color: var(--calendar-button-hover-bg-color);
  }

  &:focus-visible {
    outline: 2px solid var(--calendar-button-focus-border-color);
  }

  &[data-disabled] {
    pointer-events: none;
    color: var(--calendar-cell-disabled-color);
  }
}

.DayGrid {
  padding: 12px;
  height: 276px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  z-index: 1;
  position: relative;
}

.DayGridBody {
  display: flex;
  flex-direction: column;
  row-gap: 2px;
}

.DayGridRow,
.DayGridHeaderRow {
  display: flex;
  justify-content: center;
}

.DayGridHeaderCell {
  width: 36px;
  text-align: center;
  font-size: 0.75rem;
  color: var(--calendar-day-grid-header-color);
  font-weight: 500;
  padding: 0;
}

.DayGridCell {
  padding: 0;
}

.DayButton {
  background: none;
  padding: 0;
  font: inherit;
  height: 36px;
  width: 36px;
  position: relative;
  user-select: none;
  border: none;
  background-color: transparent;
  outline: none;
  box-sizing: border-box;
  border-radius: 4px;
  color: var(--calendar-root-color);

  &::before {
    content: '';
    position: absolute;
    inset: 2px;
    border-radius: 4px;
    border: none;
    z-index: -1;
    background-color: transparent;
  }

  &::after {
    content: '';
    border-radius: 4px;
    position: absolute;
    inset: 2px;
  }

  &:not([data-outside-month]):focus-visible {
    &::after {
      outline: 2px solid var(--calendar-button-focus-border-color);
    }
  }

  &:not([data-selected]):hover::before {
    background-color: var(--calendar-button-hover-bg-color);
  }

  &[data-selected]:not([data-outside-month])::before {
    background-color: var(--calendar-cell-selected-bg-color);
  }

  &[data-disabled] {
    pointer-events: none;
  }

  &:not([data-outside-month])[data-disabled] {
    color: var(--calendar-cell-disabled-color);
  }

  &:not([data-outside-month])[data-invalid] {
    text-decoration: line-through;
  }

  &[data-outside-month] {
    color: var(--calendar-cell-outside-month-color);
    pointer-events: none;
  }

  &[data-current]:not([data-selected], :focus-visible)::after {
    outline: 1px solid var(--calendar-cell-current-border-color);
  }

  &:not([data-disabled], [data-outside-month])[data-unavailable] {
    text-decoration: line-through;
    color: var(--calendar-cell-unavailable-color);
  }
}
```

## Anatomy

Import the component plus the `date-fns` library locale and wrap them around your app.

If every temporal component in your app shares the same locale, you should use the provider once at the root of your application.

```jsx title="Anatomy"
import { fr } from 'date-fns/locale/fr';
import { LocalizationProvider } from '@base-ui/react/localization-provider';

<LocalizationProvider temporalLocale={fr}>
  {/* Your app or a group of components */}
</LocalizationProvider>;
```

## Examples

### Nesting locales

The `<LocalizationProvider>` can be nested to change the locale for a part of the application.

This could be useful when you need some temporal components in your application to use a different locale than the rest of your app.

## Demo

### CSS Modules

This example shows how to implement the component using CSS Modules.

```css
/* index.module.css */
.Wrapper {
  display: flex;
  flex-flow: row wrap;
  gap: 24px;
  justify-content: center;
}
```

```tsx
/* index.tsx */
'use client';
import * as React from 'react';
import { format } from 'date-fns/format';
import { fr, zhCN } from 'date-fns/locale';
import { LocalizationProvider, useTemporalLocale } from '@base-ui/react/localization-provider';
import { Calendar } from '@base-ui/react/calendar';
import { ChevronLeft, ChevronRight } from 'lucide-react';
import styles from './calendar.module.css';
import indexStyles from './index.module.css';

export default function NestedLocalizedCalendars() {
  return (
    <div className={indexStyles.Wrapper}>
      <LocalizationProvider temporalLocale={fr}>
        <LocalizedCalendar />
        <LocalizationProvider temporalLocale={zhCN}>
          <LocalizedCalendar />
        </LocalizationProvider>
      </LocalizationProvider>
    </div>
  );
}

function LocalizedCalendar() {
  const locale = useTemporalLocale();
  return (
    <Calendar.Root className={styles.Root}>
      {({ visibleDate }) => (
        <React.Fragment>
          <header className={styles.Header}>
            <Calendar.DecrementMonth className={styles.DecrementMonth}>
              <ChevronLeft />
            </Calendar.DecrementMonth>
            <span className={styles.HeaderLabel}>
              {format(visibleDate, 'MMMM yyyy', { locale })}
            </span>
            <Calendar.IncrementMonth className={styles.IncrementMonth}>
              <ChevronRight />
            </Calendar.IncrementMonth>
          </header>
          <Calendar.DayGrid className={styles.DayGrid}>
            <Calendar.DayGridHeader className={styles.DayGridHeader}>
              <Calendar.DayGridHeaderRow className={styles.DayGridHeaderRow}>
                {(day) => (
                  <Calendar.DayGridHeaderCell
                    value={day}
                    key={day.getTime()}
                    className={styles.DayGridHeaderCell}
                  />
                )}
              </Calendar.DayGridHeaderRow>
            </Calendar.DayGridHeader>
            <Calendar.DayGridBody className={styles.DayGridBody}>
              {(week) => (
                <Calendar.DayGridRow
                  value={week}
                  key={week.getTime()}
                  className={styles.DayGridRow}
                >
                  {(day) => (
                    <Calendar.DayGridCell
                      value={day}
                      key={day.getTime()}
                      className={styles.DayGridCell}
                    >
                      <Calendar.DayButton className={styles.DayButton} />
                    </Calendar.DayGridCell>
                  )}
                </Calendar.DayGridRow>
              )}
            </Calendar.DayGridBody>
          </Calendar.DayGrid>
        </React.Fragment>
      )}
    </Calendar.Root>
  );
}
```

```css
/* calendar.module.css */
.Root {
  border: 1px solid var(--calendar-root-border-color);
  border-radius: 8px;
  height: 312px;
  display: flex;
  flex-direction: column;

  --calendar-root-color: var(--color-gray-900);
  --calendar-root-border-color: var(--color-gray-500);
  --calendar-button-hover-bg-color: #e0f2fe;
  --calendar-button-focus-border-color: #0ea5e9;
  --calendar-day-grid-separator-bg-color: #9ca3af;
  --calendar-day-grid-header-color: var(--color-gray-500);

  --calendar-cell-selected-bg-color: #7dd3fc;
  --calendar-cell-outside-month-color: var(--color-gray-400);
  --calendar-cell-disabled-color: var(--color-gray-500);
  --calendar-cell-current-border-color: var(--color-gray-500);
  --calendar-cell-unavailable-color: #f87171;

  @media (prefers-color-scheme: dark) {
    --calendar-button-hover-bg-color: #075985;
    --calendar-cell-selected-bg-color: #0369a1;
  }
}

.Header {
  box-sizing: border-box;
  padding: 8px 12px;
  height: 40px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.HeaderLabel {
  color: var(--calendar-root-color);
}

.DecrementMonth,
.IncrementMonth {
  border: none;
  user-select: none;
  background-color: transparent;
  border-radius: 4px;
  color: var(--calendar-root-color);
  margin: 0 6px;
  padding: 0;
  display: flex;

  &:hover {
    background-color: var(--calendar-button-hover-bg-color);
  }

  &:focus-visible {
    outline: 2px solid var(--calendar-button-focus-border-color);
  }

  &[data-disabled] {
    pointer-events: none;
    color: var(--calendar-cell-disabled-color);
  }
}

.DayGrid {
  padding: 12px;
  height: 276px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  z-index: 1;
  position: relative;
}

.DayGridBody {
  display: flex;
  flex-direction: column;
  row-gap: 2px;
}

.DayGridRow,
.DayGridHeaderRow {
  display: flex;
  justify-content: center;
}

.DayGridHeaderCell {
  width: 36px;
  text-align: center;
  font-size: 0.75rem;
  color: var(--calendar-day-grid-header-color);
  font-weight: 500;
  padding: 0;
}

.DayGridCell {
  padding: 0;
}

.DayButton {
  background: none;
  padding: 0;
  font: inherit;
  height: 36px;
  width: 36px;
  position: relative;
  user-select: none;
  border: none;
  background-color: transparent;
  outline: none;
  box-sizing: border-box;
  border-radius: 4px;
  color: var(--calendar-root-color);

  &::before {
    content: '';
    position: absolute;
    inset: 2px;
    border-radius: 4px;
    border: none;
    z-index: -1;
    background-color: transparent;
  }

  &::after {
    content: '';
    border-radius: 4px;
    position: absolute;
    inset: 2px;
  }

  &:not([data-outside-month]):focus-visible {
    &::after {
      outline: 2px solid var(--calendar-button-focus-border-color);
    }
  }

  &:not([data-selected]):hover::before {
    background-color: var(--calendar-button-hover-bg-color);
  }

  &[data-selected]:not([data-outside-month])::before {
    background-color: var(--calendar-cell-selected-bg-color);
  }

  &[data-disabled] {
    pointer-events: none;
  }

  &:not([data-outside-month])[data-disabled] {
    color: var(--calendar-cell-disabled-color);
  }

  &:not([data-outside-month])[data-invalid] {
    text-decoration: line-through;
  }

  &[data-outside-month] {
    color: var(--calendar-cell-outside-month-color);
    pointer-events: none;
  }

  &[data-current]:not([data-selected], :focus-visible)::after {
    outline: 1px solid var(--calendar-cell-current-border-color);
  }

  &:not([data-disabled], [data-outside-month])[data-unavailable] {
    text-decoration: line-through;
    color: var(--calendar-cell-unavailable-color);
  }
}
```

### Start of week

Start of the week is handled by the date library locale. You can override the default start of the week by spreading the locale and setting `options.weekStartsOn` to a value between `0` (Sunday) and `6` (Saturday).

## Demo

### CSS Modules

This example shows how to implement the component using CSS Modules.

```css
/* index.module.css */
.Wrapper {
  display: flex;
  flex-flow: column wrap;
  gap: 16px;
}

.Label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 0.875rem;
  color: var(--color-gray-900);
}

.Select {
  box-sizing: border-box;
  height: 2rem;
  padding-inline: 0.5rem;
  border: 1px solid var(--color-gray-200);
  border-radius: 0.375rem;
  background-color: canvas;
  font-family: inherit;
  font-size: 0.875rem;
  color: var(--color-gray-900);
}
```

```tsx
/* index.tsx */
'use client';
import * as React from 'react';
import { format } from 'date-fns/format';
import { enUS } from 'date-fns/locale/en-US';
import type { Day } from 'date-fns';
import { LocalizationProvider } from '@base-ui/react/localization-provider';
import { Calendar } from '@base-ui/react/calendar';
import { ChevronLeft, ChevronRight } from 'lucide-react';
import styles from './calendar.module.css';
import indexStyles from './index.module.css';

const dayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];

export default function StartOfWeekCalendar() {
  const [weekStartsOn, setWeekStartsOn] = React.useState<Day>(1);
  const locale = React.useMemo(
    () => ({ ...enUS, options: { ...enUS.options, weekStartsOn } }),
    [weekStartsOn],
  );

  return (
    <div className={indexStyles.Wrapper}>
      <label className={indexStyles.Label}>
        First day of the week
        <select
          className={indexStyles.Select}
          value={weekStartsOn}
          onChange={(event) => setWeekStartsOn(Number(event.target.value) as Day)}
        >
          {dayNames.map((day, index) => (
            <option key={day} value={index}>
              {day}
            </option>
          ))}
        </select>
      </label>
      <LocalizationProvider temporalLocale={locale}>
        <Calendar.Root className={styles.Root}>
          {({ visibleDate }) => (
            <React.Fragment>
              <header className={styles.Header}>
                <Calendar.DecrementMonth className={styles.DecrementMonth}>
                  <ChevronLeft />
                </Calendar.DecrementMonth>
                <span className={styles.HeaderLabel}>{format(visibleDate, 'MMMM yyyy')}</span>
                <Calendar.IncrementMonth className={styles.IncrementMonth}>
                  <ChevronRight />
                </Calendar.IncrementMonth>
              </header>
              <Calendar.DayGrid className={styles.DayGrid}>
                <Calendar.DayGridHeader className={styles.DayGridHeader}>
                  <Calendar.DayGridHeaderRow className={styles.DayGridHeaderRow}>
                    {(day) => (
                      <Calendar.DayGridHeaderCell
                        value={day}
                        key={day.getTime()}
                        className={styles.DayGridHeaderCell}
                      />
                    )}
                  </Calendar.DayGridHeaderRow>
                </Calendar.DayGridHeader>
                <Calendar.DayGridBody className={styles.DayGridBody}>
                  {(week) => (
                    <Calendar.DayGridRow
                      value={week}
                      key={week.getTime()}
                      className={styles.DayGridRow}
                    >
                      {(day) => (
                        <Calendar.DayGridCell
                          value={day}
                          key={day.getTime()}
                          className={styles.DayGridCell}
                        >
                          <Calendar.DayButton className={styles.DayButton} />
                        </Calendar.DayGridCell>
                      )}
                    </Calendar.DayGridRow>
                  )}
                </Calendar.DayGridBody>
              </Calendar.DayGrid>
            </React.Fragment>
          )}
        </Calendar.Root>
      </LocalizationProvider>
    </div>
  );
}
```

```css
/* calendar.module.css */
.Root {
  border: 1px solid var(--calendar-root-border-color);
  border-radius: 8px;
  height: 312px;
  display: flex;
  flex-direction: column;

  --calendar-root-color: var(--color-gray-900);
  --calendar-root-border-color: var(--color-gray-500);
  --calendar-button-hover-bg-color: #e0f2fe;
  --calendar-button-focus-border-color: #0ea5e9;
  --calendar-day-grid-separator-bg-color: #9ca3af;
  --calendar-day-grid-header-color: var(--color-gray-500);

  --calendar-cell-selected-bg-color: #7dd3fc;
  --calendar-cell-outside-month-color: var(--color-gray-400);
  --calendar-cell-disabled-color: var(--color-gray-500);
  --calendar-cell-current-border-color: var(--color-gray-500);
  --calendar-cell-unavailable-color: #f87171;

  @media (prefers-color-scheme: dark) {
    --calendar-button-hover-bg-color: #075985;
    --calendar-cell-selected-bg-color: #0369a1;
  }
}

.Header {
  box-sizing: border-box;
  padding: 8px 12px;
  height: 40px;
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.HeaderLabel {
  color: var(--calendar-root-color);
}

.DecrementMonth,
.IncrementMonth {
  border: none;
  user-select: none;
  background-color: transparent;
  border-radius: 4px;
  color: var(--calendar-root-color);
  margin: 0 6px;
  padding: 0;
  display: flex;

  &:hover {
    background-color: var(--calendar-button-hover-bg-color);
  }

  &:focus-visible {
    outline: 2px solid var(--calendar-button-focus-border-color);
  }

  &[data-disabled] {
    pointer-events: none;
    color: var(--calendar-cell-disabled-color);
  }
}

.DayGrid {
  padding: 12px;
  height: 276px;
  display: flex;
  flex-direction: column;
  gap: 4px;
  z-index: 1;
  position: relative;
}

.DayGridBody {
  display: flex;
  flex-direction: column;
  row-gap: 2px;
}

.DayGridRow,
.DayGridHeaderRow {
  display: flex;
  justify-content: center;
}

.DayGridHeaderCell {
  width: 36px;
  text-align: center;
  font-size: 0.75rem;
  color: var(--calendar-day-grid-header-color);
  font-weight: 500;
  padding: 0;
}

.DayGridCell {
  padding: 0;
}

.DayButton {
  background: none;
  padding: 0;
  font: inherit;
  height: 36px;
  width: 36px;
  position: relative;
  user-select: none;
  border: none;
  background-color: transparent;
  outline: none;
  box-sizing: border-box;
  border-radius: 4px;
  color: var(--calendar-root-color);

  &::before {
    content: '';
    position: absolute;
    inset: 2px;
    border-radius: 4px;
    border: none;
    z-index: -1;
    background-color: transparent;
  }

  &::after {
    content: '';
    border-radius: 4px;
    position: absolute;
    inset: 2px;
  }

  &:not([data-outside-month]):focus-visible {
    &::after {
      outline: 2px solid var(--calendar-button-focus-border-color);
    }
  }

  &:not([data-selected]):hover::before {
    background-color: var(--calendar-button-hover-bg-color);
  }

  &[data-selected]:not([data-outside-month])::before {
    background-color: var(--calendar-cell-selected-bg-color);
  }

  &[data-disabled] {
    pointer-events: none;
  }

  &:not([data-outside-month])[data-disabled] {
    color: var(--calendar-cell-disabled-color);
  }

  &:not([data-outside-month])[data-invalid] {
    text-decoration: line-through;
  }

  &[data-outside-month] {
    color: var(--calendar-cell-outside-month-color);
    pointer-events: none;
  }

  &[data-current]:not([data-selected], :focus-visible)::after {
    outline: 1px solid var(--calendar-cell-current-border-color);
  }

  &:not([data-disabled], [data-outside-month])[data-unavailable] {
    text-decoration: line-through;
    color: var(--calendar-cell-unavailable-color);
  }
}
```

## API reference

Defines the temporal locale provider for Base UI temporal components.Doesn't render its own HTML element.

**LocalizationProvider Props:**

| Prop           | Type        | Default | Description                               |
| :------------- | :---------- | :------ | :---------------------------------------- |
| temporalLocale | `Locale`    | `en-US` | The locale to use in temporal components. |
| children       | `ReactNode` | -       | -                                         |
