深入研究.NET Core的本地化机制
ASP.NET Core中提供了一些本地化服务和中间件,可将网站本地化为不同的语言文化。
ASP.NET Core中我们可以使用Microsoft.AspNetCore.Localization库来实现本地化。
在.NET Core 2.0以上版本, Microsoft.AspNetCore.Localization已经包含在了Microsoft.AspNetCore.All中,所以我们并不需要手动引入其他的类库。
创建一个MVC网站
为了测试ASP.NET Core的本地化,我们首先在Visual Studio 2017中创建一个MVC项目LocalizationSample。

配置Startup类
ASP.NET Core中,如果希望启动本地化,首先需要在Startup类的ConfigureServices方法中使用services.AddLocalization添加本地化服务。
public void ConfigureServices(IServiceCollection services)
{
services.AddLocalization(o =>
{
o.ResourcesPath = "Resources";
});
services.AddMvc();
}
在这个方法中,我们指定了文件夹Resources作为存放翻译文件的目录。
注: 如果不指定存放翻译文件的目录, ASP.NET Core会默认从网站根目录下读取。
然后我们需要在Configure方法中添加本地化中间件。
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
app.UseStaticFiles();
IList<CultureInfo> supportedCultures = new List<CultureInfo>
{
new CultureInfo("en-US"),
new CultureInfo("zh-CN"),
};
app.UseRequestLocalization(new RequestLocalizationOptions
{
DefaultRequestCulture = new RequestCulture("en-US"),
SupportedCultures = supportedCultures,
SupportedUICultures = supportedCultures
});
app.UseMvc(routes =>
{
routes.MapRoute(
name: "default",
template: "{controller=Home}/{action=Index}/{id?}");
});
}
app.UseRequestLocalization必须放置app.UseMvc之前DefaultRequestCulture参数指定了默认的语言文化,即用户不指定任何文化时的默认语言文化SupportedCultures和SupportedUICultures是指定当前应用支持的所有语言文化
注:
SupportedCultures指定的是数字和日期格式,SupportedUICultures指定的翻译文件
添加资源文件
下面我们尝试添加一个资源文件
- 首先我们创建一个Resources文件夹,这就是我们在前面
Startup类中配置的目录名。 - 然后我们在Resource文件夹中添加一个资源文件,并命名为Controllers.HomeController.zh-CN.resx。
- 在这个资源文件中,添加一个字段Hello, 并设置其值为“你好”。

在Controller中获取本地化字符串
现在我们打开默认生成的HomeController, 清空里面所有的action, 并添加一个新的action, 代码如下:
public class HomeController : Controller
{
public HomeController()
{
}
public IActionResult Hello()
{
return Content("Hello");
}
}
启动项目之后访问/Home/Hello, 结果如下

下面我们修改HomeController的代码, 来引入本地化字符串访问器
public class HomeController : Controller
{
private readonly IStringLocalizer<HomeController> _localizer;
public HomeController(IStringLocalizer<HomeController> localizer)
{
_localizer = localizer;
}
public IActionResult Hello()
{
return Content(_localizer["Hello"]);
}
}
代码解释
IStringLocalizer是一个本地化字符串访问器的泛型接口,这里我们通过依赖注入的方式在HomeController的构造函数中将其注入- 我们可以通过IStringLocalizer的属性访问器获取到对应字段在不同语言下的文本。
最终效果
现在我们启动程序, 重新访问/Home/Hello, 结果如下

你会发现结果没有变化,这是因为默认我们设置的语言文化是en-US, 但是我们之前没有添加en-US的资源文件,所以程序就直接将访问的字段名输出了。
现在我们修改URL, 访问/Home/Hello?ui-culture=zh-CN, 结果如下

