[.Net5 实用笔记] i18n国际化配置

976 阅读3分钟

国际化是使应用程序可以自动适应不同语言和区域的功能,本地化是指应用程序可以支持不同语言的功能,在.net 5中,可以默认提供的本地化中间件快速实现。

具体实现

在Visual Studio中创建ASP.NET Core空模板的项目

1. 配置本地化资源和添加本地化中间件

在Startup.cs中配置本地化资源和添加本地化中间件

public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // 设置资源文件路径
        services.AddLocalization(options => options.ResourcesPath = "Resources");
        services.AddControllers();
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        // 确保本地化中间件在Endpoints中间件前
        app.UseRequestLocalization(options =>
        {
            // 配置可支持的语言
            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();
        });
    }
}

2. 添加本地化资源文件

  • 需要添加类SharedResources,注意namespace为项目根目录
  • 项目根目录创建Resources文件夹(该文件夹名称是上一步设置的ResourcesPath)
  • ResourcesPath中添加的文件名格式为{resources-class}.{culture}.resx

项目的目录结构 image.png

添加资源 image.png

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

4. 测试

默认支持以下三种方式设置Culture,使用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'
  • Header
curl --location --request GET 'http://localhost:5000/api/greet' \
--header 'Accept-Language: zh'
  • Cookie
curl --location --request GET 'http://localhost:5000/api/greet' \
--header 'Cookie: .AspNetCore.Culture=c=zh|uic=zh'

image.png

扩展

1. 配置Culture provider

本地化中间件中间默认支持Querystring,Header,和Cookie传递culture,如果需要自定义可以修改本地化中间件的配置

// 只支持request header中设置Accept-Language
public class Startup
{
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        app.UseRequestLocalization(options =>
        {
            options.RequestCultureProviders = new List<IRequestCultureProvider>
            {
                new AcceptLanguageHeaderRequestCultureProvider()
            };
        });
    }
}

如果默认的culture provider不满足需求时,需要在url路径中设置culture的情况,这时可以自定义Culture provider

例如以下代码实现了RequestCultureProvider,然后在DetermineProviderCultureResult方法中通过HttpContext获取到culture,如果没有找到culture,则返回NullProviderCultureResult,此时会使用本地化中间件设置的默认culture

// PathRequestCultureProvider.cs
// 使用{host}/zh/{template}中的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(new ProviderCultureResult(culture));
     }
 }
public class Startup
{
    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {

        app.UseRequestLocalization(options =>
        {
            options.RequestCultureProviders = new List<IRequestCultureProvider>
            {
                new PathRequestCultureProvider(supportedCultures)
            };
        });
    }
}

image.png

2. 配置本地化资源来源

上面的实例是使用共享resx资源文件存储本地化信息的,实际上可以使用其他文件格式或者外部的资源进行存储,如何使用请参考以下文档

如何实现一个自定义的本地化信息来源组件,挖个坑,以后有空会补上


参考文档

本地化、国际化、全球化是指什么?

ASP.NET Core 全球化和本地化 | Microsoft Docs