CountryData.Globalization 1.0.0

dotnet add package CountryData.Globalization --version 1.0.0
                    
NuGet\Install-Package CountryData.Globalization -Version 1.0.0
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="CountryData.Globalization" Version="1.0.0" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="CountryData.Globalization" Version="1.0.0" />
                    
Directory.Packages.props
<PackageReference Include="CountryData.Globalization" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add CountryData.Globalization --version 1.0.0
                    
#r "nuget: CountryData.Globalization, 1.0.0"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package CountryData.Globalization@1.0.0
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=CountryData.Globalization&version=1.0.0
                    
Install as a Cake Addin
#tool nuget:?package=CountryData.Globalization&version=1.0.0
                    
Install as a Cake Tool

CountryData.Globalization

.NET License

A high-performance .NET library providing comprehensive country data, regions, cultures, currencies, and globalization information. Built for international applications with full country/region support.

Features

  • High Performance - O(1) dictionary lookups with lazy-loaded caches
  • 250+ Countries - Complete ISO 3166-1 country data
  • Administrative Regions - States, provinces, territories
  • Currency Information - Symbols, codes, names in multiple languages
  • Full Globalization - CultureInfo and RegionInfo integration
  • Phone Codes - International dialing codes
  • Multi-Language - Support for cultures and localized names
  • DI Ready - Built-in dependency injection support
  • Thread-Safe - All operations are thread-safe
  • Zero Dependencies - Lightweight, no external packages

Installation

Install both the core package and hosting package:

# Core package
dotnet add package CountryData.Globalization

# Hosting package (for DI support)
dotnet add package CountryData.Globalization.Hosting

Package Manager Console:

Install-Package CountryData.Globalization
Install-Package CountryData.Globalization.Hosting

Option 2: Core Package Only

If you don't need dependency injection support:

dotnet add package CountryData.Globalization

Package Manager Console:

Install-Package CountryData.Globalization

Quick Start

Step 1: Register the service

// Program.cs
using CountryData.Globalization.Hosting.Extensions;

var builder = WebApplication.CreateBuilder(args);

// Register CountryData services
builder.Services.AddCountryData();

var app = builder.Build();

Step 2: Inject and use

using CountryData.Globalization.Services;

public class CountryController : ControllerBase
{
    private readonly ICountryDataProvider _countryProvider;

    public CountryController(ICountryDataProvider countryProvider)
    {
        _countryProvider = countryProvider;
    }

    [HttpGet("country/{code}")]
    public IActionResult GetCountry(string code)
    {
        var country = _countryProvider.GetCountryByCode(code);
        if (country == null) return NotFound();

        return Ok(new
        {
            Name = country.CountryName,
            Flag = _countryProvider.GetCountryFlag(code),
            Currency = _countryProvider.GetCurrencySymbol(code),
            PhoneCode = country.PhoneCode,
            IsMetric = _countryProvider.IsMetric(code)
        });
    }
}

Using Without Dependency Injection

If you're not using DI, create the provider directly:

using CountryData.Globalization.Services;

// Simple - just create it (recommended)
var provider = new CountryDataProvider();

// Use the provider
var country = provider.GetCountryByCode("US");
Console.WriteLine($"{country.CountryName} - {provider.GetCountryFlag("US")}");

// Get regions
var states = provider.GetRegionsByCountryCode("US");
foreach (var state in states)
{
    Console.WriteLine($"{state.Name} ({state.ShortCode})");
}

// Get currency info
var symbol = provider.GetCurrencySymbol("US");
Console.WriteLine($"Currency: {symbol}");

Important: Reuse the same provider instance. Don't create new instances repeatedly as it's expensive.

// GOOD - Singleton pattern
public class CountryDataSingleton
{
    private static readonly Lazy<ICountryDataProvider> _instance = 
        new Lazy<ICountryDataProvider>(() => new CountryDataProvider());

    public static ICountryDataProvider Instance => _instance.Value;
}

// Usage
var country = CountryDataSingleton.Instance.GetCountryByCode("US");

