A modern, customizable language picker for React Native — with a searchable modal, a fully overridable language dataset, and a pluggable flag system. Pure JavaScript, zero native code.
🚧 v0.1.0 — early release. APIs are stabilizing. Feedback and contributions very welcome.
Note on flags: v0.1 ships with no bundled flag artwork — the built-in
Flagcomponent renders a styled country-code badge by default. Drop in your own SVG flags viaregisterFlagor therenderFlagprop. Bundled artwork is planned for v0.2.
Most existing React Native language pickers are unmaintained, lock you into a fixed UI, or ship a giant dataset you can't trim. This library aims to be:
- ✅ Maintained — actively developed, MIT-licensed, open to contributors
- ✅ Customizable — show flags only, override the language list, swap any subcomponent via render props, theme everything
- ✅ Lightweight — pure JS, tree-shakeable flag SVGs, only
react-native-svgas a peer dep - ✅ TypeScript-first — full types, no
anyin the public API - ✅ Accessible — proper roles, labels, and screen-reader support out of the box
- ✅ i18n-ready — every UI string is overridable; native names included for every language
See the example/ app in this repo.
npm install @dcankayrak/react-native-language-picker react-native-svg
# or
yarn add @dcankayrak/react-native-language-picker react-native-svgIf you're on bare React Native, also run:
cd ios && pod installExpo users: react-native-svg is already included in the Expo SDK — no extra setup required.
| Package | Version |
|---|---|
react |
>=17 |
react-native |
>=0.70 |
react-native-svg |
>=13 |
import React, { useState } from 'react';
import { View, Button } from 'react-native';
import { LanguagePicker, type Language } from '@dcankayrak/react-native-language-picker';
export default function App() {
const [visible, setVisible] = useState(false);
const [selected, setSelected] = useState<Language>();
return (
<View>
<Button title={selected?.nativeName ?? 'Pick a language'} onPress={() => setVisible(true)} />
<LanguagePicker
visible={visible}
selectedLanguage={selected?.code}
onSelect={(lang) => {
setSelected(lang);
setVisible(false);
}}
onClose={() => setVisible(false)}
/>
</View>
);
}That's it. The modal renders with search, the bundled language list, and country flags.
| Prop | Type | Default | Description |
|---|---|---|---|
selectedLanguage |
LanguageCode |
— | ISO 639-1 code of the currently selected language. |
onSelect |
(lang: Language) => void |
required | Called when the user picks a language. |
| Prop | Type | Default | Description |
|---|---|---|---|
languages |
Language[] |
bundled list | Replace the built-in list entirely. |
excludeLanguages |
LanguageCode[] |
[] |
Hide specific languages from the bundled list. |
includeLanguages |
LanguageCode[] |
— | Whitelist mode — only show these. Takes precedence over excludeLanguages. |
| Prop | Type | Default | Description |
|---|---|---|---|
showFlags |
boolean |
true |
Show the country flag next to each item. |
showNativeName |
boolean |
true |
Show the language's native name (e.g. Türkçe). |
showEnglishName |
boolean |
true |
Show the English name (e.g. Turkish). |
flagsOnly |
boolean |
false |
Render a grid of flags with no text. |
| Prop | Type | Default | Description |
|---|---|---|---|
visible |
boolean |
— | Controlled visibility. If omitted, picker manages its own state. |
onClose |
() => void |
— | Called when the user dismisses the modal. |
searchable |
boolean |
true |
Show a search input at the top of the modal. |
searchPlaceholder |
string |
"Search…" |
Placeholder text for the search input. |
| Prop | Type | Description |
|---|---|---|
labels |
{ search?: string; close?: string; empty?: string } |
Override the picker's own UI strings. |
| Prop | Type | Description |
|---|---|---|
theme |
Partial<LanguagePickerTheme> |
Merge into the default theme — colors, spacing, radius, typography. |
style |
StyleProp<ViewStyle> |
Style for the outer modal container. |
styles |
Partial<LanguagePickerStyles> |
Per-slot style overrides (item, separator, search bar, etc.). |
| Prop | Type | Description |
|---|---|---|
renderItem |
(lang, selected) => ReactNode |
Replace each row entirely. |
renderFlag |
(countryCode) => ReactNode |
Replace the flag component. |
renderTrigger |
(open, selected?) => ReactNode |
Render your own trigger button (uncontrolled mode). |
| Prop | Type | Description |
|---|---|---|
testID |
string |
Test identifier for the modal root. |
accessibilityLabel |
string |
Override the modal's accessibilityLabel. |
<LanguagePicker visible={visible} flagsOnly onSelect={...} onClose={...} /><LanguagePicker
visible={visible}
includeLanguages={['en', 'tr', 'de', 'fr', 'es']}
onSelect={...}
onClose={...}
/><LanguagePicker
visible={visible}
labels={{
search: 'Ara…',
close: 'Kapat',
empty: 'Sonuç bulunamadı',
}}
onSelect={...}
onClose={...}
/>import { LanguagePicker, darkTheme } from '@dcankayrak/react-native-language-picker';
<LanguagePicker visible={visible} theme={darkTheme} onSelect={...} onClose={...} /><LanguagePicker
onSelect={setSelected}
renderTrigger={(open, selected) => (
<TouchableOpacity onPress={open}>
<Text>{selected?.nativeName ?? 'Choose language'}</Text>
</TouchableOpacity>
)}
/><LanguagePicker
languages={[
{ code: 'en', name: 'English', nativeName: 'English', countryCode: 'US' },
{ code: 'tr', name: 'Turkish', nativeName: 'Türkçe', countryCode: 'TR' },
]}
onSelect={...}
/>By default, the built-in Flag component renders a styled badge containing the country code (e.g. US, TR, JP). To use real flag SVGs, you have two options:
import { Svg, Path } from 'react-native-svg';
import { registerFlag, registerFlags } from '@dcankayrak/react-native-language-picker';
const US = (props) => (
<Svg viewBox="0 0 640 480" {...props}>
{/* paths */}
</Svg>
);
registerFlag('US', US);
// or
registerFlags({ US, GB, DE, FR /* ... */ });Once registered, every LanguagePicker instance picks up the SVG automatically.
<LanguagePicker
renderFlag={(countryCode) => <MyFlagComponent code={countryCode} />}
onSelect={...}
/>This is handy if you already use a flag library like react-native-country-flag.
type LanguageCode = string; // ISO 639-1, lowercase, e.g. 'en'
type CountryCode = string; // ISO 3166-1 alpha-2, uppercase, e.g. 'US'
type Language = {
code: LanguageCode;
name: string; // English name
nativeName: string; // Native name
countryCode: CountryCode; // Default flag to show
countries?: CountryCode[]; // All associated countries (optional)
};Does this work with Expo?
Yes. Expo SDK ships react-native-svg, so you only need to install this package.
Does it support RTL?
Yes — the modal honors I18nManager.isRTL automatically.
Can I add a missing language? Yes! See CONTRIBUTING.md for the (very small) process.
Can I use this on the web (react-native-web)? Yes — the component uses only RN core primitives that have web shims.
PRs are very welcome. See CONTRIBUTING.md for setup and guidelines, and CODE_OF_CONDUCT.md for community standards.
For security issues, please follow SECURITY.md — do not open a public issue.
- Bundled flag SVGs (planned for v0.2) will be derived from flag-icons by Panayiotis Lipiridis (MIT). See NOTICE.