MSDN Docs

Globalization & Localization in .NET

Overview

.NET provides robust support for building applications that can adapt to different cultures, languages, and regional settings. This includes:

Working with CultureInfo

The System.Globalization.CultureInfo class represents information about a specific culture. Use it to format data or to change the current thread’s culture:

using System;
using System.Globalization;

CultureInfo german = new CultureInfo("de-DE");
decimal price = 1234.56m;

Console.WriteLine(price.ToString("C", german)); // €1.234,56

Resource Files

Store localized strings in .resx files. Create a base file (e.g., Resources.resx) and additional files for each culture (Resources.fr.resx, Resources.ja.resx, …).

public class LocalizedStrings
{
    private static ResourceManager _rm = new ResourceManager("MyApp.Resources", typeof(LocalizedStrings).Assembly);
    public static string Welcome => _rm.GetString("Welcome");
}

Culture‑Aware Formatting

Use the String.Format overload that accepts an IFormatProvider or the ToString overload with a format provider.

DateTime now = DateTime.Now;
Console.WriteLine(now.ToString("D", new CultureInfo("ja-JP"))); // 2025年9月10日

Complete Example

This sample demonstrates a simple console app that switches cultures at runtime and retrieves localized strings.

using System;
using System.Globalization;
using System.Resources;
using System.Threading;

class Program
{
    static void Main()
    {
        // Simulate user selection
        Console.WriteLine("Select language: (1) English  (2) French");
        var choice = Console.ReadKey().KeyChar;
        CultureInfo selected = choice == '2' ? new CultureInfo("fr-FR") : new CultureInfo("en-US");
        Thread.CurrentThread.CurrentCulture = selected;
        Thread.CurrentThread.CurrentUICulture = selected;

        ResourceManager rm = new ResourceManager("MyApp.Resources", typeof(Program).Assembly);
        Console.WriteLine();
        Console.WriteLine(rm.GetString("Greeting"));
        Console.WriteLine(DateTime.Now.ToString("F"));
    }
}

Best Practices

Further Reading