Socket
Book a DemoInstallSign in
Socket

country-number-formatter

Package Overview
Dependencies
Maintainers
1
Versions
3
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

country-number-formatter

A TypeScript package that detects user's country and formats numbers according to local conventions

1.1.1
latest
Source
npmnpm
Version published
Maintainers
1
Created
Source

Country Number Formatter

A TypeScript npm package that formats numbers, currencies, and percentages according to country-specific locale conventions. Perfect for React applications that need internationalization (i18n) support.

Features

  • 🌍 Country-Based Formatting: Formats numbers according to any country's locale conventions
  • 🔢 Smart Number Formatting: Formats numbers with correct decimal and thousand separators
  • 💰 Currency Formatting: Displays currency with proper symbols and formatting
  • 📊 Percentage Formatting: Handles percentage display according to locale
  • ⚛️ React Integration: Includes React hooks and components for easy integration
  • 🎯 TypeScript Support: Fully typed with comprehensive TypeScript definitions
  • 🚀 Lightweight: Minimal dependencies with efficient caching
  • 🔄 Fallback Support: Graceful fallbacks using browser locale detection
  • 🏃‍♂️ No CORS Issues: Works perfectly in browsers without external API calls

Installation

npm install country-number-formatter

For React usage, ensure you have React 16.8+ installed:

npm install react@^16.8.0

Quick Start

Standalone Usage

import { CountryLocaleFormatter } from 'country-number-formatter';

const formatter = new CountryLocaleFormatter();

// Option 1: Use browser locale detection
await formatter.initialize();

// Option 2: Specify a country code
await formatter.initialize('DE'); // Germany

// Option 3: Change country later
formatter.setCountry('FR'); // France

// Format numbers
const number = formatter.formatNumber(1234.56);
console.log(number?.formatted); // "1,234.56" (US) or "1.234,56" (DE)

// Format currency
const currency = formatter.formatCurrency(1234.56);
console.log(currency?.formatted); // "$1,234.56" (US) or "1.234,56 €" (DE)

// Format percentage
const percent = formatter.formatPercent(0.1234);
console.log(percent?.formatted); // "12.34%" (US) or "12,34 %" (DE)

// Format numbers in strings (simple method)
const text = "Price: 1234.56 and quantity: 100";

// Use current country (set during initialize or setCountry)
const autoFormatted = formatter.formatNumbersInString(text, undefined, 2);

// Use specific country
const formatted = formatter.formatNumbersInString(text, 'DE', 2);
console.log(formatted); // "Price: 1.234,56 and quantity: 100,00"

// Format numbers in strings (detailed method)
const detailed = formatter.formatStringNumbers(text, 'DE', 2);
console.log(detailed.formattedString); // "Price: 1.234,56 and quantity: 100,00"
console.log(detailed.numbersFound); // 2
console.log(detailed.replacements); // Array of replacement details

String Formatting

The package includes powerful string formatting methods that can find and format all numbers within a text string:

Simple String Formatting

Use formatNumbersInString() when you just need the formatted string:

// Current country formatting (uses initialized country)
const autoResult = formatter.formatNumbersInString(
  "Sales: 1234567.89 and costs: 999.5"
  // No country code = uses current country
);

// Specific country formatting
const result = formatter.formatNumbersInString(
  "Sales: 1234567.89 and costs: 999.5", 
  'FR'  // French formatting
);
console.log(result); 
// "Sales: 1 234 567,89 and costs: 999,50"

// With decimal place control
const result2 = formatter.formatNumbersInString(
  "Values: 123.456 and 789.123", 
  'DE',  // German formatting
  2      // Force 2 decimal places
);
console.log(result2); 
// "Values: 123,46 and 789,12"

Detailed String Formatting

Use formatStringNumbers() when you need metadata about the formatting:

const result = formatter.formatStringNumbers(
  "Price: 1234.56 and tax: 123.45", 
  'IN',  // Indian formatting
  2      // 2 decimal places
);

