asp.net core 实现支持多语言

Intro

最近有一个外国友人通过邮件联系我,想用我的活动室预约,但是还没支持多语言,基本上都是写死的中文,所以最近想支持一下更多语言,于是有了多语言方面的一些实践

国际化/本地化介绍

国际化(Globalization)和本地化(Localization)是要实现的多语言支持的基础

Globalization is the process of designing and developing applications that function for multiple cultures.

Localization is the process of customizing your application for a given culture and locale.

国际化是要支持处理多种文化,而本地化是要根据某一个文化和区域的来展示相应的处理。

更多关于国际化与本地化的不同可以参考 Stack Overflow 上的讨论 https://stackoverflow.com/questions/2074869/globalization-vs-localization

Localization In Asp.NET Core

微软官方的 Localization 的实现是基于资源文件实现的 ( *.resx),我们也可以扩展支持更多方式,如 JSON/数据库 都是可以的,社区已经有实现的示例,只要是可以提供一个文本源的都是可以的,我们先使用默认的基于资源文件的,下一篇再讲一个自定义实现一个 Localization Provider。

.NET Core Localization 的 核心是 IStringLocalizer,asp.net core 里扩展定义了 IViewLocalizerIHtmlLocalizerIViewLocalizerIHtmlLocalizer 主要是为了处理包含 html 的资源,他们不会对资源进行 html encode,相当于 @Html.Raw 的效果,而 IStringLocalizer 则会被 html encode,除此之外 IViewLocalizer 还会根据当前视图的路径寻找资源文件

来看一个示例:

Razor 页面

浏览器效果:

查看网页源代码:

实际案例

服务注册

注册 Localization 相关服务:

var supportedCultures = new[]
{new CultureInfo("zh"),new CultureInfo("en"),
};
services.Configure<RequestLocalizationOptions>(options =>
{options.DefaultRequestCulture = new RequestCulture("zh");// Formatting numbers, dates, etc.options.SupportedCultures = supportedCultures;// UI strings that we have localized.options.SupportedUICultures = supportedCultures;
});
services.AddLocalization(options => options.ResourcesPath = Configuration.GetAppSetting("ResourcesPath"));

配置视图 Localization(根据需要如果是 WebAPI 就不需要了)

