1、背景

  公司业务遍及全球各地,对应业务系统国际化就是顺理成章的事情。最近就接手了一批新老系统的国际化任务,这里把一些探索经验、案例记录下来。本身改造和探索过程包括.NET MVC的,以及.NET CORE WEB API的,但这里旧版MVC的就不描述了,重点介绍netcore下的国际化方案。国际化重点在于多语言支持,以及多时区支持,本文就从这两个方面入手。

  预设:有一个前后端分离的系统,前端由i18n负责多语言支持,后端不渲染视图,提供api返回数据给前端。

  Demo解决方案截图:

2、多语言

  如上解决方案截图,Common.Resource是多语言资源工程,ExceptionHandlerTest是示例web api项目,Service是api项目依赖的服务工程。之所以这么设计场景,是为了探索资源文件放在单独工程下,以及非Web Api工程中的多语言方案,这点在官方教程中基本是没有的。

  先来看demo要干的事情:HomeController中有个SayHello方法,此方法调用HomeService中的SayHello方法返回欢迎语信息,我们要做的就是对HomeService中返回的欢迎语进行语言协商。下边来看看具体怎么实现:

2.1、定义多语言资源文件

  以支持中英文为例,定义如下图资源文件,步骤与FX下的很类似。

  唯一的重大区别,是如果你希望在单独工程中放置资源配置,那就添加一个单独类代码文件,假如你的资源是Common.en.rex,那对应类就应该是Common,这点在跨程序集寻找资源文件中至关重要,官网文档中可没有描述这至关重要的一点,别问我怎么知道的, 问就是看core底层源码。。。

  资源文件中定义的资源配置项如下:

2.2、配置多语言服务及中间件

1)注册本地化服务及HomeService服务

  HomeService必须使用容器解析,否则core底层没法注入多语言基础服务到我们的组件,那你就只能手动传入。

2)注册本地化中间件

2.3、系统中引入多语言设置项

1)HomeService中注入IStringLocalizer服务

2)SayHello方法引用多语言配置项

2.4、实际效果

1)默认访问

不做任何设置,系统也无设置对应cookie情况下,netcore直接取浏览器语言环境设置,就是下图这个地方:

  假如我们将浏览器语言环境改成英文,那默认情况下系统就会选取英文了。

2)通过查询字符串切换语言

  如上图,我们使用netcore规定的culture=en格式向后端传递语言环境信息。具体语言环境选择优先级是这样的:查询字符串  >  cookie  >  浏览器语言环境设置,这在官网有详细介绍,看底层源码也证实了这个。基于cookie选取语言环境时候,cookie名称是可以修改的,我实际项目就是如此,官网文档也有介绍,这里不做赘述。

3、多时区

3.1、场景预设

预设1:HomeController中有两个方法,GetTime返回服务端或数据库中存储的UTC时间,系统根据客户本地时区自动转换成其对应时间;SetTime方法接收客户本地时区下的时间,转换成UTC时间存入服务器或数据库

预设2:系统支持中国东八区时间及印度东5区时间

3.2、自定义时间转换器

/// <summary>
/// 日期转换
/// </summary>
public class DateTimeOffsetJsonConverter : JsonConverter<DateTimeOffset>
{
private TimeZoneInfo chinaZoneInfo = TimeZoneInfo.CreateCustomTimeZone("zh", TimeSpan.FromHours(), "中国时区", "China time zone");
private TimeZoneInfo indiaZoneInfo = TimeZoneInfo.CreateCustomTimeZone("en-IN", TimeSpan.FromHours(), "印度时区", "India time zone"); public override DateTimeOffset Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
var currentZoneInfo = Thread.CurrentThread.CurrentCulture.Name.Contains("zh") ? chinaZoneInfo : indiaZoneInfo;
//var time1 = DateTimeOffset.Parse(reader.GetString());
//var time2 = time1.ToOffset(currentZoneInfo.BaseUtcOffset);
var time1 = new DateTimeOffset(DateTime.Parse(reader.GetString()), currentZoneInfo.BaseUtcOffset);
var time2 = time1.ToUniversalTime();
//var time3 = time2.ToUniversalTime(); return time2;
} public override void Write(Utf8JsonWriter writer, DateTimeOffset value, JsonSerializerOptions options)
{
var currentZoneInfo = Thread.CurrentThread.CurrentCulture.Name.Contains("zh") ? chinaZoneInfo : indiaZoneInfo;
writer.WriteStringValue(value.ToOffset(currentZoneInfo.BaseUtcOffset).ToString("yyyy-MM-dd HH:mm:ss"));
}
}

  如上所述,自定义时间序列化转换器,读取时间时,根据客户语言环境匹配其对应时区,时区中有对应UTC偏离时间信息,据此转换成UTC时间;序列化写入时候,同样根据语言环境匹配时区信息,将服务器端的UTC时间按照时区偏离转换成本地时间返给客户端。