console.log(result.formattedString);  // "Price: 1,234.56 and tax: 123.45"
console.log(result.numbersFound);     // 2
console.log(result.countryUsed);      // "IN"
console.log(result.replacements);     // Array with details about each replacement

Information & Utility Methods

Getting Formatting Information

// Get current formatting rules
const formatInfo = formatter.getFormattingInfo();
console.log(formatInfo?.decimalSeparator);   // "." or ","
console.log(formatInfo?.thousandSeparator);  // "," or "." or "'" or " "
console.log(formatInfo?.currencySymbol);     // "$", "€", "£", etc.
console.log(formatInfo?.currencyPosition);   // "before" or "after"
console.log(formatInfo?.example);            // "1,234.56" (example format)

// Get all supported country codes  
const countries = formatter.getSupportedCountries();
console.log(countries.length);    // 250+
console.log(countries.slice(0,5)); // ["AD", "AE", "AF", "AG", "AI"]

React Information Methods

const { 
  getFormattingInfo, 
  getSupportedCountries,
  countryInfo 
} = useCountryFormatter();

// Get current formatting rules
const formatInfo = getFormattingInfo();

// Get all supported countries
const allCountries = getSupportedCountries();

// Display current country info
console.log(countryInfo?.countryCode);  // "US"
console.log(countryInfo?.countryName);  // "United States"
console.log(countryInfo?.currency);     // "USD"
console.log(countryInfo?.locale);       // "en-US"

Advanced Configuration Options

// Custom formatting with all options
const formatted = formatter.formatNumber(1234.56789, {
  minimumFractionDigits: 2,    // At least 2 decimal places
  maximumFractionDigits: 4,    // At most 4 decimal places
  useGrouping: true            // Use thousand separators
});

// Currency with custom settings
const currency = formatter.formatCurrency(1234.56, {
  currency: 'EUR',             // Override default currency
  minimumFractionDigits: 0,    // No decimal places required
  maximumFractionDigits: 2     // Max 2 decimal places
});

// Country setting options
await formatter.initialize('DE');     // Use Germany
await formatter.initialize();         // Use browser locale
formatter.setCountry('JP');           // Change to Japan manually

// Get current country
const currentCountry = formatter.getCountryInfo();

React Hook Usage

import { useCountryFormatter } from 'country-number-formatter/react';

function MyComponent() {
  const { 
    formatNumber, 
    formatCurrency, 
    formatNumbersInString,
    formatStringNumbers,
    countryInfo, 
    isLoading 
  } = useCountryFormatter();

  if (isLoading) return <div>Detecting location...</div>;

  const price = 1234.56;
  const formattedPrice = formatCurrency(price);
  
  // Simple string formatting
  const text = "Total: 1234.56 with tax: 123.45";
  
  // Auto-detection (omit country code to use current country)
  const autoFormattedText = formatNumbersInString(text, undefined, 2);
  
  // Specific country formatting
  const deFormattedText = formatNumbersInString(text, 'DE', 2);

  return (
    <div>
      <p>Country: {countryInfo?.countryName}</p>
      <p>Price: {formattedPrice?.formatted}</p>
      <p>Auto Text: {autoFormattedText}</p>
      <p>DE Text: {deFormattedText}</p>
    </div>
  );
}

React Components

import { 
  CountryFormatterProvider, 
  CurrencyDisplay, 
  NumberDisplay,
  PercentDisplay 
} from 'country-number-formatter/react';

function App() {
  return (
    <CountryFormatterProvider defaultCountry="US">
      <div>
        <NumberDisplay value={1234.56} />
        <CurrencyDisplay value={1234.56} />
        <PercentDisplay value={0.1234} />
      </div>
    </CountryFormatterProvider>
  );
}

API Reference

CountryLocaleFormatter Class

Main class for standalone usage.

