在.NET Core项目中也是可以使用.resx资源文件,来为程序提供多语言支持。以下我们就以一个.NET Core控制台项目为例,来讲解资源文件的使用。

新建一个.NET Core控制台项目,然后我们在其中新建一个.resx资源文件叫DemoResource.resx

注意.resx资源文件默认是Internal访问级别的,这会导致其它程序集无法访问资源文件类,所以我们最好将其改为Public访问级别

然后我们在资源文件DemoResource.resx中定义一个字符串叫"Message",值为"Hello",如下所示:

由于资源文件是支持多语言的,其文件名命名格式如下:

{资源文件名}.{语言文化名称}.resx

其中{语言文化名称}就是诸如:zh-CN、en-US、ja-JP等语言字符串,代表了一种特定的语言,例如zh-CN就是简体中文。

所以现在我们就为资源文件DemoResource.resx再创造两种语言:

DemoResource.zh-CN.resx,简体中文资源文件:

DemoResource.ja-JP.resx,日语资源文件:

所以我们现在,就有三个资源文件:

  • DemoResource.resx是默认的资源文件,我们将其内部的字符串Message定义为了英文。
  • DemoResource.zh-CN.resx是简体中文资源文件,我们将其内部的字符串Message定义为了简体中文。
  • DemoResource.ja-JP.resx是日语资源文件,我们将其内部的字符串Message定义为了日语。

其实它们代表的都是DemoResource资源文件,只不过是不同的语言版本罢了,现在项目结构如下所示:

好了,现在定义好了资源文件,我们就来看看怎么使用它们。

在.NET Core中.resx资源文件是和线程的语言相关,其主要和当前线程的如下两个语言属性相关:

  • Thread.CurrentThread.CurrentCulture
  • Thread.CurrentThread.CurrentUICulture

如果当前线程的这两个属性是什么语言,那么.resx资源文件就会返回对应语言的内容。

首先我们在.NET Core控制台项目的Main方法中,设置当前线程的CurrentCulture和CurrentUICulture为zh-CN:

static void Main(string[] args)
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("zh-CN");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("zh-CN"); Console.WriteLine($"Message为:{DemoResource.Message}"); Console.WriteLine("按任意键结束...");
Console.ReadKey();
}

运行结果如下,我们可以看到显示的Message为中文"你好"

现在我们将当前线程的CurrentCulture和CurrentUICulture设置为ja-JP:

static void Main(string[] args)
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("ja-JP");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("ja-JP"); Console.WriteLine($"Message为:{DemoResource.Message}"); Console.WriteLine("按任意键结束...");
Console.ReadKey();
}

运行结果如下,我们可以看到显示的Message为日文"こんにちは"

然后,我们将当前线程的CurrentCulture和CurrentUICulture设置为fr-FR,代表法语:

static void Main(string[] args)
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("fr-FR");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("fr-FR"); Console.WriteLine($"Message为:{DemoResource.Message}"); Console.WriteLine("按任意键结束...");
Console.ReadKey();
}

那么现在结果是什么呢,如下所示:

可能很多同学会觉得很奇怪为什么Message显示的是英语"Hello"。其实道理很简单,因为我们没有定义DemoResource.fr-FR.resx这个法语资源文件啊,所以在当前线程的CurrentCulture和CurrentUICulture为fr-FR时,调用DemoResource.Message时,.NET Core只好使用DemoResource默认资源文件DemoResource.resx的内容,所以DemoResource.Message输出的是英文"Hello"。

其实资源文件类DemoResource也是可以通过设置其Culture属性来指定使用某一种特定的语言,如下代码所示,虽然我们设置当前线程的CurrentCulture和CurrentUICulture为ja-JP,但是由于我们设置了DemoResource.Culture为zh-CN:

static void Main(string[] args)
{
Thread.CurrentThread.CurrentCulture = new CultureInfo("ja-JP");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("ja-JP"); DemoResource.Culture = new CultureInfo("zh-CN"); Console.WriteLine($"Message为:{DemoResource.Message}"); Console.WriteLine("按任意键结束...");
Console.ReadKey();
}

所以最后显示的Message为中文"你好"

Async和Await模式对线程语言的影响

有的同学可能会想.NET Core中的Async和Await模式,会对Thread.CurrentThread.CurrentCulture和Thread.CurrentThread.CurrentUICulture这两个线程的语言属性产生影响吗。