3.3、时间转换测试

1)获取服务器时间

  其中currentTime是模拟服务器上或数据库中取出来的UTC时间,然后什么不做直接返回,具体时间转换交由时间转换器负责。下边看效果:

中文环境时间:

  可以看到,原始UTC时间2019-07-15 08:30:00在中国东八区8个小时偏离下,返给客户端变成了16:30:00,即中国本地时间;

英文环境:

  当语言环境切换为英文,则匹配到印度东5区时区信息,UTC时间2019-07-15 08:30:00转换成印度本地时间2019-07-15 13:30:00。

2)写入时间到服务器

  同样的,接收到客户端时间后,我们业务代码层不做任何设置,交由时间转换器去负责,具体看效果:

中文环境:

  传入本地时间2019-07-15 16:30:00,到了服务器,时间如下:

  可以看到,中国东八区时间2019-07-15 16:30:00在服务器上转换成UTC时间2019-07-15 08:30:00;

  同样的本地时间,但语言环境为英语:

  可以看到,印度东5区的本地时间2019-07-15 16:30:00到服务器,转换成UTC时间2019-07-15 11:30:00。

4、总结

  系统国际化的重点,在于语言环境国际化,以及多时区自适应,解决这两点,剩下就不是啥问题了。关于时区,这里是以服务器及数据库中统一保存UTC时间为例,但也有一定麻烦,比如你需要后台维护数据,尤其是直接在数据库中维护这种,就需要做本地时间和UTC时间的手动处理,除非你是英国人,身处英国,用英国的时区。针对这点可以做对应发散,例如假如系统中文用户占多数,运维也主要是中国员工,那就可以采取服务器或数据库统一存储中国东8区的时间,其他本地时间向中国时间进行转换的做法,思路、解决方案是一致的。

