This blog post is part of the C# Advent 2024 calendar! Be sure to check it out for more great articles on C# and .NET.
When building applications for users around the world, it's important to support different languages and regional settings. This process, called localization, helps make your application more accessible to users from different countries and cultures. In this guide, we'll learn how to add localization to an ASP.NET Core Web API using a practical example.
What is Localization?
Localization (often shortened to L10n) means adapting your application to support different languages and regional settings. For web APIs, this means sending responses in the user's preferred language. ASP.NET Core makes this easy with built-in localization support.
Let's build a simple Web API that returns user information in different languages. We'll work with a basic user profile that includes name, age, and gender fields. Our example will show how to display the gender field in both English and French, based on what language the client requests.
Creating the Sample Application
1. Set Up the Project
First, create a new Web API project using either the .NET CLI or Visual Studio:
dotnet new webapi -n WebApiLocalization
cd WebApiLocalization
2. Define the Data Models
Create the User class and Gender enum to represent our data:
public class User
{
public int Id { get; set; }
public string Name { get; set; }
public Gender Gender { get; set; }
}
public enum Gender
{
Male,
Female,
Other
}
3. Add Sample Data
Create a helper class to provide some test data:
public static class DataHelper
{
public static List<User> GetUsers()
{
return
[
new User { Id = 1, Name = "Alice", Gender = Gender.Female },
new User { Id = 2, Name = "Bob", Gender = Gender.Male },
new User { Id = 3, Name = "Gamma", Gender = Gender.Other }
];
}
}
4. Set Up Resource Files
Resource files store our translated text. Here's how to set them up:
Create a
Resources
folder in your projectAdd a marker class called
SharedResource
:
public class SharedResource
{
}
Add two resource files:
SharedResource.en.resx
for EnglishSharedResource.fr.resx
for French
Add these translations to your resource files:
SharedResource.en.resx:
Female → Female
Male → Male
Other → Other
Female → Femme
Male → Homme
Other → Autre
5. Create the Localization Service
We'll create a custom service to handle translations:
public interface IAppLocalizer
{
string Localize(string key);
}
public class AppLocalizer : IAppLocalizer
{
private readonly IStringLocalizer _localizer;
public AppLocalizer(IStringLocalizerFactory factory)
{
var type = typeof(SharedResource);
var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName);
_localizer = factory.Create("SharedResource", assemblyName.Name);
}
public string Localize(string key) => _localizer[key];
}
In .NET Core, the IStringLocalizer<T>
interface is commonly used to handle string localization. In our custom localizer service (AppLocalizer
), instead of directly using IStringLocalizer<T>
, we inject an instance of IStringLocalizerFactory
. This factory allows us to dynamically create an IStringLocalizer
specifically tied to the SharedResource
class. We can now use this AppLocalizer
class for localizing any translation string from our shared resource file.
6. Configure the Application
Update your Program.cs
to enable localization:
var builder = WebApplication.CreateBuilder(args);
// Add localization services
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");
builder.Services.AddScoped<IAppLocalizer, AppLocalizer>();
builder.Services.AddControllers();
builder.Services.AddOpenApi();
var app = builder.Build();
if (app.Environment.IsDevelopment())
{
app.MapOpenApi();
}
// Set up supported languages
var supportedCultures = new[] { "en", "fr" };
var localizationOptions = new RequestLocalizationOptions()
.SetDefaultCulture(supportedCultures[0])
.AddSupportedCultures(supportedCultures)
.AddSupportedUICultures(supportedCultures);
localizationOptions.RequestCultureProviders.Insert(0, new AcceptLanguageHeaderRequestCultureProvider());
app.UseRequestLocalization(localizationOptions);
app.UseAuthorization();
app.MapControllers();
app.Run();
By configuring the request localization middleware, we are performing the following.
We define the supported cultures by our API. We are defining English (en) and French (fr) as the supported cultures.
We set the default culture to English by calling the
SetDefaultCulture(supportedCultures[0])
which specifies the fallback culture if no/unsupported culture is specified in the request.app.UseRequestLocalization(localizationOptions)
activates middleware to:Detect the culture from incoming requests (e.g., Accept-Language header).
Set the application's culture for formatting and resource localization.
7. Create the API Endpoint
First, create a DTO to shape our response:
public class UserDto
{
public int Id { get; set; }
public string Name { get; set; }
public string Gender { get; set; }
}
Then create the controller:
[ApiController]
public class UserController(IAppLocalizer localizer) : ControllerBase
{
[HttpGet("/users/{id}")]
public IActionResult Get(int id)
{
var user = DataHelper.GetUsers().FirstOrDefault(u => u.Id == id);
var userDto = new UserDto
{
Id = user.Id,
Gender = localizer.Localize(user.Gender.ToString()),
Name = user.Name
};
return Ok(userDto);
}
}
The controller class accepts an instance of IAppLocalizer through dependency injection and we can use that instance to localize the Gender property.
8. Testing the API
You can test the API using cURL or any API testing tool. Here's how to test for different languages:
For English:
curl -X GET "http://localhost:5127/users/1" -H "Accept-Language: en"
For French:
curl -X GET "http://localhost:5127/users/1" -H "Accept-Language: fr"
We can see that the gender field is localized.
If you don't specify a language or use an unsupported one, the API will default to English.
Summary
We've created a Web API that can respond in different languages using ASP.NET Core's localization features. The key points we covered:
Setting up resource files for different languages
Creating a custom localization service
Configuring the application to handle language preferences
Building an API endpoint that returns localized data
This approach makes it easy to add support for more languages later - just add new resource files for each language you want to support.