Skip to main content
Version: v0.30.x

Internationalization & RTL

Every name the pickers display comes from the JavaScript Intl API for the locale you pass (or the device default), and every UI string is a prop.

What locale controls​

ComponentDerived from locale
Calendar / DatePickerMonth title, weekday names, first day of week, day accessibility labels
DateWheelPickerMonth names, column order (D/M/Y vs M/D/Y vs Y/M/D)
TimePicker / TimeRangePicker12h vs 24h, AM/PM labels
DateTimePickerThe day labels, plus the calendar and time as above
MonthPickerMonth names
CountryPicker / PhoneFieldCountry names, where the engine has them
CurrencyPicker / AmountFieldCurrency names, where the engine has them; AmountField's separators and symbol side ($1,234.50, 1.234,50 €)
TimeZonePickerTime zone names, where the engine has them
Loading…
<View style={{ gap: 12 }}>
  <Text style={{ fontWeight: '600' }}>he-IL</Text>
  <DatePicker value={d} onChange={setD} locale="he-IL" />
  <Text style={{ fontWeight: '600' }}>ar-EG</Text>
  <TimePicker value={t} onChange={setT} locale="ar-EG" />
</View>

Pass your app's language, for example from expo-localization or i18next:

import { getLocales } from 'expo-localization';
const locale = getLocales()[0]?.languageTag; // 'fr-CA'

<DatePicker locale={locale} … />

Hermes and Intl​

Hermes (the default engine) supports Intl.DateTimeFormat on iOS and Android. If a locale or feature is missing at runtime, every helper falls back to English names instead of throwing. firstDayOfWeek uses Intl.Locale week info where available; otherwise it defaults to Sunday, so pass firstDayOfWeek={1} explicitly if you need Monday everywhere.

Hermes can't list or name countries and time zones (Intl.DisplayNames, Intl.supportedValuesOf), so CountryPicker and TimeZonePicker ship their lists. Names show in the user's language where the engine provides them, and in English otherwise.

Translating UI strings​

ComponentString props (defaults)
Picker sheetsconfirmLabel (Done, OK in Material), cancelLabel (Cancel), title
SelectPickerplaceholder (Select…), label, sheetTitle, searchPlaceholder (Search), emptyText (No results)
SelectListsearchPlaceholder, emptyText, loadingText (Loading…), searchPrompt (Type to search)
CountryPickerplaceholder (Select a country), searchPlaceholder (Search countries), preferredLabel (Suggested), allCountriesLabel (All countries)
PhoneFieldlabel, countrySheetTitle (Country code)
CurrencyPickerplaceholder (Select a currency), searchPlaceholder (Search currencies), preferredLabel (Suggested), allCurrenciesLabel (All currencies)
AmountFieldlabel, currencySheetTitle (Currency)
TimeZonePickerplaceholder (Select a time zone), searchPlaceholder (Search time zones), preferredLabel (Your time zone), allTimeZonesLabel (All time zones)
EmojiPickersearchPlaceholder (Search emoji), emptyText (No emoji found), categoryLabels
TimePickerdayPeriodLabels (from the locale)
TimeRangePickerstartLabel (Start), endLabel (End)
DurationPickerlabels (h, min, s)
ColorPickerlabels: tab, slider and button names (Grid, Hue, Opacity, Copy…)
Calendar, WeekStripformatTitle
ActionSheetcancelLabel (Cancel)
SliderthumbLabels (Minimum, Maximum) for screen readers
OtpField, RatingaccessibilityLabel (Verification code, Rating)
const { t } = useTranslation();

<DatePickerSheet confirmLabel={t('done')} cancelLabel={t('cancel')} title={t('pickDate')} … />
<SelectPicker placeholder={t('select')} searchPlaceholder={t('search')} emptyText={t('noResults')} … />

Right-to-left​

All layouts use logical start / end properties, so they mirror automatically when I18nManager.isRTL is true:

  • Calendar arrows swap direction, and swipe direction follows.
  • The range band grows from the correct side.
  • Select check marks, icons and chips sit on the logical end / start.
  • Multi-wheel columns follow the row direction.

Enable RTL the standard React Native way:

import { I18nManager } from 'react-native';
I18nManager.allowRTL(true);
I18nManager.forceRTL(true); // requires an app reload

On the web​

React Native Web has no RTL layout flag, and the browser aligns each label by its own script, so a list mixing Hebrew and English would zigzag. Select labels are therefore pinned to the left edge on the web. For an RTL web app, align them right through the slot styles:

const rtl = { textAlign: 'right' } as const;

<SelectPicker styles={{ optionLabel: rtl, optionDescription: rtl, groupHeaderText: rtl, triggerText: rtl, placeholder: rtl }} … />

Search in any language​

The select search folds case and diacritics (é → e) and strips Hebrew niqqud, so users don't need to type accents. Use keywords to make options findable in other languages or by synonyms:

{ label: 'Germany', value: 'DE', keywords: ['Deutschland', 'Allemagne', 'גרמניה'] }