Country locale data: from phone numbers to flags.
npm install @callsy/localeA comprehensive locale data library for Node.js and TypeScript. Work seamlessly with countries, phone numbers, and languages using ISO standards, with built-in emoji support and zero runtime dependencies.
- Three Powerful Classes: Work with countries, phone numbers, and languages through intuitive, fluent APIs.
- Zero Runtime Dependencies: Lightweight and secure with no external dependencies.
- 200+ Countries: Comprehensive coverage of ISO 3166-1 alpha-2 country codes with names, flags, and metadata.
- 200+ Languages: Full support for ISO 639 language codes including regional variants (e.g., en-US, fr-CA).
- 300+ US Area Codes: Detailed mapping of NANP area codes to US states for precise location identification.
- E.164 Phone Validation: Automatic validation and formatting of international phone numbers.
- Flag Emoji Support: Built-in flag emojis for countries and languages for rich UI experiences.
- Bidirectional Lookups: Convert seamlessly between codes, names, and related entities.
- TypeScript Ready: Fully typed with comprehensive IntelliSense support for a superior developer experience.
``bash`
npm install @callsy/locale
Work with countries, phone numbers, and languages using clean, intuitive APIs.
`typescript
import { Country, Phone, Language } from '@callsy/locale'
// 1. Working with Countries
const usa = new Country('US')
console.log(usa.name()) // "United States"
console.log(usa.name({ includeEmoji: true })) // "πΊπΈ United States"
console.log(usa.emoji()) // "πΊπΈ"
console.log(usa.continent()) // "NA"
console.log(usa.languages()) // ["en"]
// Or create from name
const france = Country.fromName('France')
console.log(france.iso2()) // "FR"
// 2. Working with Phone Numbers
const phone = new Phone('+1-415-555-0123')
console.log(phone.value()) // "+14155550123"
console.log(phone.country()) // "US"
console.log(phone.state()) // "CA"
console.log(phone.isE164()) // true
// Extract country information from phone
const phoneCountry = new Country(phone.country())
console.log(phoneCountry.name({ includeEmoji: true })) // "πΊπΈ United States"
// 3. Working with Languages
const english = new Language('en')
console.log(english.name()) // "English"
console.log(english.countries()) // ["US", "GB", "CA", ...]
// Regional language codes
const usEnglish = new Language('en-US')
console.log(usEnglish.name()) // "English (United States)"
// Or create from name
const spanish = Language.fromName('Spanish')
console.log(spanish.code()) // "es"
`
The Country class provides comprehensive information about any country using its ISO 3166-1 alpha-2 code.
Creating a Country Instance:
`typescript
// From ISO2 code (case-insensitive, whitespace-tolerant)
const usa = new Country('US')
const uk = new Country(' gb ') // Automatically normalized to "GB"
// From country name (case-sensitive, exact match required)
const canada = Country.fromName('Canada')
`
Getting Country Information:
`typescript
const japan = new Country('JP')
japan.iso2() // "JP"
japan.name() // "Japan"
japan.name({ includeEmoji: true }) // "π―π΅ Japan"
japan.name({ includeCode: true }) // "Japan (JP)"
japan.name({ includeEmoji: true, includeCode: true }) // "π―π΅ Japan (JP)"
japan.emoji() // "π―π΅"
japan.continent() // "AS"
japan.languages() // ["ja"]
`
Comparing Countries:
`typescript
const us1 = new Country('US')
const us2 = new Country('us')
const gb = new Country('GB')
us1.equals(us2) // true
us1.equals(gb) // false
`
Accessing Raw Data:
`typescript`
// Access all static mappings directly
Country.isoToName['US'] // "United States"
Country.nameToIso['France'] // "FR"
Country.isoToFlag['DE'] // "π©πͺ"
Country.isoToCont['BR'] // "SA"
Country.isoToLang['CH'] // ["de", "fr", "it", "rm"]
The Phone class validates and extracts information from international phone numbers following the E.164 format.
Creating a Phone Instance:
`typescript
// Automatically cleans and formats various inputs
const phone1 = new Phone('+1-415-555-0123') // Cleans to +14155550123
const phone2 = new Phone('1 (415) 555-0123') // Adds + if missing
const phone3 = new Phone('+442071234567') // UK number
// All non-digit characters are removed
const phone4 = new Phone('+1abc234def5678') // Becomes +12345678
`
Extracting Phone Information:
`typescript
const phone = new Phone('+14155551234')
phone.value() // "+14155551234"
phone.digits() // "14155551234"
phone.isE164() // true
phone.country() // "US" (extracts country from prefix)
phone.state() // "CA" (US-specific: extracts state from area code)
// For non-US numbers, state() returns null
const ukPhone = new Phone('+442071234567')
ukPhone.country() // "GB"
ukPhone.state() // null
`
Understanding NANP (North American Numbering Plan):
`typescript
// The +1 prefix is shared by multiple countries
const nanpPhone = new Phone('+14165551234')
nanpPhone.country() // "US" (returns first match in NANP countries)
// Access all NANP countries
Phone.phoneToIso[1] // ["US", "CA", "AG", "AI", ...]
`
US State Extraction:
`typescript
// Extract US state from area code
const nyPhone = new Phone('+12125551234')
nyPhone.state() // "NY"
const caPhone = new Phone('+14155551234')
caPhone.state() // "CA"
// Access all US area codes
Phone.usAreaCodes['212'] // "NY"
Phone.usAreaCodes['415'] // "CA"
`
Comparing Phone Numbers:
`typescript
const phone1 = new Phone('+14155551234')
const phone2 = new Phone('1-415-555-1234') // Different format, same number
const phone3 = new Phone('+14155559999')
phone1.equals(phone2) // true (normalized comparison)
phone1.equals(phone3) // false
`
Accessing Raw Data:
`typescript`
// Access static mappings
Phone.isoToPhone['US'] // [1]
Phone.isoToPhone['GB'] // [44]
Phone.phoneToIso[1] // ["US", "CA", "AG", "AI", ...]
Phone.phoneCodes // [1268, 1264, ..., 44, 1] (sorted longest to shortest)
Phone.usAreaCodes['212'] // "NY"
The Language class handles ISO 639 language codes, including support for regional variants.
Creating a Language Instance:
`typescript
// Basic language code (case-insensitive, whitespace-tolerant)
const english = new Language('en')
const french = new Language(' FR ') // Normalized to "fr"
// Regional variants (automatically formatted)
const usEnglish = new Language('en-us') // Normalized to "en-US"
const caFrench = new Language('fr-CA') // "fr-CA"
// From language name (case-sensitive, exact match)
const spanish = Language.fromName('Spanish')
const german = Language.fromName('German (Germany)') // Regional variant
`
Getting Language Information:
`typescript
const spanish = new Language('es')
spanish.code() // "es"
spanish.name() // "Spanish"
spanish.name({ includeEmoji: true }) // "πͺπΈ Spanish"
spanish.name({ includeCode: true }) // "Spanish (es)"
spanish.name({ includeEmoji: true, includeCode: true }) // "πͺπΈ Spanish (es)"
spanish.emoji() // "πͺπΈ" (or "π" if no flag)
spanish.countries() // ["ES", "MX", "AR", ...] countries where Spanish is spoken
`
Working with Regional Variants:
`typescript
const usEnglish = new Language('en-US')
const gbEnglish = new Language('en-GB')
usEnglish.name() // "English (United States)"
gbEnglish.name() // "English (United Kingdom)"
usEnglish.code() // "en-US"
gbEnglish.code() // "en-GB"
// Both regional variants share the same base language
const baseEnglish = new Language('en')
baseEnglish.name() // "English"
`
Comparing Languages:
`typescript
const en1 = new Language('en')
const en2 = new Language('EN')
const es = new Language('es')
en1.equals(en2) // true
en1.equals(es) // false
// Regional variants are different
const enUS = new Language('en-US')
const enGB = new Language('en-GB')
enUS.equals(enGB) // false
`
Accessing Raw Data:
`typescript`
// Access static mappings
Language.codeToName['en'] // "English"
Language.nameToCode['Spanish'] // "es"
Language.codeToFlag['fr'] // "π«π·"
Language.codeToCountries['en'] // ["US", "GB", "CA", ...] countries where English is spoken
Convert seamlessly between different representations:
`typescript
// Country: Code β Name
const countryCode = Country.nameToIso['United States'] // "US"
const countryName = Country.isoToName['US'] // "United States"
// Language: Code β Name
const langCode = Language.nameToCode['English'] // "en"
const langName = Language.codeToName['en'] // "English"
// Phone: Country Code β Phone Prefix
const phonePrefix = Phone.isoToPhone['US'] // [1]
const countries = Phone.phoneToIso[44] // ["GB"]
`
Combine classes for powerful workflows:
`typescript
// Extract country from phone number and get full details
const phone = new Phone('+442071234567')
const country = new Country(phone.country())
console.log(country.name({ includeEmoji: true })) // "π¬π§ United Kingdom"
console.log(country.languages()) // ["en", "cy", "gd"]
// Get languages for a country and display them
const japan = new Country('JP')
const languages = japan.languages().map(code => {
const lang = new Language(code)
return lang.name({ includeEmoji: true })
})
console.log(languages) // ["π―π΅ Japanese"]
// Validate phone number matches expected country
const usPhone = new Phone('+14155551234')
const usCountry = new Country('US')
const isMatch = usPhone.country() === usCountry.iso2() // true
`
All classes throw descriptive errors for invalid inputs:
`typescript
// Invalid country code
try {
new Country('XX')
} catch (error) {
// Error: "Unrecognised country code. Make sure you provide a valid ISO2 country code. Current value: "XX"."
}
// Invalid phone format
try {
new Phone('+123456789012345678') // Exceeds 15 digits
} catch (error) {
// Error: "Phone number must be in E164 format (e.g., +1234567890). Current value: "..."."
}
// Invalid language code
try {
new Language('xyz')
} catch (error) {
// Error: "Unrecognised language code. Make sure you provide a valid ISO 639 language code. Current value: "xyz"."
}
// Empty values
try {
new Country('')
} catch (error) {
// Error: "You must provide a country code. Value can not be empty. Current value: ""."
}
``
ISC