Methods

  • initialize(countryCode?: string): Promise<CountryInfo>
  • setCountry(countryCode: string): void
  • getCountryInfo(): CountryInfo | null
  • formatNumber(value: number, options?: FormatOptions): FormattedNumber | null
  • formatCurrency(value: number, options?: FormatOptions): FormattedNumber | null
  • formatPercent(value: number, options?: FormatOptions): FormattedNumber | null
  • parseNumber(formattedValue: string): number | null
  • getFormattingInfo(): FormattingInfo | null
  • formatNumbersInString(inputString: string, countryCode?: string, decimalPlaces?: number): string
  • formatStringNumbers(inputString: string, countryCode?: string, decimalPlaces?: number): StringFormatResult
  • getSupportedCountries(): string[]
  • formatPercent(value: number, options?: FormatOptions): FormattedNumber | null
  • parseNumber(formattedValue: string): number | null
  • getFormattingInfo(): FormattingInfo | null

React Hook: useCountryFormatter

const {
  countryInfo,
  isLoading,
  error,
  formatNumber,
  formatNumber,
  formatCurrency,
  formatPercent,
  parseNumber,
  setCountry,
  refreshCountry,
  getFormattingInfo,
  formatNumbersInString,
  formatStringNumbers
} = useCountryFormatter(options);

Options

interface UseCountryFormatterOptions {
  autoDetect?: boolean;        // Use browser locale detection (default: true)
  defaultCountry?: string;     // Fallback country code (default: 'US')
  onCountryDetected?: (countryInfo: CountryInfo) => void;
  onError?: (error: Error) => void;
}

React Components

CountryFormatterProvider

Provides country formatting context to child components.

<CountryFormatterProvider 
  autoDetect={true}
  defaultCountry="US"
  fallback={<div>Loading...</div>}
>
  {children}
</CountryFormatterProvider>

NumberDisplay

Display formatted numbers with full customization:

<NumberDisplay 
  value={1234.56}
  type="number"                    // "number" | "currency" | "percent"
  minimumFractionDigits={2}        // Minimum decimal places
  maximumFractionDigits={4}        // Maximum decimal places
  useGrouping={true}               // Use thousand separators
  currency="USD"                   // Currency override
  className="my-number"            // CSS class
  style={{ color: 'blue' }}       // Inline styles
  prefix="Total: "                 // Text before number
  suffix=" USD"                    // Text after number
  onFormatted={(result) => {       // Callback with formatting result
    console.log(result.formatted);
  }}
/>

CurrencyDisplay

Display formatted currency with automatic symbols:

<CurrencyDisplay 
  value={1234.56}
  currency="EUR"                   // Override detected currency
  minimumFractionDigits={0}        // No decimals required
  maximumFractionDigits={2}        // Max 2 decimals
  className="price"
  prefix="Price: "
  onFormatted={(result) => {
    console.log('Currency:', result.currency);
    console.log('Symbol:', result.symbol);
  }}
/>

PercentDisplay

Display formatted percentages:

<PercentDisplay 
  value={0.1234}                   // 0.1234 = 12.34%
  minimumFractionDigits={1}        // At least 1 decimal
  maximumFractionDigits={2}        // At most 2 decimals
  className="percentage"
  suffix=" discount"
/>

CountryInfoComponent

Display current country information:

<CountryInfoComponent 
  showFlag={true}                  // Show country flag emoji
  showCurrency={true}              // Show currency code
  showLocale={true}                // Show locale string
  className="country-info"
  style={{ padding: '10px' }}
  format={(info) =>                // Custom formatting function
    `${info.countryName} (${info.countryCode})`
  }
/>

Types

CountryInfo

interface CountryInfo {
  countryCode: string;    // ISO country code (e.g., "US", "DE")
  countryName: string;    // Full country name
  currency: string;       // Currency code (e.g., "USD", "EUR")
  locale: string;         // Locale string (e.g., "en-US", "de-DE")
}

FormattedNumber