我们期望的“你好”被正确输出了,这说明ASP.NET Core默认支持在Url中以culture参数的形式设置当前网站使用的语言文化。
资源文件命名
为什么我们之前添加了一个名为Controllers.HomeController.zh-CN.resx的资源文件,本地化字符串访问器IStringLocalizer就能定位到这个文件并读取其中的字段属性呢?
这是由ASP.NET Core资源文件的命名约定决定的。
ASP.NET Core资源文件的名称由2部分组成:
- 去掉程序集名称的完整类名
- 语言文化名称
以前面的例子为例:
我们创建了一个本地化字符串访问器接口,它的泛型类型是HomeController, 其完整类名是LocalizationSample.Controllers.HomeController, 当前程序集的名称是LocalizationSample, 所以去掉程序集名称之后,剩余部分是Controllers.HomeController。当我们设置culture参数是zh-CN时, ASP.NET Core查找的资源文件名是Controllers.HomeController.zh-CN.resx, 这正是我们前面添加的中文语言文化资源文件名。
如果你不喜欢这种方式,ASP.NET Core还提供了另外一种资源文件的组织方式
你可以Resources目录下创建以下目录结构
- Resources
- Controllers
- HomeController.zh-CN.resx
- Controllers
本地化字符串访问器也能自动定位到这个文件。
默认的语言文化提供器
ASP.NET Core的本地化中间件默认支持3种语言文化提供器
- URL中的查询字符串
- Cookie
- 请求头
URL中的查询字符串
ASP.NET Core会从URL中的culture参数中获取当前应用使用的语言文化,这就是前面例子中,“你好”能正确输出的原因
除了指定ui-culture参数,你还可以使用culture参数指定当前格式化时间,数字等所使用的语言文化。
?culture=zh-CN&ui-culture=zh-CN
?culture=zh-CN
?ui-culture=zh-CN
Tips: 当只指定culture或ui-culture参数时,ASP.NET Core会自动将culture和ui-culture设置成一样的。即?culture=zh-CN等同于?culture=zh-CN&ui-culture=zh-CN
Cookie
ASP.NET Core中还支持使用Cookie的方式设置当前应用使用的语言文化。默认使用的Cookie名称是.AspNetCore.Culture。
.AspNetCore.Culture的值格式如下
c=zh-CN|uic=zh-CN
c=zh-CN
uic=zh-CN
其中c表示culture, uic表示ui-culture。
下面我们使用Chrome的开发者工具, 为当前网页添加语言文化Cookie

然后我们访问/Home/Hello, "你好"也被正确的输出了

这说明ASP.NET Core从Cookie中读取到了语言文化配置
请求头
除了URL查询字符串和Cookie, ASP.NET Core还支持在请求头中指定语言文化。请求头中语言文化字段名称是 Accept-Language。
Accept-Language的文档,参见https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Headers/Accept-Language
这里我们使用Postman来测试一下,我们设置Accept-Language为zh-CN, zh;q=0.9, 结果如下

如何在View中使用本地化
除了Controller, 我们更多的是在View中使用本地化。
如果希望在View中使用本地化,首先需要在Startup类的ConfigureServices方法中启用View本地化。
public void ConfigureServices(IServiceCollection services)
{
services.AddMvc()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix);
}
这里LanguageViewLocationExpanderFormat支持2种方式,这个和前面Controller的本地化文件名称约定类似
- Suffix, 例/Resources/Home/Hello.zh-CN.resx
- Path, 例/Resources/Home/zh-CN/Hello.resx
下面我们修改HomeController的代码,Hello方法将返回一个View
HomeController
public IActionResult Hello()
{
//return Content(_localizer["Hello"]);
return View();
}
Hello.cshtml
@{
ViewData["Title"] = "Hello";
}
<h2>Good Bye</h2>
然后我们创建如下图的目录结构, 并创建资源文件Hello.zh-CN.resx, 并添加GoodBye字段,其值为"再见"


使用ViewLocalizer
ViewLocalizer类可以帮助我们在Razor视图中使用本地化文本。现在我们来修改Hello.cshtml, 在文件添加本地化引用,并注入一个ViewLocalizer对象
@using Microsoft.AspNetCore.Mvc.Localization
@inject IViewLocalizer Localizer
@{
ViewData["Title"] = "Hello";
}
<h2>@Localizer["GoodBye"]</h2>
这里我们使用ViewLocalizer读取了本地化文本,它的用法和IStringLocalier一样,都是通过属性访问器访问对应字段的本地化文本。
最终效果
现在我们运行程序并访问/Home/Hello, 结果如下

然后我们继续访问/Home/Hello?ui-culture=zh-CN, 结果如下

