views 多文件夹 netcore_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 里扩展定义了 IViewLocalizer 和 IHtmlLocalizer,IViewLocalizer 和 IHtmlLocalizer 主要是为了处理包含 html 的资源,他们不会对资源进行 html encode,相当于 @Html.Raw 的效果,而 IStringLocalizer 则会被 html encode,除此之外 IViewLocalizer 还会根据当前视图的路径寻找资源文件

来看一个示例:

Razor 页面

6b025297279f2de171bbed59c75f1c64.png

浏览器效果:

a58380cc0c4fef77e415fa1244f5cbe4.png

查看网页源代码:

d7264d0909631c372253542fa8ca0113.png

实际案例#

服务注册#

注册 Localization 相关服务:

Copyvar supportedCultures = new[]{    new CultureInfo("zh"),    new CultureInfo("en"),};services.Configure(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 就不需要了)

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

中间件配置:#

Copyapp.UseRequestLocalization();

逻辑代码中使用示例:#

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

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

在视图中使用示例:#

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

Copy@inject IViewLocalizer viewLocalizerviewLocalizer["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 nameDot or path namingResources/Controllers.HomeController.fr.resxDotResources/Controllers/HomeController.fr.resxPath

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

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

01fec0d9b7fe2d55640fc97f65d58ff9.png

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

默认的中文界面:

1cae9fd4c20ffc740190dcbc04105c69.png

英文界面:

cf95645913f724dd997f9ffec8c18b72.png

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

Docker 部署#

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

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

CopyRUN apk add --no-cache icu-libs # 安装 icu-libsENV 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 文件

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值