API Reference

Country Data Methods

Method Description Returns
GetAllCountries() Gets all 250+ countries IEnumerable<Country>
GetCountryByCode(code) Get country by ISO 3166-1 alpha-2 code Country?
GetCountryNames() Gets all country names IEnumerable<string>
GetCountryFlag(code) Gets Unicode emoji flag string
GetCurrentRegionCountry() Gets country for current user's region Country?

Example:

var country = provider.GetCountryByCode("US");
var flag = provider.GetCountryFlag("JP");
var allCountries = provider.GetAllCountries();

Phone Code Methods

Method Description Returns
GetPhoneCodeByCountryShortCode(code) Get phone code for country string?
GetCountriesByPhoneCode(phoneCode) Get all countries with phone code IEnumerable<Country>

Example:

var phoneCode = provider.GetPhoneCodeByCountryShortCode("GB");  // "+44"
var countries = provider.GetCountriesByPhoneCode("+1");         // US, Canada, etc.

Region Methods

Method Description Returns
GetRegionsByCountryCode(code) Get states/provinces/territories IEnumerable<Region>
GetCountriesByRegion(regionName) Find countries containing region IEnumerable<Country>

Example:

var states = provider.GetRegionsByCountryCode("US");
var country = provider.GetCountriesByRegion("California").FirstOrDefault();

Currency Methods

Method Description Returns
GetCurrencySymbol(code) Get currency symbol string?
GetCurrencyEnglishName(code) Get currency English name string?
GetCurrencyNativeName(code) Get currency native name string?
GetCountriesByCurrency(currencyCode) Get all countries using currency IEnumerable<Country>

Example:

var symbol = provider.GetCurrencySymbol("US");           // "$"
var name = provider.GetCurrencyEnglishName("GB");        // "British Pound"
var euroCountries = provider.GetCountriesByCurrency("EUR");

Culture & Globalization Methods

Method Description Returns
GetCultureInfo(code) Get primary CultureInfo CultureInfo?
GetAllCulturesForCountry(code) Get all cultures for country IEnumerable<CultureInfo>
GetSpecificCultureByCountryAndLanguage(country, lang) Get specific culture CultureInfo?
GetCountriesByCulture(cultureName) Get countries by culture IEnumerable<Country>
GetCountriesByLanguage(languageCode) Get countries by language IEnumerable<Country>

Example:

var culture = provider.GetCultureInfo("US");             // en-US culture
var cultures = provider.GetAllCulturesForCountry("CA");  // en-CA, fr-CA
var frenchCA = provider.GetSpecificCultureByCountryAndLanguage("CA", "fr");

RegionInfo Methods

Method Description Returns
GetRegionInfo(code) Get .NET RegionInfo RegionInfo?
GetDisplayName(code, culture?) Get localized country name string?
IsMetric(code) Check if country uses metric bool
GetThreeLetterISORegionName(code) Get ISO 3166-1 alpha-3 code string?
GetThreeLetterWindowsRegionName(code) Get Windows region code string?

Example:

var regionInfo = provider.GetRegionInfo("US");
var isMetric = provider.IsMetric("US");                  // false
var iso3 = provider.GetThreeLetterISORegionName("US");   // "USA"

Common Usage Examples

Example 1: Country Dropdown for Forms

public class CountryDropdownService
{
    private readonly ICountryDataProvider _provider;

    public CountryDropdownService(ICountryDataProvider provider)
    {
        _provider = provider;
    }

    public List<CountryOption> GetCountryOptions()
    {
        return _provider.GetAllCountries()
            .OrderBy(c => c.CountryName)
            .Select(c => new CountryOption
            {
                Code = c.CountryShortCode,
                Name = c.CountryName,
                Flag = _provider.GetCountryFlag(c.CountryShortCode)
            })
            .ToList();
    }
}

Example 2: Phone Number Formatting

public class PhoneNumberService
{
    private readonly ICountryDataProvider _provider;

