Telephone number input React component with country selection, validation, and formatting capabilities
—
Complete internationalization support with locale files for 25+ languages and customizable country/UI labels. The library provides comprehensive localization for country names, UI elements, and supports multiple locale loading patterns.
Pre-built locale files containing translated country names and UI labels.
/**
* Locale label structure
* Contains country names and UI element labels
*/
type Labels = Partial<Record<LabelKey, string>>;
type LabelKey = Country | 'ZZ' | 'ext' | 'country' | 'phone';
// Available locale imports
declare const ar: Labels; // Arabic
declare const ca: Labels; // Catalan
declare const cz: Labels; // Czech
declare const de: Labels; // German
declare const el: Labels; // Greek
declare const en: Labels; // English
declare const es: Labels; // Spanish
declare const et: Labels; // Estonian
declare const fi: Labels; // Finnish
declare const fr: Labels; // French
declare const he: Labels; // Hebrew
declare const hy: Labels; // Armenian
declare const it: Labels; // Italian
declare const ja: Labels; // Japanese
declare const ko: Labels; // Korean
declare const nb: Labels; // Norwegian Bokmål
declare const nl: Labels; // Dutch
declare const pl: Labels; // Polish
declare const pt: Labels; // Portuguese
declare const pt_BR: Labels; // Portuguese (Brazil)
declare const ru: Labels; // Russian
declare const sk: Labels; // Slovak
declare const sv: Labels; // Swedish
declare const th: Labels; // Thai
declare const tr: Labels; // Turkish
declare const ua: Labels; // Ukrainian
declare const vi: Labels; // Vietnamese
declare const zh: Labels; // ChineseBasic Locale Usage:
import PhoneInput from "react-phone-number-input";
import en from "react-phone-number-input/locale/en.json";
import de from "react-phone-number-input/locale/de.json";
import fr from "react-phone-number-input/locale/fr.json";
// English locale
function EnglishExample() {
const [value, setValue] = useState();
return (
<PhoneInput
value={value}
onChange={setValue}
labels={en}
defaultCountry="US"
/>
);
}
// German locale
function GermanExample() {
const [value, setValue] = useState();
return (
<PhoneInput
value={value}
onChange={setValue}
labels={de}
defaultCountry="DE"
/>
);
}
// French locale
function FrenchExample() {
const [value, setValue] = useState();
return (
<PhoneInput
value={value}
onChange={setValue}
labels={fr}
defaultCountry="FR"
/>
);
}Multiple import patterns are supported for different build systems.
// JSON imports (recommended)
import en from "react-phone-number-input/locale/en.json";
import de from "react-phone-number-input/locale/de.json";
// Module imports
import en from "react-phone-number-input/locale/en";
import de from "react-phone-number-input/locale/de";
// CommonJS requires
const en = require("react-phone-number-input/locale/en.json");
const de = require("react-phone-number-input/locale/de.json");The locales prop enables automatic locale resolution from browser preferences.
/**
* Locale property supporting single or multiple locales
* Automatically selects best match from browser language preferences
*/
type LocaleProperty = string | string[];
interface LocaleProps {
/** Single locale string or array of locales for automatic selection */
locales?: LocaleProperty;
/** Explicit labels object (takes precedence over locales) */
labels?: Labels;
}Multi-Locale Examples:
import PhoneInput from "react-phone-number-input";
import "react-phone-number-input/style.css";
// Automatic locale selection from browser
function AutoLocaleExample() {
const [value, setValue] = useState();
return (
<PhoneInput
value={value}
onChange={setValue}
locales={['de', 'fr', 'en']} // Will select best match
defaultCountry="DE"
/>
);
}
// Single locale string
function SingleLocaleExample() {
const [value, setValue] = useState();
return (
<PhoneInput
value={value}
onChange={setValue}
locales="es"
defaultCountry="ES"
/>
);
}Each locale file contains country names and UI element labels.
/**
* Locale file structure
* All entries are optional - missing entries fall back to country codes
*/
interface LocaleStructure {
// UI element labels
"ext"?: string; // Extension label (e.g., "ext.")
"country"?: string; // Country selection aria-label
"phone"?: string; // Phone input aria-label
"ZZ"?: string; // International option label
// Country name labels (partial list shown)
"US"?: string; // "United States"
"CA"?: string; // "Canada"
"GB"?: string; // "United Kingdom"
"DE"?: string; // "Germany"
"FR"?: string; // "France"
"JP"?: string; // "Japan"
"CN"?: string; // "China"
// ... all ~250 country codes supported
}Example Locale Content:
{
"ext": "ext.",
"country": "Phone number country",
"phone": "Phone",
"ZZ": "International",
"US": "United States",
"CA": "Canada",
"GB": "United Kingdom",
"DE": "Germany",
"FR": "France",
"IT": "Italy",
"ES": "Spain",
"JP": "Japan",
"CN": "China",
"IN": "India",
"BR": "Brazil",
"RU": "Russia"
}Create custom label objects for specialized use cases or unsupported languages.
/**
* Custom labels interface
* Can override any subset of countries and UI elements
*/
interface CustomLabels extends Partial<Labels> {
[countryCode: string]: string;
}
// Custom label creation
function createCustomLabels(baseLabels: Labels, overrides: Partial<Labels>): Labels {
return { ...baseLabels, ...overrides };
}Custom Labels Examples:
import en from "react-phone-number-input/locale/en.json";
// Custom UI labels
const customUILabels: Labels = {
...en,
"country": "Select Country",
"phone": "Phone Number",
"ZZ": "International Number",
"ext": "extension"
};
// Regional customizations
const regionalLabels: Labels = {
...en,
"US": "USA",
"GB": "UK",
"CN": "Mainland China"
};
// Business-specific labels
const businessLabels: Labels = {
...en,
"US": "United States of America",
"CA": "Canada (requires verification)",
"MX": "Mexico (additional fees apply)"
};
function CustomLabelsExample() {
const [value, setValue] = useState();
return (
<PhoneInput
value={value}
onChange={setValue}
labels={customUILabels}
defaultCountry="US"
/>
);
}Different strategies for loading and managing locales in applications.
// Static import strategy
import en from "react-phone-number-input/locale/en.json";
import de from "react-phone-number-input/locale/de.json";
import fr from "react-phone-number-input/locale/fr.json";
const localeMap = { en, de, fr };
// Dynamic import strategy
async function loadLocale(locale: string): Promise<Labels> {
try {
const module = await import(`react-phone-number-input/locale/${locale}.json`);
return module.default;
} catch (error) {
// Fallback to English
const fallback = await import("react-phone-number-input/locale/en.json");
return fallback.default;
}
}
// Context-based locale management
const LocaleContext = React.createContext<Labels>(en);Dynamic Locale Loading Examples:
import React, { useState, useEffect } from "react";
import PhoneInput from "react-phone-number-input";
// Dynamic locale loading component
function DynamicLocalePhoneInput({ locale = "en", ...props }) {
const [labels, setLabels] = useState();
const [loading, setLoading] = useState(true);
useEffect(() => {
loadLocale(locale)
.then(setLabels)
.finally(() => setLoading(false));
}, [locale]);
if (loading) return <div>Loading...</div>;
return (
<PhoneInput
{...props}
labels={labels}
/>
);
}
// Locale context provider
function LocaleProvider({ locale, children }) {
const [labels, setLabels] = useState();
useEffect(() => {
loadLocale(locale).then(setLabels);
}, [locale]);
return (
<LocaleContext.Provider value={labels}>
{children}
</LocaleContext.Provider>
);
}
// Hook for using locale context
function useLocale() {
return useContext(LocaleContext);
}The library supports right-to-left languages through proper labeling.
// RTL language examples
import ar from "react-phone-number-input/locale/ar.json"; // Arabic
import he from "react-phone-number-input/locale/he.json"; // Hebrew
// RTL usage with proper CSS
function RTLExample() {
const [value, setValue] = useState();
return (
<div dir="rtl">
<PhoneInput
value={value}
onChange={setValue}
labels={ar}
defaultCountry="SA"
className="rtl-phone-input"
/>
</div>
);
}The library handles missing locale entries gracefully with fallback behavior.
// Fallback priority order:
// 1. Explicit labels prop
// 2. Resolved locale from locales prop
// 3. Country code as fallback (e.g., "US" displays as "US")
// 4. Default English labels for UI elements
// Missing country name fallback
const incompleteLocale: Labels = {
"ext": "ext.",
"US": "United States",
// "CA" missing - will display as "CA"
};
// UI element fallbacks
const countryOnlyLocale: Labels = {
"US": "United States",
"CA": "Canada"
// UI elements missing - will use English defaults
};Fallback Handling Examples:
// Safe locale merging with fallbacks
function mergeWithFallbacks(primaryLocale: Labels, fallbackLocale: Labels): Labels {
return {
...fallbackLocale,
...primaryLocale
};
}
// Locale with guaranteed UI elements
function ensureUILabels(locale: Labels): Labels {
return {
ext: "ext.",
country: "Country",
phone: "Phone",
ZZ: "International",
...locale
};
}
// Usage with fallback
import en from "react-phone-number-input/locale/en.json";
import partialLocale from "./partial-locale.json";
function FallbackExample() {
const safeLabels = mergeWithFallbacks(partialLocale, en);
return (
<PhoneInput
labels={safeLabels}
// ... other props
/>
);
}Install with Tessl CLI
npx tessl i tessl/npm-react-phone-number-input