我们来看看如下代码:

/// <summary>
/// 测试Async和Await模式,是否会对Thread.CurrentThread.CurrentCulture和Thread.CurrentThread.CurrentUICulture产生影响
/// </summary>
static void AsyncAwaitThreadCulture()
{
//设置主线程的CurrentCulture和CurrentUICulture为语言ja-JP
Thread.CurrentThread.CurrentCulture = new CultureInfo("ja-JP");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("ja-JP"); Console.WriteLine($"Thread id:{Thread.CurrentThread.ManagedThreadId.ToString()}=>主线程的CurrentCulture是{Thread.CurrentThread.CurrentCulture.ToString()}, CurrentUICulture是{Thread.CurrentThread.CurrentUICulture.ToString()}"); //通过Task来启动第一层线程
Task.Run(async () =>
{
Console.WriteLine($"Thread id:{Thread.CurrentThread.ManagedThreadId.ToString()}=>第一层线程的CurrentCulture是{Thread.CurrentThread.CurrentCulture.ToString()}, CurrentUICulture是{Thread.CurrentThread.CurrentUICulture.ToString()}"); //通过Task来启动第二层线程
Task task = Task.Run(() =>
{
Console.WriteLine($"Thread id:{Thread.CurrentThread.ManagedThreadId.ToString()}=>第二层线程的CurrentCulture是{Thread.CurrentThread.CurrentCulture.ToString()}, CurrentUICulture是{Thread.CurrentThread.CurrentUICulture.ToString()}"); //通过Thread来启动第三层线程
Thread th = new Thread(new ThreadStart(() =>
{ Thread.Sleep(); Console.WriteLine($"Thread id:{Thread.CurrentThread.ManagedThreadId.ToString()}=>第三层线程的CurrentCulture是{Thread.CurrentThread.CurrentCulture.ToString()}, CurrentUICulture是{Thread.CurrentThread.CurrentUICulture.ToString()}");
})); th.IsBackground = true;
th.Start(); th.Join();//阻塞第二层线程,直到第三层线程th结束
}); Thread.Sleep(); Console.WriteLine($"Thread id:{Thread.CurrentThread.ManagedThreadId.ToString()}=>await之前CurrentCulture是{Thread.CurrentThread.CurrentCulture.ToString()}, CurrentUICulture是{Thread.CurrentThread.CurrentUICulture.ToString()}"); await task;//await,直到第二层线程结束 Console.WriteLine($"Thread id:{Thread.CurrentThread.ManagedThreadId.ToString()}=>await之后CurrentCulture是{Thread.CurrentThread.CurrentCulture.ToString()}, CurrentUICulture是{Thread.CurrentThread.CurrentUICulture.ToString()}"); }).Wait();//阻塞主线程,直到第一层线程执行完毕
}

运行结果如下所示:

我们在AsyncAwaitThreadCulture方法中,将主线程的CurrentCulture和CurrentUICulture设置为了ja-JP,结果可以发现后续启动的线程其CurrentCulture和CurrentUICulture也都为ja-JP

现在我们设置主线程的CurrentCulture和CurrentUICulture为ja-JP,但是将第一层线程的CurrentCulture和CurrentUICulture改为zh-CN

/// <summary>
/// 测试Async和Await模式,是否会对Thread.CurrentThread.CurrentCulture和Thread.CurrentThread.CurrentUICulture产生影响
/// </summary>
static void AsyncAwaitThreadCulture()
{
//设置主线程的CurrentCulture和CurrentUICulture为语言ja-JP
Thread.CurrentThread.CurrentCulture = new CultureInfo("ja-JP");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("ja-JP"); Console.WriteLine($"Thread id:{Thread.CurrentThread.ManagedThreadId.ToString()}=>主线程的CurrentCulture是{Thread.CurrentThread.CurrentCulture.ToString()}, CurrentUICulture是{Thread.CurrentThread.CurrentUICulture.ToString()}"); //通过Task来启动第一层线程
Task.Run(async () =>
{
//将第一层线程的CurrentCulture和CurrentUICulture改为zh-CN
Thread.CurrentThread.CurrentCulture = new CultureInfo("zh-CN");
Thread.CurrentThread.CurrentUICulture = new CultureInfo("zh-CN"); Console.WriteLine($"Thread id:{Thread.CurrentThread.ManagedThreadId.ToString()}=>第一层线程的CurrentCulture是{Thread.CurrentThread.CurrentCulture.ToString()}, CurrentUICulture是{Thread.CurrentThread.CurrentUICulture.ToString()}"); //通过Task来启动第二层线程
Task task = Task.Run(() =>
{
Console.WriteLine($"Thread id:{Thread.CurrentThread.ManagedThreadId.ToString()}=>第二层线程的CurrentCulture是{Thread.CurrentThread.CurrentCulture.ToString()}, CurrentUICulture是{Thread.CurrentThread.CurrentUICulture.ToString()}"); //通过Thread来启动第三层线程
Thread th = new Thread(new ThreadStart(() =>
{ Thread.Sleep(); Console.WriteLine($"Thread id:{Thread.CurrentThread.ManagedThreadId.ToString()}=>第三层线程的CurrentCulture是{Thread.CurrentThread.CurrentCulture.ToString()}, CurrentUICulture是{Thread.CurrentThread.CurrentUICulture.ToString()}");
})); th.IsBackground = true;
th.Start(); th.Join();//阻塞第二层线程,直到第三层线程th结束
}); Thread.Sleep(); Console.WriteLine($"Thread id:{Thread.CurrentThread.ManagedThreadId.ToString()}=>await之前CurrentCulture是{Thread.CurrentThread.CurrentCulture.ToString()}, CurrentUICulture是{Thread.CurrentThread.CurrentUICulture.ToString()}"); await task;//await,直到第二层线程结束 Console.WriteLine($"Thread id:{Thread.CurrentThread.ManagedThreadId.ToString()}=>await之后CurrentCulture是{Thread.CurrentThread.CurrentCulture.ToString()}, CurrentUICulture是{Thread.CurrentThread.CurrentUICulture.ToString()}"); }).Wait();//阻塞主线程,直到第一层线程执行完毕
}

现在运行结果如下:

我们可以看到从第一层线程开始,后续启动线程的CurrentCulture和CurrentUICulture都为zh-CN了

这说明在.NET Core中,默认情况下线程的CurrentCulture和CurrentUICulture属性是由启动它的线程来决定的,上面的结果很明显由于第一层线程的CurrentCulture和CurrentUICulture为zh-CN,所以由第一层线程启动的后续线程(第二层和第三层线程)也都为zh-CN。所以在.NET Core中要设置线程的CurrentCulture和CurrentUICulture属性,最简单的办法就是在根线程(主线程)上设置CurrentCulture和CurrentUICulture的语言即可。

最后如果是在ASP.NET Core中,只需要写一个中间件(Middleware),来更改主线程的CurrentCulture和CurrentUICulture属性为特定语言,即可实现.resx资源文件的全局利用,当然ASP.NET Core中也有一套自带的资源文件匹配规则,这里大家觉得怎么用起来方便怎么用即可。

本文示例源代码

.NET Core中多语言支持的更多相关文章

  1. ASP.NET Core 中的 WebSocket 支持(转自MSDN)

    本文介绍 ASP.NET Core 中 WebSocket 的入门方法. WebSocket (RFC 6455) 是一个协议,支持通过 TCP 连接建立持久的双向信道. 它用于从快速实时通信中获益的 ...

  2. 使用Novell.Directory.Ldap.NETStandard在.NET Core中验证AD域账号

    Novell.Directory.Ldap.NETStandard是一个在.NET Core中,既支持Windows平台,又支持Linux平台,进行Windows AD域操作的Nuget包. 首先我们 ...

  3. 在Asp.net Core中使用中间件来管理websocket

    介绍 ASP.NET Core SignalR是一个有用的库,可以简化Web应用程序中实时通信的管理.但是,我宁愿使用WebSockets,因为我想要更灵活,并且与任何WebSocket客户端兼容. ...

  4. 【asp.net core 系列】14 .net core 中的IOC

    0.前言 通过前面几篇,我们了解到了如何实现项目的基本架构:数据源.路由设置.加密以及身份验证.那么在实现的时候,我们还会遇到这样的一个问题:当我们业务类和数据源越来越多的时候,我们无法通过普通的构造 ...

  5. 在ASP.NET Core中使用Apworks开发数据服务:对HAL的支持

    HAL,全称为Hypertext Application Language,它是一种简单的数据格式,它能以一种简单.统一的形式,在API中引入超链接特性,使得API的可发现性(discoverable ...

  6. 在ASP.NET Core中如何支持每个租户数据存储策略的数据库

    在ASP.NET Core中如何支持每个租户数据存储策略的数据库 不定时更新翻译系列,此系列更新毫无时间规律,文笔菜翻译菜求各位看官老爷们轻喷,如觉得我翻译有问题请挪步原博客地址 本博文翻译自: ht ...

  7. C# 嵌入dll 动软代码生成器基础使用 系统缓存全解析 .NET开发中的事务处理大比拼 C#之数据类型学习 【基于EF Core的Code First模式的DotNetCore快速开发框架】完成对DB First代码生成的支持 基于EF Core的Code First模式的DotNetCore快速开发框架 【懒人有道】在asp.net core中实现程序集注入

    C# 嵌入dll   在很多时候我们在生成C#exe文件时,如果在工程里调用了dll文件时,那么如果不加以处理的话在生成的exe文件运行时需要连同这个dll一起转移,相比于一个单独干净的exe,这种形 ...

  8. JVM中的动态语言支持简介

    抽丝剥茧 细说架构那些事——[优锐课] 从版本6开始,JVM已扩展为支持现代动态语言(也称为脚本语言).Java8的发行为这一领域提供了更多动力.感到这种支持的必要性是因为Java作为一种语言固有地是 ...

  9. [.NET Core]ASP.NET Core中如何解决接收表单时的不支持的媒体类型(HTTP 415 Unsupported Media Type)错误呢?

    [.NET Core]ASP.NET Core中如何解决接收表单时的不支持的媒体类型(HTTP 415 Unsupported Media Type)错误呢? 在ASP.NET Core应用程序中,接 ...

随机推荐

  1. 使用镶嵌数据集 MosaicDataSet管理不同分辨率影像数据

    镶嵌数据集 MosaicDataSet是Esri推出的一种用于管理海量影像数据的数据模型,它是Geodatabase数据模型的一个子集定义. 该数据模型强大之处在于它能统一管理不同采集时间.不同采集来 ...

  2. 【小程序】微信小程序绑定企业微信后怎样获取到用户信息

    一.获取access_token 1.https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=ID&corpsecret=SECRECT Cor ...

  3. Difference between 'SAME' and 'VALID' padding

    Difference between 'SAME' and 'VALID' padding 'SAME' padding 和 'VALID' padding 的区别 If you like ascii ...

  4. screen 状态为Attached 连不上

    用 screen -ls, 显式当前状态为Attached, 但当前没有用户登陆些会话.screen此时正常状态应该为(Detached)  此时用screen -r ,怎么也登不上. 最后找到解决方 ...

  5. Android 运行时权限处理(from jianshu)

    https://www.jianshu.com/p/e1ab1a179fbb 翻译的国外一篇文章. android M 的名字官方刚发布不久,最终正式版即将来临! android在不断发展,最近的更新 ...

  6. DOMINO的JDBC和ODBC连接方法

     利用ODBC实现Domino和关系数据库的互操作 Lotus Domino是当今办公自动化系统的主流开发平台之一,Domino自带一个非关系型数据库–文档型数据库,而目前大部分企业的信息都储存在 ...

  7. java web项目中引入spring

    自己动手实践了一次,发生中间出了一下问题,现整理出来,供参考. Step1: 新建一个java web项目 Step2:下载spring的jar包http://repo.spring.io/libs- ...

  8. IIS 中托管基于TCP绑定的WCF服务

    IIS 中托管基于TCP绑定的WCF服务 一.创建一个基于TCP绑定的WCF服务 1.创建一个的简单的服务具体代码如下 服务契约定义 namespace SimpleService { // 注意: ...

  9. Mysql压缩解决方案

    提到mysql压缩相关的内容,我们能想到的可能是如下几种和压缩相关的场景: 1.客户端和服务器之间传输的数据量太大,需要进行压缩,节约带宽 2.mysql某个列的数据量大,只针对某个列的数据压缩 3. ...

  10. [翻译] SSKeychain

    SSKeychain https://github.com/soffes/sskeychain SSKeychain is a simple wrapper for accessing account ...