@k2b/ui
Locale and formatting
Inherited render locale with unstyled semantic number, currency, and date formatters.
One inherited render locale for unstyled semantic formatters. The German block wraps the same values in a LocaleProvider; date and time components take an explicit timezone and default to UTC.
Effective locale:
1,234,567.89 · €1,999.50 · 42% · 1.5 KiB
· ·
Effective locale:
1.234.567,89 · 1.999,50 € · 42% · 1,5 KiB
· ·
TSX
Copy<LocaleProvider locale="de"> <Format.Currency value={1999.5} currency="EUR" /> <Format.DateTime value={order.createdAt} timeZone="Europe/Berlin" /> <Format.RelativeTime value={order.updatedAt} /></LocaleProvider>LocaleProvider, useLocale(), and the unstyled Format namespace make @k2b/ui components render numbers, currencies, and dates in one coherent locale without prop-drilling. Locale selection, user preferences, and message catalogs stay application-owned.
Use LocaleProvider and Format
Use Format components wherever a value is displayed rather than edited: statistics, tables, timestamps, file sizes, and durations. They render semantic, unstyled elements, so the surrounding surface owns all styling.
Use LocaleProvider once near the SSR root to set the render locale. Use useLocale() in application components that need the effective locale for their own Intl calls.
Keep locale and timezone separate: the provider carries only the locale; date and time components take an explicit timeZone prop where it matters.
Import
import {
Format,
LocaleProvider,
useLocale,
type FormatCurrencyProps,
type LocaleProviderProps,
} from "@k2b/ui";Locale resolution
Every locale-aware component resolves its locale in the same order:
- an explicit component
localeprop, - the nearest
LocaleProvider, - the browser's
document.documentElement.lang, - the deterministic default
"en".
On the server the provider is the only source, so SSR consumers wrap the page in LocaleProvider and emit a matching <html lang>. A browser island is an independent Solid root: an outer server-side provider does not survive the island's re-render, which falls back to <html lang> instead. Keeping both equal keeps server and browser text identical. Changing the language without a document reload is out of scope; update the preference and reload.
NumberInput, DatePicker, and Calendar inherit the same locale: the pickers prefer an explicit dateConfig.locale, and NumberInput derives its decimal separator from the effective locale while keeping its numeric value contract unchanged.
Formatters
Format.Number— grouped number, optionalcompactsuffixes and fixeddecimals.Format.Percent— ratio input (0.12renders12%), optionalclamp.Format.Currency— requires an ISO 4217currencycode.Format.Bytes— IEC units by default,mode="si"for decimal units.Format.Date,Format.Time,Format.DateTime— render<time>with a canonicaldatetimeattribute; format in UTC unless an explicittimeZoneis given, so server and browser never disagree.Format.RelativeTime— relative wording with an optional deterministicbase.Format.Duration— human-readable span betweenfromandto.Format.DurationMs— compact duration from milliseconds.
Numeric components render a <span>; temporal components render <time>. Null and invalid input renders the fallback text (default "—") in a <span>. Native attributes pass through to the rendered element.
Accessibility
Temporal components expose the machine-readable instant through the <time datetime> attribute. The visible text is plain content, so screen readers announce the localized value directly. Fallback output is text, never an empty element.
Runtime
All formatting runs through Intl and published @k2b/stdlib helpers; no translations ship with the package and no global state is mutated. The provider is request-local, so one server can render different locales concurrently.
Example
<LocaleProvider locale={requestLocale}>
<p>
<Format.Currency value={1999.5} currency="EUR" /> ·{" "}
<Format.DateTime value={order.createdAt} timeZone="Europe/Berlin" /> ·{" "}
<Format.RelativeTime value={order.updatedAt} />
</p>
</LocaleProvider>