国际化是使应用程序可以自动适应不同语言和区域的功能,本地化是指应用程序可以支持不同语言的功能,在.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
项目的目录结构
添加资源
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'
扩展
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)
};
});
}
}
2. 配置本地化资源来源
上面的实例是使用共享resx资源文件存储本地化信息的,实际上可以使用其他文件格式或者外部的资源进行存储,如何使用请参考以下文档
- 使用JSON文件存储本地化信息:hishamco/My.Extensions.Localization.Json: JSON Localization Resources (github.com)
- 使用数据库存储本地化信息:damienbod/AspNetCoreLocalization: Localization.SqlLocalizer & ASP.NET Core MVC Localization Examples (github.com)
如何实现一个自定义的本地化信息来源组件,挖个坑,以后有空会补上