Skip to content

dcankayrak/react-native-language-picker

@dcankayrak/react-native-language-picker

npm version npm downloads CI License: MIT PRs Welcome

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 Flag component renders a styled country-code badge by default. Drop in your own SVG flags via registerFlag or the renderFlag prop. 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-svg as a peer dep
  • TypeScript-first — full types, no any in 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-svg

If you're on bare React Native, also run:

cd ios && pod install

Expo 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.

License

MIT

About

React Native Language Picker Components

Topics

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors