MasaFramework -- i18n (国际化)
概念
作为一个普通开发者, 我们负责的项目的使用群体大多数是本国的人民, 但不可避免的也有一些做外贸的业务或者给外企做的项目, 这个时候就要求我们的项目有服务全球客户的能力, 而一个支持国际化能力的框架会让我们项目的体验变得更好.
关于本地化我们听到最多的是I18N、L10N、G11N, 那它们分别代表了什么意思呢?
- I18N: 是"Internationalization" 的缩写, 由于I到N之间间隔了18个字母, 也被简称为"i18n". 使产品或软件具有不同国际市场的普遍适应性, 从而无需重新设计就可适应多种语言和文化习俗的过程. 真正的国际化要在软件设计和文档开发过程中, 使产品或软件的功能和代码设计能处理多种语言和文化习俗, 具有良好的本地化能力. 它让程序具备了支持多种语言的能力
- L10N: 是"Localization"的缩写, 由于L到N之间间隔了10个字母, 也被简称为"L10N". 是将产品或软件针对特定国际语言和文化进行加工, 使之符合特定区域市场的过程. 真正的本地化要考虑目标区域市场的语言、文化、习俗、特征和标准. 通常包括改变软件的书写系统(输入法)、键盘使用、字体、日期、时间和货币格式等
- G11N: 是"Globalization"的缩写, 由于G到N之间间隔了11个字母, 也被简称为"G11n", 是指在全球范围内推出产品的业务方面, 可以简单理解为 "I18N" + "L10N"
本地化的意义
本地化包括:
- 产品本地化
- 技术研发本地化
- 原材料本地化
- 人才本地化
- 企业文化本地化
经过研究表明, 本地化后的产品的销量会比未经过本地化的更好, 75%的人偏好用母语购买产品, 86%的本地化广告在点击率、转换率上超过未经过本地化的广告, 这些数字都说明了人们对自己母语显示的内容更加感兴趣, 通过本地化可以让你更精准的打动客户, 帮你迅速的进入市场, 但本地化不等于直接翻译, 本地化是基于对当地市场情况和文化精心策划的, 在习惯、习俗、日期和货币格式上是不相同的, 本地化的产品能节约沟通成本, 更容易被理解和接受.
举个通俗的例子: 相比找一个不认识的陌生人买东西, 我们更喜欢去找那个知根知底的本地人买东西, 这无关产品的质量, 只是熟悉的人更容易获得我们的认同感
虽然本地化包括很多模块, 但在此我们只考虑产品的本地化, 下面我们就说一下如何做使得自己的产品可以支持本地化
使用
- 安装.NET 6.0
- 新建ASP.NET Core 空项目
Assignment.I18nDemo,并安装Masa.Contrib.Globalization.I18n.AspNetCore
dotnet add package Masa.Contrib.Globalization.I18n.AspNetCore --version 0.7.0-preview.16
- 注册
I18n, 并修改Program.cs
builder.Services.AddI18n();
- 使用
I18N
app.UseI18n();//启用本地化中间件
- 添加多语言资源文件, 文件夹结构如下:
- Resources
- I18n
- en-US.json
- zh-CN.json
- supportedCultures.json
- en-US.json
{
"Home":"Home"
}
- zh-CN.json
{
"Home":"首页"
}
- supportedCultures.json
[
{
"Culture":"zh-CN",
"DisplayName":"中文简体",
"Icon": "{Replace-Your-Icon}"
},
{
"Culture":"en-US",
"DisplayName":"English (United States)",
"Icon": "{Replace-Your-Icon}"
}
]
- 使用
I18n
app.Map("/test", (string key) => I18n.T(key));
- 测试多语言, 在浏览器访问"https://localhost:7082/get?key=Home"即可得到对应语言下键名为
Home的值
是不是感觉用起来十分简单呢, 但这究竟是如何做的呢
进阶
国内的小伙伴根据上面的例子操作下来, 会发现请求响应的内容是中文, 那什么情况下它会变成英文呢?
本地化中间件
由于.NET 提供了本地化的能力, 它提供了本地化的中间件, 通过它使得我们的项目具备解析当前语言的能力
目前它支持了以下三种方式进行语言切换:
- URL 参数 方式: ?culture=en-US,此方式优先级最高,格式为:culture=区域码
- Cookies 方式:cookie 格式为 c=%LANGCODE%|uic=%LANGCODE%,其中 c 是 Culture,uic 是 UICulture, 例如:
c=en-UK|uic=en-US
- 客户端浏览器语言自动匹配:如果前面两种方式都没有设置,支持自动根据客户端浏览器语言进行匹配
语言优先级:
URL 参数 方式 > Cookies方式 > 客户端语言 > 默认语言
默认语言
默认语言有两种配置方式, 它们分别是:
- 约定配置
supportedCultures.json文件中的第一个语言
- 手动指定默认语言
- 通过
app.UseI18n("{Replace-Your-DefaultCulture}")
- 通过
它们的优先级是:
手动指定默认语言 > 约定配置
修改默认资源路径
builder.Services.AddI18n(options =>
{
options.ResourcesDirectory = Path.Combine("Resources", "I18n");//修改默认资源路径
options.SupportedCultures = new List<CultureModel>() //支持语言
{
new("zh-CN"),
new("en-US")
};
});
支持资源文件
如果你希望将配置文件嵌入到dll文件中, 不希望被看到修改, 那么你需要将资源json文件的生成操作改为嵌入的资源, 并修改I18N注册代码为:
builder.Services.AddI18nByEmbedded();
嵌套配置
相信了解前端开发的小伙伴也见到过嵌套的资源配置, 那对于Masa提供的多语言方案而言, 我们也支持这种格式的配置, 例如:
{
"Home":"首页",
"User":{
"Name":"名称"
}
}
我们希望拿到User节点下的Name属性的值, 则可以通过:
var result = I18N.T("User.Name");//其中key的值不区分大小写
当然除此之外, 我们也可以将不同资源的文件分开存放到不同的json文件, 然后通过添加多个资源目录的文件, 最终实现, 但在使用时稍微有区别:
app.Map("/test2", (string key, II18n<CustomResource> i18n) => i18n.T(key));//通过DI获取到自定义资源下Key对应内容
如何对接远程资源配置
多语言的远程资源配置目前仅支持Dcc, 我们可以这样做:
- 注册
MasaConfiguration并使用Dcc, 修改Program.cs
builder.Services.AddMasaConfiguration(configurationBuilder =>
{
// configurationBuilder.UseDcc();//正确配置好Dcc配置后开启
});
- 配置Dcc配置信息, 修改
appsettings.json
{
"DccOptions": {
"ManageServiceAddress": "{Replace-Your-DccManagerServiceHost}",
"RedisOptions": {
"Servers": [
{
"Host": "{Replace-Your-DccUseRedisHost}",
"Port": 6379
}
],
"DefaultDatabase": 0,
"Password": ""
}
}
}
对MasaConfiguration有疑问点这里
- 注册I18n
builder.Services.AddI18n(
Path.Combine("Resources", "I18n"),
"supportedCultures.json",
options => options.UseDcc());
我们仅需要在/Resources/I18n目录下存放支持语言的配置即可, 具体的语言配置将从Dcc读取 (读取Dcc语言的配置节点: 在Dcc配置下默认AppId下的"Culture.{语言}"), 例如:
如果支持语言为zh-CN、en-US, 则默认读取Dcc配置下默认AppId下Culture.zh-CN、Culture.en-Us两个配置对象的值, 我们仅需要修改它们的值即可, 并且如果对应的内容发生更改, 项目无需重启即可完成自动更新
源码解读
在MasaFramework中, 抽象了多语言的能力, 它提供了
- string this[string name]: 获取指定
name的值 (如果name不存在, 则返回name的值) - string? this[string name, bool returnKey]: 获取指定
name的值 (如果returnKey为false, 且name不存在, 则返回null) - string this[string name, params object[] arguments]: 获取指定
name的值, 并根据文化、输入参数格式化响应信息返回 (如果name不存在, 则返回name的值) - string? this[string name, bool returnKey, params object[] arguments]: 获取指定
name的值, 并根据文化、输入参数格式化响应信息返回 (如果returnKey为false, 且name不存在, 则返回null) - string T(string name): 获取指定
name的值, 如果name不存在, 则返回name的值 - string? T(string name, bool returnKey): 获取指定
name的值 (如果returnKey为false, 且name不存在, 则返回null) - string T(string name, params object[] arguments): 获取指定
name的值, 并根据文化、输入参数格式化响应信息返回 (如果name不存在, 则返回name的值) - string? T(string name, bool returnKey, params object[] arguments): 获取指定
name的值, 并根据文化、输入参数格式化响应信息返回 (如果returnKey为false, 且name不存在, 则返回null) - CultureInfo GetCultureInfo(): 获取当前线程的区域性 (被用于需要格式化响应信息的方法)
- void SetCulture(string cultureName, bool useUserOverride = true): 设置当前线程的区域性
- void SetCulture(CultureInfo culture): 设置当前线程的区域性
- CultureInfo GetUiCultureInfo(): 获取资源管理器使用的当前区域性以便在运行时查找区域性特定的资源
- void SetUiCulture(string cultureName, bool useUserOverride = true): 设置资源管理器使用的当前区域性以便在运行时查找区域性特定的资源
- void SetUiCulture(CultureInfo culture): 设置资源管理器使用的当前区域性以便在运行时查找区域性特定的资源
我们可以通过DI获取到II18n进而来使用它提供的这些能力, 当然它使用的是资源类型为DefaultResource的资源 (在服务注册时所指向的资源 services.AddI18n()), 除此之外, 我们也可以通过DI获取到II18n<DefaultResource>来使用, 也可以通过I18n(全局静态类)来使用它提供的能力, 但是如果你使用了自定义资源类型, 则只能通过DI获取II18n<{Replace-Your-ResourceType}>来使用.
除此之外, 我们还提供了支持的语言列表的能力, 它被抽象在ILanguageProvider
- IReadOnlyList GetLanguages(): 获取支持语言集合
我们可以通过DI获取ILanguageProvider来使用, 也可以通过I18n.GetLanguages()来使用
总结
当然, MasaFramework绝不仅仅只是提供了这么简单的多语言的能力, 目前全局异常、Caller也已经支持了多语言, 其他模块也在逐步完善多语言支持, 等之后框架的错误信息也将会支持多语言, 我们的开发体验也将会变得更加友好
参考
本章源码
Assignment18
https://github.com/zhenlei520/MasaFramework.Practice
开源地址
MASA.Framework:https://github.com/masastack/MASA.Framework
MASA.EShop:https://github.com/masalabs/MASA.EShop
MASA.Blazor:https://github.com/BlazorComponent/MASA.Blazor
如果你对我们的 MASA Framework 感兴趣,无论是代码贡献、使用、提 Issue,欢迎联系我们

MasaFramework -- i18n (国际化)的更多相关文章
- Django1.9开发博客(12)- i18n国际化
国际化与本地化的目的为了能为各个不同的用户以他们最熟悉的语言和格式来显示网页. Django能完美支持文本翻译.日期时间和数字的格式化.时区. 另外,Django还有两点优势: 允许开发者和模板作者指 ...
- Bootstrap-datepicker3官方文档中文翻译---I18N/国际化(原文链接 http://bootstrap-datepicker.readthedocs.io/en/latest/index.html)
I18N/国际化 这个插件支持月份和星期名以及weekStart选项的国际化.默认是英语(“en”); 其他有效的译本语言在 js/locales/ 目录中, 只需在插件后包含您想要的地区. 想要添加 ...
- i18n(国际化) 和l18n(本地化)时的地域标识代码
i18n(国际化) 和l18n(本地化)时的地域标识代码 格式如 zh-CN(语言-国家) i18n(国际化) 和l18n(本地化)时的地域标识代码 格式如 zh-CN(语言-国家) 国家说明 语言说 ...
- i18n,国际化翻译,excel与js互转
背景 公司开发新产品时,要求适配多国语言,采用i18n国际化工具,但翻译字典(js的json)还是需要前端自己写的.字典最终需要转换成excel给专业人员翻译,翻译完成后再转换成js字典文件. 如果手 ...
- 【JavaWeb】i18n 国际化
i18n 国际化 什么是 i18n 国际化(Internationalization)指的是同一个网站可以支持多种不同的语言,以方便不同国家,不同语种的用户访问. 希望相同的一个网站,不同人访问的时候 ...
- I18N 国际化
http://blog.sina.com.cn/s/blog_6c7e59770101p7w9.html 一.I18N 在 J2EE 中的应用 [转载:http://blog.csdn.net/cha ...
- Web---JSTL(Java标准标签库)-Core核心标签库、I18N国际化、函数库
前面为JSTL中的常用EL函数,后面的为具体演示实例! JSTL简介: JSTL(Java Standard Tag Library) –Java标准标签库. SUN公司制定的一套标准标签库的规范. ...
- Struts2 学习笔记17 I18N国际化
讲解一下国际化的内容,比如书有些大的网站可以一键切换语言,例如中英切换,这时候就会用到国际化.但是由于struts2大多数是用来写后台,国际化并不是十分重要,而且用国际化开发会减慢开发的速度,大家只要 ...
- Struts2之i18N国际化
对于i18n其实没有太多内容,一般的公司用不到这些内容,除非是跨国公司,但即便是跨国公司也不一定会使用i18n来进行国际化处理,所以本篇内容仅供大家了解,不做深入的探讨,希望通过本篇内容,可以帮助大家 ...
- SpringBoot系列——i18n国际化
前言 国际化是项目中不可或缺的功能,本文将实现springboot + thymeleaf的HTML页面.js代码.java代码国际化过程记录下来. 代码编写 工程结构 每个文件里面的值(按工程结构循 ...
随机推荐
- 二叉树及其三种遍历方式的实现(基于Java)
二叉树概念: 二叉树是每个节点的度均不超过2的有序树,因此二叉树中每个节点的孩子只能是0,1或者2个,并且每个孩子都有左右之分. 位于左边的孩子称为左孩子,位于右边的孩子成为右孩子:以左孩子为根节点的 ...
- AgileBoot - 基于SpringBoot + Vue3的前后端快速开发脚手架
AgileBoot 仓库 后端地址:https://github.com/valarchie/AgileBoot-Back-End 技术栈:Springboot / Spring Security / ...
- 知识图谱-生物信息学-医学论文(Chip-2022)-BCKG-基于临床指南的中国乳腺癌知识图谱的构建与应用
16.(2022)Chip-BCKG-基于临床指南的中国乳腺癌知识图谱的构建与应用 论文标题: Construction and Application of Chinese Breast Cance ...
- 【pytest官方文档】解读- 开发可pip安装的第三方插件
在上一篇的 hooks 函数分享中,开发了一个本地插件示例,其实已经算是在编写插件了.今天继续跟着官方文档学习更多知识点. 一个插件包含一个或多个钩子函数,pytest 正是通过调用各种钩子组成的插件 ...
- Java多线程(7):JUC(上)
您好,我是湘王,这是我的博客园,欢迎您来,欢迎您再来- 前面把线程相关的生命周期.关键字.线程池(ThreadPool).ThreadLocal.CAS.锁和AQS都讲完了,现在就剩下怎么来用多线程了 ...
- 【单元测试】Junit 4(二)--eclipse配置Junit+Junit基础注解
1.0 前言 前面我们介绍了白盒测试方法,后面我们来介绍一下Junit 4,使用的是eclipse(用IDEA的小伙伴可以撤了) 1.1 配置Junit 4 1.1.1 安装包 我们需要三个jar ...
- SpringBoot 自动装配原理
早期的Spring项目需要添加需要配置繁琐的xml,比如MVC.事务.数据库连接等繁琐的配置.Spring Boot的出现就无需这些繁琐的配置,因为Spring Boot基于约定大于配置的理念,在项目 ...
- 23种设计模式之自定义Spring框架(五)
7,自定义Spring框架 7.1 spring使用回顾 自定义spring框架前,先回顾一下spring框架的使用,从而分析spring的核心,并对核心功能进行模拟. 数据访问层.定义UserDao ...
- java学习之socket编程
0x00前言和思维导图 Socks实际上是什么:实际上是提供了精彩通信的端口,在通信之前双方都必须要创造一个端点才能通信,其实感觉socket跟计算机的三次握手有些相似,分为三个步骤: (1)服务器监 ...
- 基于iNeuOS工业互联网平台的板材实时质检系统
1. 项目背景 刨花板生产线由于原料.生产工艺等原因,会有一些产品板面出现颤纹.漏砂.胶斑.胶块.大刨花.粉尘斑.板面划痕和油污等缺陷.表面缺陷会降低板材强度.影响板材外观和二次加工,给企业带来经济 ...