Internationalization is the ability of an application to automatically adapt to different languages and regions, and localization is the ability of an application to support different languages. In.NET 5, localization middleware is provided by default for fast implementation.

The specific implementation

A project that creates an ASP.NET Core empty template in Visual Studio

1. Configure localized resources and add localized middleware

Configure localized resources and add localized middleware in startup. cs

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // Set the resource file path
        services.AddLocalization(options => options.ResourcesPath = "Resources");
        services.AddControllers();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        // Make sure local middleware is in front of Endpoints middleware
        app.UseRequestLocalization(options =>
        {
            // Configure the supported languages
            var supportedCultures = new List<CultureInfo>
            {
                new ("en"),
                new ("zh")}; options.DefaultRequestCulture =new RequestCulture("en"); options.SupportedCultures = supportedCultures; options.SupportedUICultures = supportedCultures; }); app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapControllers(); }); }}Copy the code

2. Add the localized resource file

  • Class SharedResources needs to be added. Note that namespace is the project root directory
  • Create the Resources folder in the project root (this folder is named ResourcesPath from the previous step)
  • The file name format added to ResourcesPath is {resources-class}.{culture}.resx

The directory structure of the project

Add the resource

Use 3.

[Route("[controller]")]
public class GreetController : ControllerBase
{
    private readonly IStringLocalizer<SharedResources> _localizer;

    public GreetController(IStringLocalizer<SharedResources> localizer)
    {
        _localizer = localizer;
    }

    [HttpGet]
    public string Hello()
    {
        return _localizer["hello"]; }}Copy the code

4. Test

By default, you can set Culture in the following three ways and access it using Postman

  • Querystring
curl --location --request GET 'http://localhost:5000/api/greet? culture=zh'
curl --location --request GET 'http://localhost:5000/api/greet? ui-culture=zh'
Copy the code
  • Header
curl --location --request GET 'http://localhost:5000/api/greet' \
--header 'Accept-Language: zh'
Copy the code
  • Cookie
curl --location --request GET 'http://localhost:5000/api/greet' \
--header 'Cookie: .AspNetCore.Culture=c=zh|uic=zh'
Copy the code

extension

1. Configure the Culture Provider

The native middleware supports Querystring, Header, and Cookie passing culture by default, and can be modified if customized

// Only the accept-language of the request header is supported
public class Startup
{
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseRequestLocalization(options =>
        {
            options.RequestCultureProviders = new List<IRequestCultureProvider>
            {
                newAcceptLanguageHeaderRequestCultureProvider() }; }); }}Copy the code

If the default culture provider does not meet requirements, you need to set the culture in the URL path. In this case, you can customize the culture provider

For example the following code to achieve the RequestCultureProvider, then through HttpContext access to culture in DetermineProviderCultureResult method, if not found culture, It returns NullProviderCultureResult, at this time will use middleware set the default culture localization

// PathRequestCultureProvider.cs
// Use {host}/zh/{template} as the zh culture
public class PathRequestCultureProvider : RequestCultureProvider
{
    private readonly List<string> _cultures;

    public PathRequestCultureProvider(List<CultureInfo> cultureInfos)
    {
        _cultures = cultureInfos == null
            ? new List<string>()
            : cultureInfos.Select(x => x.TwoLetterISOLanguageName).ToList();
    }

    public override Task<ProviderCultureResult> DetermineProviderCultureResult(HttpContext httpContext)
    {
        var path = httpContext.Request.Path;
        if (path == null || string.IsNullOrWhiteSpace(path.Value))
        {
            return NullProviderCultureResult;
        }

        var pathParts = path.Value.Split('/');
        var pathPartOne = pathParts[1];
        var culture = _cultures.FirstOrDefault(x => 
            string.Equals(pathPartOne, x, StringComparison.OrdinalIgnoreCase));

        return string.IsNullOrWhiteSpace(culture)
            ? NullProviderCultureResult
            : Task.FromResult(newProviderCultureResult(culture)); }}Copy the code
public class Startup
{
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {

        app.UseRequestLocalization(options =>
        {
            options.RequestCultureProviders = new List<IRequestCultureProvider>
            {
                newPathRequestCultureProvider(supportedCultures) }; }); }}Copy the code

2. Configure the local resource source

The example above uses a shared RESX resource file to store localization information. In fact, it can be stored using other file formats or external resources. See the following documentation for how to use this information

  • Using JSON file storage Localization information: hishamco/My Extensions. Localization. JSON: JSON Localization Resources (github.com)
  • Using a database to store the localization information: damienbod/AspNetCoreLocalization: Localization.SqlLocalizer & ASP.NET Core MVC Localization Examples (github.com)

How to implement a custom localized information source component that digs a hole to be filled later


Reference documentation

What do we mean by localization, internationalization and globalization?

ASP.NET, the Core of globalization and localization | Microsoft Docs