Locale Provider
betaGives the library the reader's locale, time zone and texts once per app, already translated.
@zenoxai/ui/components/locale-provider Markdownfunction LocaleProviderDemo() {
const [locale, setLocale] = React.useState("pt-BR")
// In an app these come from its dictionary, once, kept stable.
const labels = React.useMemo<LocaleLabels>(
() =>
locale === "pt-BR"
? {
pagination: {
previous: "Anterior",
next: "Próxima",
goToPrevious: "Ir para a página anterior",
goToNext: "Ir para a próxima página",
morePages: "Mais páginas",
},
numberInput: { decrease: "Diminuir", increase: "Aumentar" },
severityBadge: {
critical: "Crítica",
high: "Alta",
medium: "Média",
low: "Baixa",
unknown: "Desconhecida",
},
emptyValue: {
unknown: "Sem valor",
notApplicable: "Não se aplica",
redacted: "Oculto",
},
}
: {},
[locale]
)
return (
<div className="flex w-full max-w-md flex-col gap-6">
<ToggleGroup
variant="segmented"
size="sm"
value={[locale]}
onValueChange={(value) => {
if (value[0]) setLocale(value[0])
}}
aria-label="Locale"
>
<ToggleGroupItem value="en-US">en-US</ToggleGroupItem>
<ToggleGroupItem value="pt-BR">pt-BR</ToggleGroupItem>
</ToggleGroup>
<LocaleProvider locale={locale} labels={labels}>
<div className="flex flex-wrap items-center gap-4">
<SeverityBadge level="high" />
<EmptyValue reason="not-applicable" />
<NumberInput defaultValue={12040} ariaLabel="Events per day" />
</div>
<Pagination>
<PaginationContent>
<PaginationItem>
<PaginationPrevious href="#" />
</PaginationItem>
<PaginationItem>
<PaginationLink href="#" isActive>
1
</PaginationLink>
</PaginationItem>
<PaginationItem>
<PaginationEllipsis />
</PaginationItem>
<PaginationItem>
<PaginationNext href="#" />
</PaginationItem>
</PaginationContent>
</Pagination>
</LocaleProvider>
</div>
)
}Usage
import { LocaleProvider } from "@zenoxai/ui/components/locale-provider"
import { ptBR } from "react-day-picker/locale"
<LocaleProvider
locale="pt-BR"
timeZone="America/Sao_Paulo"
labels={labels}
dateLocale={ptBR}
>
<App />
<Toaster />
<ConfirmDialogHost />
</LocaleProvider>
Mount one at the root of the app, around the Toaster and the confirmation host too. It sets:
locale, a BCP 47 tag: the locale of every number the library formats, and the default of Number Input, Progress, Slider and the chart tooltip.timeZone, an IANA name, for the app’s own dates throughuseLocale().labels, the library’s own texts grouped by part, already translated. The app passes the results of its ownt(); the library ships no translations.dateLocale, the locale of the Calendar, fromreact-day-picker/locale, which also translates the calendar’s navigation.
Keep labels stable: build it once, in a module constant or a useMemo on the language. The
groups, their keys and how they fall back are on the Localization
page.
Without a provider every part shows its English default, as before.
Examples
Reading the locale in the app
useLocale() returns the provider’s locale and time zone, and the functions of
lib/format bound to them, for the app’s own text.
const { format } = useLocale()
format.number(1204) // "1.204"
format.dateTime(alert.detectedAt, { seconds: true }) // "27/10/2026 15:05:09"
Outside a provider it returns en-US and the runtime’s time zone, and never throws.
A different text in one part of the page
A provider inside another merges its labels into the parent’s, one group deep, and keeps the
parent’s locale. An instance’s own prop still wins over both.
<LocaleProvider labels={{ dataTable: { empty: "Nenhuma regra" } }}>
<DataTable table={rules} label="Regras" />
</LocaleProvider>
Accessibility
- Set
langon<html>to the same language, so screen readers choose the right voice. The provider renders no element. - The accessible names the library writes on its own (Close, Loading, Previous page) come from
labels. In development, a part that falls back to English under another locale logs a warning that names the missing key.
API reference
Generated from the TypeScript source. className, style and children are accepted everywhere and omitted below.
LocaleContext
No props of its own. Accepts the props of the element it renders.
DEFAULT_LOCALE
The locale of the library's own texts without a provider.
No props of its own. Accepts the props of the element it renders.
createLocaleFormatters
The formatters of a locale and a time zone.
No props of its own. Accepts the props of the element it renders.
useLocaleFormatters
The formatters for the nearest provider, or en-US without one.
| Prop | Type | Default |
|---|---|---|
dateLocale* | DayPickerLocale | undefined | - |
labels* | LocaleLabels | - |
locale* | string | undefinedThe provider's locale, or undefined when only labels were given. | - |
timeZone* | string | undefined | - |
LocaleProvider
LocaleProvider gives the library the reader's locale, time zone and texts, once per app, instead of passing them to every instance. Text still arrives already translated: the app passes the results of its own `t()`, and the library ships no translations.
| Prop | Type | Default |
|---|---|---|
dateLocale | DayPickerLocaleThe date-fns locale of the Calendar and of FilterDate's calendar. Pass the one from `react-day-picker/locale`, which also translates the calendar's navigation ("Ir para o próximo mês"). | - |
labels | LocaleLabelsThe library's texts, already translated, by part. Keep the object stable (a module constant or a useMemo): a new object renders every part again. | - |
locale | stringThe BCP 47 tag of the reader's language, such as `pt-BR`: the locale of every number and date the library formats, and the default `locale` of NumberInput, Progress, Slider, FilterNumberRange and Chart's tooltip. A nested provider that only changes labels can leave it out. | - |
timeZone | stringThe IANA name of the reader's time zone, such as `America/Sao_Paulo`. The library formats no zoned date of its own: useLocale hands it to the app, and useFilterDateToday reads it. Defaults to the runtime's zone. | - |
useLocale
useLocale returns the nearest LocaleProvider's locale and time zone, and the formatters bound to them, for an app's own text: `format.number(1204)`, `format.dateTime(alert.detectedAt, { seconds: true })`. Outside a provider it returns en-US and the runtime's time zone, and never throws.
No props of its own. Accepts the props of the element it renders.
useLocaleContext
The provider's locale, or undefined outside one; internal.
No props of its own. Accepts the props of the element it renders.
useLabels
useLabels returns a part's texts. The instance's `prop` wins over the provider's group, which wins over the `common` keys named in `fallbacks`, which win over the English `defaults`. Every function in the result gets the locale's formatters as its last argument, so a label function typed `(count: number, format: LocaleFormatters) => string` is called as `labels.x(count)`. Pass every argument before it, `undefined` included.
No props of its own. Accepts the props of the element it renders.