Reaching Global Audiences
Imagine launching an e-commerce site that needs to serve customers in Germany, Japan, and Brazil. Each market expects prices in local currency, dates in familiar formats, and UI text in their language. Hardcoding "Welcome" and "$99.99" won't cut it.
.NET's globalization framework handles culture-specific formatting automatically through CultureInfo. Localization features let you store translated strings in resource files and load them based on user preference. Together, these make multilingual sites manageable.
You'll learn how CultureInfo formats dates and numbers, how resource files organize translations, and how ASP.NET Core middleware detects user language. By the end, you'll build sites that adapt seamlessly to any culture.
Understanding CultureInfo
CultureInfo represents a specific culture with formatting rules for dates, numbers, and currency. Every thread has CurrentCulture for formatting and CurrentUICulture for resource loading. Setting these controls how your app displays data.
Culture names follow ISO standards: "en-US" for US English, "de-DE" for German, "ja-JP" for Japanese. Neutral cultures like "en" lack region-specific rules. Always use specific cultures when formatting to avoid ambiguity.
using System.Globalization;
var date = new DateTime(2025, 11, 4);
var price = 1234.56m;
// US English
CultureInfo.CurrentCulture = new CultureInfo("en-US");
Console.WriteLine($"US: {date:D} - {price:C}");
// German
CultureInfo.CurrentCulture = new CultureInfo("de-DE");
Console.WriteLine($"DE: {date:D} - {price:C}");
// Japanese
CultureInfo.CurrentCulture = new CultureInfo("ja-JP");
Console.WriteLine($"JP: {date:D} - {price:C}");
// Output:
// US: Tuesday, November 4, 2025 - $1,234.56
// DE: Dienstag, 4. November 2025 - 1.234,56 €
// JP: 2025年11月4日火曜日 - ¥1,235
The same date and decimal format differently based on culture. CultureInfo handles decimal separators, currency symbols, date ordering, and even digit grouping automatically. You write format strings once and they adapt.
Organizing Translations with Resource Files
Resource files (.resx) store translations as key-value pairs. Create a base file like Resources.resx for default language, then culture-specific files like Resources.de.resx for German. .NET selects the appropriate file based on CurrentUICulture.
The resource manager searches for the most specific culture file available, falling back to neutral cultures then the default. This lets you provide broad translations and override specific regions as needed.
// Resources.resx (default - English):
// Key: Greeting, Value: Hello
// Key: Farewell, Value: Goodbye
// Resources.de.resx (German):
// Key: Greeting, Value: Hallo
// Key: Farewell, Value: Auf Wiedersehen
// Resources.ja.resx (Japanese):
// Key: Greeting, Value: こんにちは
// Key: Farewell, Value: さようなら
using System.Resources;
var rm = new ResourceManager("MyApp.Resources", typeof(Program).Assembly);
CultureInfo.CurrentUICulture = new CultureInfo("en");
Console.WriteLine(rm.GetString("Greeting")); // Hello
CultureInfo.CurrentUICulture = new CultureInfo("de");
Console.WriteLine(rm.GetString("Greeting")); // Hallo
CultureInfo.CurrentUICulture = new CultureInfo("ja");
Console.WriteLine(rm.GetString("Greeting")); // こんにちは
Resource Manager loads the correct file automatically. If Resources.de.resx is missing a key, it falls back to Resources.resx. This graceful degradation prevents missing translations from breaking your app.
ASP.NET Core Localization Middleware
ASP.NET Core's RequestLocalizationMiddleware detects user language from headers, cookies, or query strings. It sets CultureInfo automatically before your controllers run. Configure supported cultures and default fallback in your startup code.
The middleware checks providers in order: query string, cookie, Accept-Language header. This lets users override browser defaults with a language selector that sets a preference cookie.
using Microsoft.AspNetCore.Localization;
using System.Globalization;
var builder = WebApplication.CreateBuilder(args);
// Configure supported cultures
var supportedCultures = new[]
{
new CultureInfo("en-US"),
new CultureInfo("de-DE"),
new CultureInfo("ja-JP")
};
builder.Services.Configure<RequestLocalizationOptions>(options =>
{
options.DefaultRequestCulture = new RequestCulture("en-US");
options.SupportedCultures = supportedCultures;
options.SupportedUICultures = supportedCultures;
});
var app = builder.Build();
app.UseRequestLocalization();
app.MapGet("/", () =>
{
var culture = CultureInfo.CurrentCulture;
var price = 99.99m;
return $"Culture: {culture.Name}, Price: {price:C}";
});
app.Run();
Users get content in their browser's language automatically. Add a language switcher that sets a cookie, and they can override the default. The middleware handles detection complexity so your controllers just read CultureInfo.
Try It Yourself
Build a simple culture switcher that demonstrates formatting changes. You'll see dates, numbers, and currency adapt as you change cultures.
Steps
- Create:
dotnet new console -n CultureSwitch
- Navigate:
cd CultureSwitch
- Replace Program.cs with the code below
- Run:
dotnet run
using System.Globalization;
var cultures = new[] { "en-US", "de-DE", "ja-JP", "fr-FR" };
var date = DateTime.Now;
var price = 1499.99m;
foreach (var cultureName in cultures)
{
var culture = new CultureInfo(cultureName);
CultureInfo.CurrentCulture = culture;
Console.WriteLine($"\n{culture.DisplayName}:");
Console.WriteLine($" Date: {date:D}");
Console.WriteLine($" Price: {price:C}");
Console.WriteLine($" Number: {123456.78:N2}");
}
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<Nullable>enable</Nullable>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
</Project>
What you'll see
English (United States):
Date: Tuesday, November 4, 2025
Price: $1,499.99
Number: 123,456.78
German (Germany):
Date: Dienstag, 4. November 2025
Price: 1.499,99 €
Number: 123.456,78
Japanese (Japan):
Date: 2025年11月4日火曜日
Price: ¥1,500
Number: 123,456.78
French (France):
Date: mardi 4 novembre 2025
Price: 1 499,99 €
Number: 123 456,78
Notice how decimal separators, thousand separators, currency symbols, and date formats all change automatically. CultureInfo handles these details so you don't hardcode formatting logic.