    public PhoneNumberService(ICountryDataProvider provider)
    {
        _provider = provider;
    }

    public string FormatPhoneNumber(string countryCode, string localNumber)
    {
        var phoneCode = _provider.GetPhoneCodeByCountryShortCode(countryCode);
        return $"{phoneCode} {localNumber}";
    }
}

// Usage: FormatPhoneNumber("US", "555-1234") returns "+1 555-1234"

Example 3: Address Form with Dynamic Regions

public class AddressFormService
{
    private readonly ICountryDataProvider _provider;

    public AddressFormService(ICountryDataProvider provider)
    {
        _provider = provider;
    }

    public List<RegionOption> GetRegionsForCountry(string countryCode)
    {
        return _provider.GetRegionsByCountryCode(countryCode)
            .Select(r => new RegionOption
            {
                Code = r.ShortCode,
                Name = r.Name
            })
            .OrderBy(r => r.Name)
            .ToList();
    }
}

Example 4: Currency Display

public class CurrencyService
{
    private readonly ICountryDataProvider _provider;

    public CurrencyService(ICountryDataProvider provider)
    {
        _provider = provider;
    }

    public CurrencyInfo GetCurrencyInfo(string countryCode)
    {
        return new CurrencyInfo
        {
            Symbol = _provider.GetCurrencySymbol(countryCode),
            EnglishName = _provider.GetCurrencyEnglishName(countryCode),
            NativeName = _provider.GetCurrencyNativeName(countryCode)
        };
    }
}

Example 5: Multi-Language Support

public class LocalizationService
{
    private readonly ICountryDataProvider _provider;

    public LocalizationService(ICountryDataProvider provider)
    {
        _provider = provider;
    }

    public string GetLocalizedCountryName(string countryCode, string languageCode)
    {
        var culture = new CultureInfo(languageCode);
        return _provider.GetDisplayName(countryCode, culture) 
            ?? _provider.GetCountryByCode(countryCode)?.CountryName 
            ?? "Unknown";
    }
}

// Usage: 
// GetLocalizedCountryName("JP", "fr-FR") returns "Japon"
// GetLocalizedCountryName("JP", "es-ES") returns "Japón"

Architecture & Performance

Performance Characteristics

Operation Time Complexity Notes
GetCountryByCode O(1) Dictionary lookup
GetCountriesByPhoneCode O(1) Pre-built index
GetCountriesByCurrency O(1) Pre-built index
GetCountriesByLanguage O(1) Pre-built index
GetAllCountries O(1) Returns cached collection
GetRegionsByCountryCode O(1) Direct property access
GetCultureInfo O(1) Pre-built cache
GetRegionInfo O(1) Pre-built cache
GetCountriesByRegion O(n×m) Sequential scan - cache if frequently used

Caching Strategy

All caches use lazy initialization with thread-safe Lazy<T>:

  1. Country Dictionary - Built at construction (~50ms)
  2. RegionInfo Cache - Built on first currency/region access (~50-100ms)
  3. CultureInfo Cache - Built on first culture access (~100-150ms)
  4. Phone Code Index - Built on first phone query (<10ms)
  5. Currency Index - Built on first currency query (~50-100ms)
  6. Language Index - Built on first language query (~100-150ms)

Memory Footprint: ~2-5 MB for all caches combined

Thread Safety

100% Thread-Safe

  • Immutable data collections
  • Thread-safe lazy initialization via Lazy<T>
  • No mutable state
  • Safe for concurrent access from multiple threads
  • Registered as Singleton by default

Data Models

Country Model

public class Country
{
    public string CountryName { get; set; }        // "United States"
    public string CountryShortCode { get; set; }   // "US"
    public string PhoneCode { get; set; }          // "+1"
    public List<Region> Regions { get; set; }      // States/Provinces
}

Region Model

public class Region
{
    public string Name { get; set; }         // "California"
    public string? ShortCode { get; set; }   // "CA" (optional)
}

Best Practices