interface FormattedNumber {
  formatted: string;         // The formatted number string
  currency: string;          // Currency code used
  locale: string;           // Locale used for formatting
  decimalSeparator: string; // Decimal separator character
  thousandSeparator: string; // Thousand separator character
  symbol?: string;          // Currency or percent symbol
}

FormatOptions

interface FormatOptions {
  type?: 'number' | 'currency' | 'percent';
  minimumFractionDigits?: number;
  maximumFractionDigits?: number;
  useGrouping?: boolean;
  currency?: string;  // Override default currency
}

FormattingInfo

interface FormattingInfo {
  decimalSeparator: string;      // "." or ","
  thousandSeparator: string;     // "," or "." or "'" or " "
  currencySymbol: string;        // "$", "€", "£", "¥", etc.
  currencyPosition: "before" | "after";  // Symbol position
  example: string;               // Example formatted number "1,234.56"
}

StringFormatResult

interface StringFormatResult {
  formattedString: string;       // String with formatted numbers
  originalString: string;        // Original input string
  numbersFound: number;          // Count of numbers found
  replacements: Array<{          // Details of each replacement
    original: string;            // Original number string
    formatted: string;           // Formatted number string
    position: number;            // Position in original string
  }>;
  countryUsed: string;          // Country code used for formatting
}

UseCountryFormatterReturn

Complete React hook return interface:

interface UseCountryFormatterReturn {
  // State
  countryInfo: CountryInfo | null;
  isLoading: boolean;
  error: Error | null;
  
  // Formatting Methods
  formatNumber: (value: number, options?: FormatOptions) => FormattedNumber | null;
  formatCurrency: (value: number, options?: Omit<FormatOptions, 'type'>) => FormattedNumber | null;
  formatPercent: (value: number, options?: Omit<FormatOptions, 'type'>) => FormattedNumber | null;
  parseNumber: (formattedValue: string) => number | null;
  
  // String Processing
  formatStringNumbers: (inputString: string, countryCode?: string, decimalPlaces?: number) => StringFormatResult;
  formatNumbersInString: (inputString: string, countryCode?: string, decimalPlaces?: number) => string;
  
  // Information & Control
  setCountry: (countryCode: string) => void;
  refreshCountry: () => Promise<void>;
  getFormattingInfo: () => FormattingInfo | null;
  getSupportedCountries: () => string[];
}

Complete Function Reference

Core Library Functions

// Initialization
const formatter = new CountryLocaleFormatter();
await formatter.initialize(autoDetect?, defaultCountry?);

// Number Formatting
formatter.formatNumber(1234.56, options?);         // FormattedNumber | null
formatter.formatCurrency(1234.56, options?);       // FormattedNumber | null
formatter.formatPercent(0.1234, options?);         // FormattedNumber | null

// String Processing
formatter.formatStringNumbers(text, country?, decimals?);    // StringFormatResult
formatter.formatNumbersInString(text, country?, decimals?);  // string

// Information & Control
formatter.getCountryInfo();                         // CountryInfo | null
formatter.getFormattingInfo();                      // FormattingInfo | null
formatter.getSupportedCountries();                  // string[]
formatter.setCountry(countryCode);                  // void
formatter.parseNumber(formattedText);               // number | null

React Hook Functions

const {
  // State
  countryInfo, isLoading, error,
  
  // All core functions available in React
  formatNumber, formatCurrency, formatPercent,
  formatStringNumbers, formatNumbersInString,
  getFormattingInfo, getSupportedCountries,
  setCountry, refreshCountry, parseNumber
} = useCountryFormatter(options?);

Practical Examples

Real-World Usage Scenarios

// E-commerce product pricing
const productPrice = 1299.99;
const formattedPrice = formatter.formatCurrency(productPrice);
// US: "$1,299.99" | DE: "1.299,99 €" | JP: "¥1,299.99"

