@dcankayrak/react-native-language-picker
v0.1.0
Published
A modern, customizable language picker for React Native with searchable modal, country flags, and overridable dataset.
Maintainers
Readme
@dcankayrak/react-native-language-picker
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.
Why this library?
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
Demo
See the example/ app in this repo.
Installation
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.
Peer dependencies
| Package | Version |
|---|---|
| react | >=17 |
| react-native | >=0.70 |
| react-native-svg | >=13 |
Quick start
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.
Props
Selection
| 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. |
Dataset
| 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. |
Display
| 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. |
Modal behavior
| 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. |
i18n of UI strings
| Prop | Type | Description |
|---|---|---|
| labels | { search?: string; close?: string; empty?: string } | Override the picker's own UI strings. |
Theming & styling
| 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.). |
Render-prop slots
| 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). |
Accessibility
| Prop | Type | Description |
|---|---|---|
| testID | string | Test identifier for the modal root. |
| accessibilityLabel | string | Override the modal's accessibilityLabel. |
Examples
Show only flags
<LanguagePicker visible={visible} flagsOnly onSelect={...} onClose={...} />Limit to a few languages
<LanguagePicker
visible={visible}
includeLanguages={['en', 'tr', 'de', 'fr', 'es']}
onSelect={...}
onClose={...}
/>Translated UI
<LanguagePicker
visible={visible}
labels={{
search: 'Ara…',
close: 'Kapat',
empty: 'Sonuç bulunamadı',
}}
onSelect={...}
onClose={...}
/>Dark theme
import { LanguagePicker, darkTheme } from '@dcankayrak/react-native-language-picker';
<LanguagePicker visible={visible} theme={darkTheme} onSelect={...} onClose={...} />Custom trigger (uncontrolled)
<LanguagePicker
onSelect={setSelected}
renderTrigger={(open, selected) => (
<TouchableOpacity onPress={open}>
<Text>{selected?.nativeName ?? 'Choose language'}</Text>
</TouchableOpacity>
)}
/>Provide your own dataset
<LanguagePicker
languages={[
{ code: 'en', name: 'English', nativeName: 'English', countryCode: 'US' },
{ code: 'tr', name: 'Turkish', nativeName: 'Türkçe', countryCode: 'TR' },
]}
onSelect={...}
/>Flags
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:
Option 1 — register globally
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.
Option 2 — pass renderFlag per-instance
<LanguagePicker
renderFlag={(countryCode) => <MyFlagComponent code={countryCode} />}
onSelect={...}
/>This is handy if you already use a flag library like react-native-country-flag.
Types
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)
};FAQ
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.
Contributing
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.
Credits
- Bundled flag SVGs (planned for v0.2) will be derived from flag-icons by Panayiotis Lipiridis (MIT). See NOTICE.