// GOOD - With DI (Recommended)
builder.Services.AddCountryData();

public class MyService
{
    private readonly ICountryDataProvider _provider;
    
    public MyService(ICountryDataProvider provider)
    {
        _provider = provider;
    }
}

// GOOD - Without DI (Simple instantiation)
var provider = new CountryDataProvider();

// GOOD - Without DI (Singleton pattern)
public class CountryDataSingleton
{
    private static readonly Lazy<ICountryDataProvider> _instance = 
        new Lazy<ICountryDataProvider>(() => new CountryDataProvider());

    public static ICountryDataProvider Instance => _instance.Value;
}

Anti-Patterns to Avoid

// BAD - Creating new instances repeatedly
foreach (var item in items)
{
    var provider = new CountryDataProvider();  // Expensive!
    var country = provider.GetCountryByCode(item.Code);
}

// GOOD - Reuse single instance
var provider = new CountryDataProvider();
foreach (var item in items)
{
    var country = provider.GetCountryByCode(item.Code);
}

// BAD - Calling GetCountriesByRegion in loops
foreach (var region in regions)
{
    var country = provider.GetCountriesByRegion(region).FirstOrDefault();  // O(n×m)!
}

// GOOD - Build your own index for repeated lookups
var regionIndex = provider.GetAllCountries()
    .SelectMany(c => c.Regions.Select(r => new { Region = r.Name, Country = c }))
    .ToDictionary(x => x.Region, x => x.Country, StringComparer.OrdinalIgnoreCase);

Contributing

Contributions are welcome! Please:

  1. Fork the repository
  2. Create a feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

License

This project is licensed under the MIT License - see the LICENSE file for details.


Acknowledgments

  • Country data based on ISO 3166-1 standards
  • Culture and region information from .NET CultureInfo and RegionInfo
  • Flag emojis using Unicode regional indicator symbols

Product Compatible and additional computed target framework versions.
.NET net5.0 was computed.  net5.0-windows was computed.  net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 is compatible.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
.NET Core netcoreapp2.0 was computed.  netcoreapp2.1 was computed.  netcoreapp2.2 was computed.  netcoreapp3.0 was computed.  netcoreapp3.1 was computed. 
.NET Standard netstandard2.0 is compatible.  netstandard2.1 was computed. 
.NET Framework net461 was computed.  net462 was computed.  net463 was computed.  net47 was computed.  net471 was computed.  net472 was computed.  net48 was computed.  net481 was computed. 
MonoAndroid monoandroid was computed. 
MonoMac monomac was computed. 
MonoTouch monotouch was computed. 
Tizen tizen40 was computed.  tizen60 was computed. 
Xamarin.iOS xamarinios was computed. 
Xamarin.Mac xamarinmac was computed. 
Xamarin.TVOS xamarintvos was computed. 
Xamarin.WatchOS xamarinwatchos was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages (1)

Showing the top 1 NuGet packages that depend on CountryData.Globalization:

Package Downloads
CountryData.Globalization.Hosting

Dependency injection extensions for CountryData.Globalization library. Provides seamless integration with Microsoft.Extensions.DependencyInjection for ASP.NET Core and other .NET applications. Includes service registration extensions and lifetime management for ICountryDataProvider. Install this package alongside CountryData.Globalization to enable DI support with AddCountryData() extension method.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.0.0 268 12/25/2025

Initial release v1.0.0:
- 250+ countries with comprehensive ISO 3166-1 data
- Administrative regions (states, provinces, territories)
- Currency information with multi-language support
- Phone codes and international dialing codes
- Full CultureInfo and RegionInfo integration
- O(1) dictionary lookups with lazy-loaded caches
- Thread-safe operations with immutable data collections
- Minimal external dependencies (only System.Text.Json)
- Multi-framework support (.NET Standard 2.0+, .NET 6, 8, 10)
- Works with .NET Framework 4.6.1+, .NET Core 2.0+, Unity, Xamarin
- Built-in dependency injection support via CountryData.Globalization.Hosting package