services.AddControllersWithViews().AddNewtonsoftJson(options =>{options.SerializerSettings.ContractResolver = new DefaultContractResolver();options.SerializerSettings.DateTimeZoneHandling = DateTimeZoneHandling.Utc; // 设置时区为 UTCoptions.SerializerSettings.NullValueHandling = NullValueHandling.Ignore;options.SerializerSettings.ReferenceLoopHandling = ReferenceLoopHandling.Ignore;}).AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix,opts => { opts.ResourcesPath = Configuration.GetAppSetting("ResourcesPath"); }).AddDataAnnotationsLocalization().SetCompatibilityVersion(CompatibilityVersion.Latest);

中间件配置:

app.UseRequestLocalization();

逻辑代码中使用示例:

IStringLocalizerIHtmlLocalizer / IViewLocalizer 都可以直接从依赖注入服务中获取, IStringLocalizerIHtmlLocalizer 推荐使用强类型的方式,也就是下面示例的使用方式,使用方式和 ILogger 类似

public async Task<ActionResult> MakeReservation([FromBody]ReservationViewModel model,[FromHeader]string captcha,[FromHeader]string captchaType,[FromServices]IStringLocalizer<HomeController> localizer)
{var result = new ResultModel<bool>();var isCodeValid = await HttpContext.RequestServices.GetService<CaptchaVerifyHelper>().ValidateVerifyCodeAsync(captchaType, captcha);if (!isCodeValid){result.Status = ResultStatus.RequestError;result.ErrorMsg = localizer["InvalidCaptchaInfo"];return Json(result);}

在视图中使用示例:

localizer["data"] 返回的是一个 LocalizedString,实现了隐式转换为 string, 有的时候可能需要强制转一下string, 或者使用 Value 属性

@inject IViewLocalizer viewLocalizer
viewLocalizer["About"]
@Html.ActionLink((string)viewLocalizer["About"], "About", "Home")
@Html.ActionLink(viewLocalizer["About"].Value, "About", "Home")

资源文件配置:

资源文件的配置和文件的结构类似,下面是一个示例

准备的来说是和类型的 FullName 有关系,一般的项目名称就是程序集名称,就是根命名空间,文件名称就是类型名称,所以一般情况下资源文件的位置和类型的位置是一致的,但是如果文件和类型名称不符合,那就要按照类型的 FullName 来找,视图也是类似的,如果根命名空间不是程序集名称,也是可以配置的具体的参考文档

Controllers.HomeController => Controllers/HomeController.zh.resx/ Controllers/HomeController.en.resx

Resource name Dot or path naming
Resources/Controllers.HomeController.fr.resx Dot
Resources/Controllers/HomeController.fr.resx Path
  • Resources/Views/Home/About.fr.resx

  • Resources/Views.Home.About.fr.resx

实际项目中的资源文件示例:

实际访问效果:https://reservation.weihanli.xyz/

默认的中文界面:

英文界面:

只是做了几个前台的示例,还有很多地方没改

Docker 部署

现在的项目是基于 docker + k8s 部署的,所以支持 docker 部署很重要

要支持多语言,需要安装 ICU 相关的包,(这个可不是 996.icu 的 icu 哈,如果不装真的有可能导致 996.icu)

RUN apk add --no-cache icu-libs # 安装 icu-libs
ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT false # 配置 Globalization

完整的 dockerfile 可以参考:https://github.com/dotnet/dotnet-docker/blob/cb7a9c35dacf6d34fcf7bab7995e60faef55f61f/samples/dotnetapp/Dockerfile.alpine-x64-globalization

More

.net core 的设计真的是很灵活,很优美,基于资源文件的本地化,感觉不太方便,使用资源文件的化可能就只能使用 VS 编辑了,虽然也是纯文本的,基于 xml 但是编辑起来不如界面看着编辑舒服,如果使用 json 之类的,就比较简单明了,编辑起来也比较方便,所以想把资源文件替换成 JSON 文件

下次分享一篇基于 JSON 的 Localization Provider 的实现

Reference

  • https://docs.microsoft.com/en-us/aspnet/core/fundamentals/localization?view=aspnetcore-3.1

  • https://github.com/dotnet/extensions/tree/master/src/Localization

  • https://github.com/dotnet/aspnetcore/tree/master/src/Middleware/Localization

  • https://stackoverflow.com/questions/2074869/globalization-vs-localization

  • https://github.com/WeihanLi/ActivityReservation

asp.net core 实现支持多语言相关推荐

  1. 体验 ASP.NET Core 中的多语言支持(Localization)

    首先在 Startup 的 ConfigureServices 中添加 AddLocalization 与 AddViewLocalization 以及配置 RequestLocalizationOp ...

  2. Asp.Net Core 已支持 gRPC-Web !!

    grpc-dotnet 项目在 PR #695 完成了 ASP.NET Core 服务与 .NET Core gRPC 客户端的 gRPC-Web 实现.虽然目前还是实验性项目,但是并不阻碍我们为之兴 ...

  3. 快速搭建CentOS+ASP.NET Core环境支持WebSocket

    以前用python,go尝试在linux下做web服务,python没有强类型支持与高性能,go又没有很好的集成开发环境(还有强迫症的语法),回头看了几次.net,都没有时间尝试,现终于实现了这些想法 ...

  4. 前端 JS/TS 调用 ASP.NET Core gRPC-Web

    前言 在上两篇文章中,介绍了ASP.NET Core 中的 gRPC-Web 实现 和 在 Blazor WebAssembly 中使用 gRPC-Web,实现了 Blazor WebAssembly ...

  5. ASP.NET Core 运行原理剖析

    1.1. 概述 在ASP.NET Core之前,ASP.NET Framework应用程序由IIS加载.Web应用程序的入口点由InetMgr.exe创建并调用托管.以初始化过程中触发HttpAppl ...

  6. ASP.Net Core 2.0中的Razor Page不是WebForm

    随着.net core2.0的发布,我们可以创建2.0的web应用了.2.0中新东西的出现,会让我们忘记老的东西,他就是Razor Page.下面的这篇博客将会介绍ASP.Net Core 2.0中的 ...

  7. (更新时间)2021年5月18日 ASP.NET Core 笔试题

    .NET Core笔试题 文章目录 .NET Core笔试题 1.如何在ASP.NET Core中激活Session功能? 2.什么是中间件? 3.Applicationbuilder的Use和Run ...

  8. 2022年8月10日:使用 ASP.NET Core 为初学者构建 Web 应用程序--使用 ASP.NET Core 创建 Web UI(没看懂需要再看一遍)

    ASP.NET Core 支持使用名为 Razor 的本地模板化引擎创建网页. 本模块介绍了如何使用 Razor 和 ASP.NET Core 创建网页. 简介 通过在首选终端中运行以下命令,确保已安 ...

  9. 【面试】ASP.NET Core+Redis+Mysql面试题答案

    .NET Core 1.如何在ASP.NET Core中激活Session功能   写的好啊,Inb哥,我是废物 2.什么是中间件   中间件是介于应用系统和系统软件之间的一类软件,它使用系统软件所提 ...

最新文章

  1. Recall(召回率)和 sensitivity(灵敏性)是同一个概念,其他无相同点
  2. c#.net URL参数传递及在js中引用
  3. 计算机主板的工作原理,计算机主板的工作原理.doc
  4. 学习鸟哥的Linux私房菜笔记(5)——目录
  5. (转载)关于IAP与APP互相跳转的实现
  6. 云炬VB开发笔记 2可视化编程基础
  7. 东南大学2004年程序设计第一届初赛解题报告
  8. Scrapy爬虫基本使用
  9. [剑指offer]面试题37:两个链表的第一个公共结点
  10. 如何提高VFP应用软件的路径适应性
  11. 第七十七期:可自动生成代码,5款基于AI的开发工具
  12. C语言 返回指针的函数--指针函数 int* max(int a)
  13. CQOI 2016 不同的最小割
  14. ffmpeg create a video from 4th image and and slow down the play speed
  15. #include与#include的区别
  16. Oracle查询优化改写技巧与案例总结四
  17. java 将ofd转为pdf(代码简单)
  18. ddk高级主题和提示
  19. H264、H265编码概念及I帧P帧B帧
  20. 计算机毕业论文指导,计算机毕业论文指导

热门文章

  1. java乘以2的位计算符号_java编程之:按位与运算,等运算规则
  2. windows命令提示符_如何个性化Windows命令提示符
  3. 机器学习-tensorflow
  4. 获取iOS 设备上崩溃日志 (Crash Log)的方法
  5. ADO.NET笔记——基本概念
  6. SQL Server默认1433端口修改方法
  7. 在sp_executesql中使用like字句
  8. 基于电子邮件的InfoPath表单发布的注意点 [Infopath 2007]
  9. Wow,一个免费、不怕打的评论插件!
  10. C#多线程开发-使用并发集合