Skip to content
UI

Localization

How the library takes the reader's locale, time zone and texts, and which texts each part has.

The contract

The library has no translations, catalogs or keys. Text arrives already translated: through a prop on an instance, or once per app through Locale Provider. Its parts default to English, so an app without a provider renders exactly as before.

import { LocaleProvider, type LocaleLabels } from "@zenoxai/ui/components/locale-provider"

function useUiLabels(): LocaleLabels {
  const { t, language } = useTranslation()
  return React.useMemo(
    () => ({
      common: {
        close: t("ui.actions.close"),
        tryAgain: t("ui.actions.tryAgain"),
        copied: t("ui.feedback.copied"),
        loading: t("ui.feedback.loading"),
      },
      dataTable: {
        empty: t("ui.table.empty"),
        resultCount: (total, format) =>
          t("ui.table.results", { count: format.number(total) }),
      },
    }),
    [t, language]
  )
}

The provider also carries the locale of every number the library formats, so “1 to 25 of 1.204” follows pt-BR before any word is translated.

Precedence

A text comes from the first of these that has it:

  1. The instance’s prop: closeLabel, labels, text, an aria-label.
  2. The part’s group in the provider: dialog.close.
  3. common, for the keys whose English default is the same text in every part: close, tryAgain, copied, loading.
  4. The English default.

common.loading reaches the Spinner and the filter panel (“Loading”), not DataTable’s “Loading rows”, which has its own key.

Label functions

A text that holds a number or a name is a function. It gets the provider’s formatters as its last argument, the functions of lib/format bound to the locale and the time zone:

dataTable: {
  pageRange: (from, to, total, format) =>
    `${format.number(from)} a ${format.number(to)} de ${format.number(total)}`,
}

Plurals come from the app’s dictionary; format.plural(count, { one, other }) picks the form by the language’s rules.

Groups

A group exists in the LocaleLabels type once the app imports its part, so TypeScript checks every key. Every key is optional.

Group Part Keys
common Several close, tryAgain, copied, loading
dialog Dialog close
sheet Sheet close
command Command dialog title, description, close
pagination Pagination previous, next, goToPrevious, goToNext, morePages
breadcrumb Breadcrumb more
carousel Carousel previous, next
sidebar Sidebar title, description, toggle
combobox Combobox showOptions, clear, remove
numberInput Number Input decrease, increase
calendar Calendar today, selected; the navigation comes with dateLocale
filterChip Filter Chip remove()
toaster Toaster notifications, closeToast
dataTable Data Table, its column factories and cells loading, empty, errorTitle, errorDescription, retry, refreshFailed, loadMoreFailed, loadMore, loadingMore, rowsPerPage, previousPage, nextPage, pageRange(), loadedCount(), loadedMore(), resultCount(), selectAll, selectPage, selectRow(), actions, columns, moreTags()
filterPanel Filter Panel title, activeCount(), clear, reset, clearAll, resetAll, removeFilter(), removeValue(), selectedCount(), showMore(), showLess, search(), searchPlaceholder, noMatches, loading, countsFailed, retry, all, formatCount(), minimum, maximum, from, to, anyTime, anyDate, clearDate(), addValue, close, showResults()
filterValues useFilters, the text of the chips yes, no, more(), between(), atLeast(), atMost(), onOrAfter(), onOrBefore(), formatNumber(), formatDate()
recordSheet Record Sheet header previous, next, copy, copyLink, copied, close
externalLink External Link, Linkified Text title, description(), copy, copied, open, close, newTab
copyButton Copy Button, Value Actions copy, copied, pivot
codeBlock Code Block name
helpTooltip Help Tooltip moreInformation
emptyValue Empty Value, Stat Tile unknown, notApplicable, redacted
listErrorState List Error State title, description, retry
severityBadge Severity Badge critical, high, medium, low, unknown
confirm Confirm Dialog host and confirmDiscard() confirm, cancel, discardTitle, discardDescription, discard, keepEditing

Keys with () are functions. The English default of every key is in the part’s API reference.

Without a provider

Every part shows its English default, and the parts that took the runtime’s locale (Number Input, Progress, Slider, the chart tooltip) still do. The pagination and breadcrumb landmarks keep their English names in every language.

Missing texts

In development, a part that falls back to English under a locale other than English logs one warning per key and locale, naming the key to add: LocaleProvider: no "dataTable.empty" label for pt-BR. A complete set of labels renders no English and no warning.