本地化字符串读取成功
本篇源代码 https://github.com/lamondlu/aspnetcore_localizationsample
深入研究.NET Core的本地化机制的更多相关文章
- 集群环境下,你不得不注意的ASP.NET Core Data Protection 机制
引言 最近线上环境遇到一个问题,就是ASP.NET Core Web应用在单个容器使用正常,扩展多个容器无法访问的问题.查看容器日志,发现以下异常: System.Security.Cryptogra ...
- .Net core 的热插拔机制的深入探索,以及卸载问题求救指南.
.Net core 的热插拔机制的深入探索,以及卸载问题求救指南. 一.依赖文件*.deps.json的读取. 依赖文件内容如下.一般位于编译生成目录中 { "runtimeTarget&q ...
- 深入研究EF Core AddDbContext 引起的内存泄露的原因
前两天逛园子,看到 @Jeffcky 发的这篇文章<EntityFramework Core依赖注入上下文方式不同造成内存泄漏了解一下>. 一开始只是粗略的扫了一遍没仔细看,只是觉得是多次 ...
- .NetCore技术研究-EntityFramework Core 3.0 Preview
前段时间.Net Core 3.0 发布了,Entity Framework Core 3.0 也发布了Preview版.假期用了一上午大致研究了一遍,同时又体验了一把Visual Studio 20 ...
- C#入门篇6-8:字符串操作 深入研究字符串的内存驻留机制
//字符串的内存驻留机制 public static void Test() { //当有多个字符串变量包含了同样的字符串实际值时, //CLR可能不会为它们重复地分配内存,而是让它们统统指向同一个字 ...
- 深入研究React setState的工作机制
前言 上个月发表了一篇 React源码学习--ReactClass,但是后来我发现,大家对这种大量贴代码分析源码的形式并不感冒.讲道理,我自己看着也烦,还不如自己直接去翻源码来得痛快.吸取了上一次的教 ...
- 【Java深入研究】4、fail-fast机制
在JDK的Collection中我们时常会看到类似于这样的话: 例如,ArrayList: 注意,迭代器的快速失败行为无法得到保证,因为一般来说,不可能对是否出现不同步并发修改做出任何硬性保证.快速失 ...
- .Net Core 全球化&本地化的使用
官网文档 nuget地址 创建资源文件 添加资源文件 实施策略 配置本地化 本地化中间件 使用 视图本地化 DataAnnotations 本地化 Make the app's content loc ...
- 【Java 线程的深入研究4】ThreadPoolExecutor运转机制详解
hreadPoolExecutor机制 一.概述 1.ThreadPoolExecutor作为java.util.concurrent包对外提供基础实现,以内部线程池的形式对外提供管理任务执行,线程调 ...
随机推荐
- selenium操作浏览器的前进和后退
前进关键字:driver.forward() 后退关键字:driver.back() 测试对象:1.https://www.baidu.com/ 2.https://www.sogou.com/ 实例 ...
- [开源]使用C# 对CPU卡基本操作封装
Github 地址:https://github.com/zifeiniu/CPUCardLib 项目需求及简介: 公司要求将用户相关的信息储存到射频卡中,之前项目使用的Mifare类型卡,只储存了用 ...
- [SCOI2015]国旗计划
Description: A 国正在开展一项伟大的计划 -- 国旗计划.这项计划的内容是边防战士手举国旗环绕边境线奔袭一圈.这项计划需要多名边防战士以接力的形式共同完成,为此,国土安全局已经挑选了 \ ...
- 接口测试——postman & jmeter
新名词: 自动化测试:写代码帮你测试 接口:是一个抽象的概念,一种交互关系. 抓包:拦截请求. 接口测试:就是功能测试,比后者还简单. 需要有测试文档,包括项目.模块.URL.请求方式.参数.参数说明 ...
- vijos搭建踩坑
nodejs我用的8.x版本,可以工作. 和制作组交谈之后他们说最好榨汁机和主机不要在同一系统下. vj4/vj4/handler/base.py的第343行 从 super(Connection, ...
- 等高布局display:table
display:table用法: 父元素:display:table; 子元素:display:table-cell; 注:使用display:table-cell元素部分出现空白缝隙的问题:设置 . ...
- Docker安装及基本操作
系统环境 CentOS Linux release 7.5.1804 (Core) 安装依赖包 更新系统软件 yum update 安装docker yum install docker 启动dock ...
- mybatis invalid comparison: java.sql.Timestamp and java.lang.String报错解决方法
这个错的意思是:java.sql.Timestamp和java.lang.String无效的比较 错误的原因是:拿传入的时间类型参数与空字符串进行比较就会报这个异常 解决方法:只保留非null判断就可 ...
- 微信小程序中的AJAX——POST,GET区别
注意:发送服务器时的DATA 最终发送给服务器的数据是 String 类型,如果传入的 data 不是 String 类型,会被转换成 String .转换规则如下: 对于 GET 方法的数据,会将数 ...
- DOS命令(一)
1. echo 输出内容,用来输出文字. [例如:echo hello] 2. titile 标题,用来修改标题. 3. color 背景色前景色,用来设置背景色和前景色 0 = 黑色 8 = 灰色 ...