深入研究.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包对外提供基础实现,以内部线程池的形式对外提供管理任务执行,线程调 ...
随机推荐
- 20175305张天钰《java程序设计》第八周学习总结
<java程序设计>第八周学习总结 第十五章 泛型与集合框架 一.知识点学习 1.String类 1.String类不可以有子类. 2.用户无法输出String对象的引用,输出的是字符序列 ...
- java编写之jpg图片与base64编码之间的转换
/** * @author zyq * 将网络图片进行Base64位编码 * @param imgUrl * */ public static String encodeWebImageToBase6 ...
- unity下贴图混合(Texture Blending)
在unity制作自定义时,经常会遇到自定义妆容等问题,美术会提供大量的眉毛/胡子/腮红等贴图,来供用户选择. 美术给出的眉毛的小贴图如下: 在用户选用不同的胡子眉毛,可以将选定的小贴图和皮肤base贴 ...
- C++ 初读迭代器
迭代器 这是个啥? string对象或vector对象可以通过下标访问每一个元素,迭代器也具有同样的效果.那又有什么不同呢?事实上并不是所有的容器到可以使用下标访问每一个元素,即在容器上迭代器更具普适 ...
- Android Getting Started
Building Your First App Creating an Android Project 介绍如何Android开发环境,具体是:怎么使用Eclipse工具 Create a Proje ...
- iOS 获取app进程被杀死事件
程序被用户双击上滑杀死后,就对app做一些特殊的处理 下面的方法可以获取到用户双击上滑杀死的事件 - (void)applicationDidEnterBackground:(UIApplicatio ...
- 如何在浏览器中输入(myeclipse创建的项目的)地址访问JSP页面
如何在浏览器中输入(myeclipse创建的项目的)地址访问JSP页面 可以在Tomcat项目里面查看你的JSP页面在哪里,具体的路径为: tomcat--work--localhost--项目名称, ...
- 3.jmeter接口测试---脚本录制
安装好jmeter后,就要进入主题了,进行接口测试,接口测试的脚本获取方式 ①手动填写 ②badboy录制后,导入jmeter使用 ③jmeter录制 不会安装的可以进入这里:https://www. ...
- angular.isUndefined()
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title> ...
- SpringBoot报错:Failed to load ApplicationContext( Failed to bind properties under 'logging.level')
引起条件: SpringBoot2.0下yml文件配置SLF4j日志输出日志级别 logging: level: debug 解决方法: 指定系统包路径 logging: root: debug 指定 ...