.net core国际化的更多相关文章

  1. .Net Core 国际化

    创建项目什么的就不说了吧 直接进入正题吧 我这里建的是个webapi 添加资源文件 1.首先我们创建一个Language文件夹,这就是我们在后面Startup类中需要配置的目录名. 2.然后我们在La ...

  2. 梳理一下web总的一些概念

    servlet中的类适合繁复翻看文档,熟悉各个类的常用方法,看一些经典的案例代码. ServletConfig 每个项目有多个servlet,每个servlet对应一个ServletCOnfigt对象 ...

  3. Web---JSTL(Java标准标签库)-Core核心标签库、I18N国际化、函数库

    前面为JSTL中的常用EL函数,后面的为具体演示实例! JSTL简介: JSTL(Java Standard Tag Library) –Java标准标签库. SUN公司制定的一套标准标签库的规范. ...

  4. asp.net core 之多语言国际化自定义资源文件

    先说说 asp.net core 默认的多语言和国际化. 官方文档 一:基本使用方法 先要安装 包 Microsoft.AspNetCore.Mvc.Localization (依赖 Microsof ...

  5. sql server 关于表中只增标识问题 C# 实现自动化打开和关闭可执行文件(或 关闭停止与系统交互的可执行文件) ajaxfileupload插件上传图片功能,用MVC和aspx做后台各写了一个案例 将小写阿拉伯数字转换成大写的汉字, C# WinForm 中英文实现, 国际化实现的简单方法 ASP.NET Core 2 学习笔记(六)ASP.NET Core 2 学习笔记(三)

    sql server 关于表中只增标识问题   由于我们系统时间用的过长,数据量大,设计是采用自增ID 我们插入数据的时候把ID也写进去,我们可以采用 关闭和开启自增标识 没有关闭的时候 ,提示一下错 ...

  6. .NET Core AvaloniaUI实现多语言国际化

    AvaloniaUI是一个基于.Net Core的跨平台桌面程序UI框架,如果使用AvaloniaUI有多语言国际化的朋友可以参考我这篇文章: 这篇文章可以帮助你: 根据用户系统设置的语言改变UI显示 ...

  7. ASP.NET Core 中文文档 第二章 指南(4.4)添加 Model

    原文:Adding a model 作者:Rick Anderson 翻译:娄宇(Lyrics) 校对:许登洋(Seay).孟帅洋(书缘).姚阿勇(Mr.Yao).夏申斌 在这一节里,你将添加一些类来 ...

  8. ASP.NET Core 中文文档 第二章 指南(4.9)添加验证

    原文:Adding Validation 作者:Rick Anderson 翻译:谢炀(Kiler) 校对:孟帅洋(书缘).娄宇(Lyrics).许登洋(Seay) 在本章节中你将为 Movie 模型 ...

  9. ASP.NET Core 中文文档 第三章 原理(6)全球化与本地化

    原文:Globalization and localization 作者:Rick Anderson.Damien Bowden.Bart Calixto.Nadeem Afana 翻译:谢炀(Kil ...

随机推荐

  1. Python File readline() 方法

    概述 readline() 方法用于从文件读取整行,包括 "\n" 字符.如果指定了一个非负数的参数,则返回指定大小的字节数,包括 "\n" 字符.高佣联盟 w ...

  2. QDC DAY1

    暴毙了,比较自闭的心理,有点崩溃.. LINK:幸福 一道曾经的我肯定能写出来的 但是我心态崩了 所以没有推出来. 当然 还是 我比较垃圾 但同时也不垃圾 ... 求 $T_n =\displayst ...

  3. 浅谈Mybatis持久化框架在Spring、SSM、SpringBoot整合的演进及简化过程

    前言 最近开始了SpringBoot相关知识的学习,作为为目前比较流行.用的比较广的Spring框架,是每一个Java学习者及从业者都会接触到一个知识点.作为Spring框架项目,肯定少不了与数据库持 ...

  4. com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'user'

    nested exception is com.fasterxml.jackson.core.JsonParseException: Unrecognized token 'user' 可能错误原因: ...

  5. 【NOI2017】游戏 题解(2-SAT+缩点)

    题目链接 题目大意:有四种场地$a,b,c,x$和三种赛车$A,B,C$,$a$不能跑$A$,$b$不能跑$B$,$c$不能跑$C$,$x$都可以跑.给定$n$个场地和$m$个四元组$(i,h_i,j ...

  6. Python监控你的女朋友/男朋友每天都在看哪些网站

    需求: 很多人学习python,不知道从何学起.很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手.很多已经做案例的人,却不知道如何去学习更加高深的知识.那么针对这三类人,我给大家提 ...

  7. 利用Python实现定时发送邮件,实现一款营销工具

    说起自动化绝对算是茶余饭后最有显B格的谈资,毕竟解放双手是从老祖先那里就流传下来的基因,都2020了,你每天上班还要登录各个邮箱账号查收邮件?快来解锁本章内容 整体思路 很多人学习python,不知道 ...

  8. 简单python爬虫编写,Python采集妹子图!

    疫情期间在家闲来无事,每天打游戏荒废了一段时间.我觉得自己不能在这么颓废下去,就立马起身写了一点python代码(本人只是python新手). 很多人学习python,不知道从何学起.很多人学习pyt ...

  9. Python利用Twilio(国际)以及腾讯云服务做一些事情

    短信服务验证服务已经不是什么新鲜事了,但是免费的手机短信服务却不多见,本次利用Python3.0基于Twilio和腾讯云服务分别来体验一下国际短信和国内短信接口. 首先,注册Twilio: www.t ...

  10. SPP、ASPP、RFB、CBAM

    SPP:ASPP:将pooling 改为了 空洞卷积RFB:不同大小的卷积核和空洞卷积进行组合,认为大的卷积应该有更大的感受野. CBAM:空间和通道的注意力机制 SPP: Spatial Pyram ...