// Financial reports with multiple numbers
const report = "Q4 Revenue: 2500000.50, Expenses: 1800000.25, Profit: 700000.25";
const formattedReport = formatter.formatNumbersInString(report, 'DE', 2);
// "Q4 Revenue: 2.500.000,50, Expenses: 1.800.000,25, Profit: 700.000,25"

// Data visualization tooltips
const tooltipText = `Sales: ${formatter.formatCurrency(125000)} (${formatter.formatPercent(0.15)} increase)`;
// "Sales: $125,000.00 (15.00% increase)"

// User input parsing
const userInput = "€1.234,56";
const parsedValue = formatter.parseNumber(userInput); // 1234.56

// Multi-country data processing
const countries = ['US', 'DE', 'FR', 'JP'];
const amount = 1234.56;
countries.forEach(country => {
  const formatted = formatter.formatCurrency(amount, { currency: getCurrency(country) });
  console.log(`${country}: ${formatted.formatted}`);
});

React Component Examples

// E-commerce product card
function ProductCard({ product }) {
  const { formatCurrency, formatPercent } = useCountryFormatter();
  
  return (
    <div className="product-card">
      <h3>{product.name}</h3>
      <div className="price">
        <CurrencyDisplay value={product.price} className="current-price" />
        {product.discount > 0 && (
          <span className="discount">
            <PercentDisplay value={product.discount} suffix=" off" />
          </span>
        )}
      </div>
    </div>
  );
}

// Financial dashboard
function Dashboard({ metrics }) {
  const { formatNumbersInString, countryInfo } = useCountryFormatter();
  
  const summary = `Revenue: ${metrics.revenue}, Costs: ${metrics.costs}, Profit: ${metrics.profit}`;
  const formattedSummary = formatNumbersInString(summary, countryInfo?.countryCode, 2);
  
  return (
    <div className="dashboard">
      <h2>Financial Summary</h2>
      <p>{formattedSummary}</p>
    </div>
  );
}

// Multi-language support
function LocalizedApp() {
  const { countryInfo, isLoading, setCountry } = useCountryFormatter();
  
  const countries = [
    { code: 'US', name: 'United States' },
    { code: 'DE', name: 'Germany' },
    { code: 'FR', name: 'France' },
    { code: 'JP', name: 'Japan' }
  ];
  
  if (isLoading) return <div>Detecting your location...</div>;
  
  return (
    <div>
      <select 
        value={countryInfo?.countryCode} 
        onChange={(e) => setCountry(e.target.value)}
      >
        {countries.map(country => (
          <option key={country.code} value={country.code}>
            {country.name}
          </option>
        ))}
      </select>
      
      <NumberDisplay value={1234.56} />
      <CurrencyDisplay value={999.99} />
    </div>
  );
}

Country Detection

The package uses browser locale detection for reliable country determination:

  • Browser Language - Primary detection via navigator.language
  • Manual Override - Direct country code specification
  • User Selection - Allow users to choose their country
  • Fallback - Default to 'US' if detection fails

1. Backend IP Detection (Most Accurate)

// Backend endpoint
app.get('/api/country', (req, res) => {
  const ip = req.ip;
  // Use any IP detection service on your backend
  const country = detectCountryFromIP(ip);
  res.json({ countryCode: country });
});

// Frontend usage
const response = await fetch('/api/country');
const { countryCode } = await response.json();
await formatter.initialize(countryCode);

2. User Selection (Best UX)

// Let users choose their country
const countrySelect = document.getElementById('country');
countrySelect.addEventListener('change', (e) => {
  formatter.setCountry(e.target.value);
  updateNumbers();
});

3. Browser Locale (Automatic)

// Uses navigator.language to detect country
await formatter.initialize(); // Automatic detection

Supported Countries

The package supports 150+ countries with their respective:

  • Locale strings
  • Currency codes
  • Number formatting conventions
  • Decimal and thousand separators

See the full list in COUNTRY_LOCALE_MAP and COUNTRY_CURRENCY_MAP constants.

Examples

Different Locale Formatting

