Implementing Localization in ASP.NET Core Web API

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

Set Up the Project

First, create a new Web API project using either the .NET CLI or Visual Studio. I am using .NET 9 in this article.

dotnet new webapi -n WebApiLocalization
cd WebApiLocalization

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
}

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 }
        ];
    }
}

Set Up Resource Files

Resource files store our translated text. Here's how to set them up.

  1. Create a Resources folder in your project
  2. Add a marker class called SharedResource.
public class SharedResource
{
}

Add two resource files

  • SharedResource.en.resx for English
  • SharedResource.fr.resx for French

Add these translations to your resource files.

SharedResource.en.resx.

  • Female → Female
  • Male → Male
  • Other → Other

SharedResource.fr.resx.

  • Female → Femme
  • Male → Homme
  • Other → Autre

Resource

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.

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.

  1. We define the supported cultures by our API. We are defining English (en) and French (fr) as the supported cultures.
  2. 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.
  3. 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.

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.

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"

English

For French

curl -X GET "http://localhost:5127/users/1" -H "Accept-Language: fr"

French

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.

  1. Setting up resource files for different languages
  2. Creating a custom localization service
  3. Configuring the application to handle language preferences
  4. 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.


Similar Articles