// US formatting
await formatter.initialize('US');
formatter.formatCurrency(1234.56); // "$1,234.56"

// German formatting  
await formatter.initialize('DE');
formatter.formatCurrency(1234.56); // "1.234,56 €"

// Japanese formatting
await formatter.initialize('JP');
formatter.formatCurrency(1234); // "¥1,234"

// Indian formatting
await formatter.initialize('IN');
formatter.formatCurrency(1234.56); // "₹1,234.56"

Custom Formatting Options

const options = {
  minimumFractionDigits: 0,
  maximumFractionDigits: 3,
  useGrouping: false
};

formatter.formatNumber(1234.567, options); // "1234.568"

Parsing Formatted Numbers

// Parse different formats
formatter.parseNumber("$1,234.56");  // 1234.56
formatter.parseNumber("1.234,56 €"); // 1234.56
formatter.parseNumber("12.34%");     // 12.34

Error Handling

The package includes comprehensive error handling:

const { error, countryInfo, formatNumber } = useCountryFormatter({
  onError: (error) => {
    console.error('Country setup failed:', error);
    // Handle error (e.g., show notification)
  },
  onCountryDetected: (country) => {
    console.log('Country set to:', country);
  }
});

// Check for errors
if (error) {
  return <div>Error: {error.message}</div>;
}

Performance

  • Caching: Formatters and country info are cached for performance
  • No Network Calls: All formatting done locally in browser
  • Minimal Bundle: Tree-shakeable exports keep bundle size small
  • Fast Initialization: Instant setup with browser locale detection

Browser Support

  • Modern browsers with Intl.NumberFormat support
  • Node.js 14+
  • React 16.8+ (for React features)
  • No external API dependencies - works offline

Contributing

  • Fork the repository
  • Create a feature branch
  • Add tests for new functionality
  • Ensure all tests pass
  • Submit a pull request

Changelog

1.1.0

  • BREAKING: Simplified API - removed IP-based auto-detection
  • BREAKING: Changed initialize(autoDetect, defaultCountry) to initialize(countryCode?)
  • Added browser locale detection as fallback
  • Removed axios dependency (smaller bundle size)
  • Fixed CORS issues - now works perfectly in all browsers
  • Improved performance - no network calls required
  • Better user control over country selection

1.0.0

  • Initial release
  • Browser locale detection for country determination
  • Number, currency, and percentage formatting
  • React hooks and components
  • TypeScript support
  • Comprehensive test suite
  • No external API dependencies

📋 Quick Reference

Installation

npm install country-number-formatter

Basic Usage

// Node.js
const formatter = new CountryLocaleFormatter();
await formatter.initialize();
const result = formatter.formatCurrency(1234.56);

// React
const { formatCurrency } = useCountryFormatter();
const result = formatCurrency(1234.56);

All Functions

  • Formatting: formatNumber(), formatCurrency(), formatPercent()
  • String Processing: formatStringNumbers(), formatNumbersInString()
  • Information: getCountryInfo(), getFormattingInfo(), getSupportedCountries()
  • Control: setCountry(), parseNumber(), initialize()

React Components

  • <NumberDisplay />, <CurrencyDisplay />, <PercentDisplay />
  • <CountryInfoComponent />, <CountryFormatterProvider />

Key Features

  • 🌍 250+ Countries - Complete international support
  • 🔍 Browser Locale Detection - Automatic country detection
  • ⚛️ React Ready - Hooks and components included
  • 📝 String Processing - Format numbers in text
  • 🎯 TypeScript - Full type safety
  • 🚀 Production Ready - Tested and optimized
  • 🏃‍♂️ No CORS Issues - Works perfectly in browsers

Need help? Check the examples above or the demo files in the repository!

Keywords

country

FAQs

Package last updated on 05 Jul 2025

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

About

Packages

Stay in touch

Get open source security insights delivered straight into your inbox.

  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc

U.S. Patent No. 12,346,443 & 12,314,394. Other pending.