先说说 asp.net core 默认的多语言和国际化。 官方文档

一:基本使用方法

先要安装 包 Microsoft.AspNetCore.Mvc.Localization (依赖 Microsoft.Extensions.Localization)  然后使用 资源文件保存不同的语言对应的数据。

1,在视图页面注入 IViewLocalizer ,然后在需要的地方使用即可。 比如:

 @inject IViewLocalizer Localizer

 <h2>@Localizer["hello"]</h2>

其中 中括号中的字符 即是资源文件中的名称, 运行后,输出的即是 当前语言对应的资源文件下的设置的资源值。

那么有个问题来了,资源文件怎么设置?

1,默认情况下会去查找 设置的 LocalizationOptions.ResourcesPath  的值对应的文件夹,如果没有设置,则去根目录下查找。

在 Startup 中设置 ResourcesPath  。

services.AddLocalization(options => options.ResourcesPath = "Resources");

2,查找当前视图文件对应的同名资源文件。 默认支持 使用 点 . 和路径 path 查找两种方式,当然也可以指定其中一个方式。 比如 当前视图路径是 views/account/login.cshtml ,那么 查找的资源文件是  views/account/login.{CultureName}.resx 文件和 views.account.login.{CultureName}.resx 文件

services.AddMvc()
.AddViewLocalization()
//.AddViewLocalization(Microsoft.AspNetCore.Mvc.Razor.LanguageViewLocationExpanderFormat.SubFolder)
.AddDataAnnotationsLocalization();

3,如果是 model 类, 查找的路径则变成了model 类对应的命名空间即typeof(model).FullName 全路径。比如 ViewModels/account/login.{CultureName}.resx 文件和 ViewModels.account.login.{CultureName}.resx 文件 。同理 如果是在controller  那么,资源文件 则是  Controllers.HomeController.{CultureName}.resx 或者 Controllers/HomeController.{CultureName}.resx

二:解析

那么这个是如何实现的呢?如果我想使用 数据库或者是 json 文件来存在这些资源文件。

在试图文件中 注入的是 IViewLocalizer 接口,对应的实现是  ViewLocalizer 。ViewLocalizer 实现了IViewLocalizer 和IHtmlLocalizer 的定义,并且 IViewLocalizer 继承自IHtmlLocalizer。  ViewLocalizer 会注入一个IHtmlLocalizerFactory,然后 用 IHtmlLocalizerFactory创建一个 IHtmlLocalizer 对应的实例。 在创建的时候 会带入两个参数 ,一个是 当前 试图的路径,一个是当前应用名称。

IHtmlLocalizer 定义如下:

所以在 IHtmlLocalizer的实例中, 既可以轻松的获取对应的值。

因为 ViewLocalizer 会注入一个IHtmlLocalizerFactory 的实例。默认的实例 是  HtmlLocalizerFactory , 在 HtmlLocalizerFactory 的构造函数中会注入一个 IStringLocalizerFactory 的实例(位于Microsoft.Extensions.Localization.Abstractions)。

的定义是

而  IHtmlLocalizerFactory 的定义是

可以说  HtmlLocalizerFactory 是对 HtmlLocalizerFactory 的一个包装。

查阅代码知道 默认 IStringLocalizerFactory 实现是 ResourceManagerStringLocalizerFactory ,并且读取资源文件均是这个实现来操作。

回到开头的问题,假设我要使用 json 文件 代替 resx 文件。该如何实现呢,。?  有2种方法

1)只要实现对应的 IStringLocalizerFactory 并且代替默认的 ResourceManagerStringLocalizerFactory 。

2)重写 ResourceManagerStringLocalizerFactory 。

1) 1,定义一个  JsonStringLocalizerFactory 并实现 IStringLocalizerFactory 。

public class JsonStringLocalizerFactory : IStringLocalizerFactory
{
private readonly string _applicationName;
private readonly IHostingEnvironment _hostingEnvironment;
private readonly LocalizationOptions _options;
public JsonStringLocalizerFactory(IHostingEnvironment hostingEnvironment, IOptions<LocalizationOptions> localizationOptions)
{
if (localizationOptions == null)
{
throw new ArgumentNullException(nameof(localizationOptions));
}
this._hostingEnvironment = hostingEnvironment ?? throw new ArgumentNullException(nameof(hostingEnvironment));
this._options = localizationOptions.Value;
this._applicationName = hostingEnvironment.ApplicationName;
} public IStringLocalizer Create(Type resourceSource)
{
TypeInfo typeInfo = IntrospectionExtensions.GetTypeInfo(resourceSource);
//Assembly assembly = typeInfo.Assembly;
//AssemblyName assemblyName = new AssemblyName(assembly.FullName); string baseResourceName = typeInfo.FullName;
baseResourceName = TrimPrefix(baseResourceName, _applicationName + "."); return new JsonStringLocalizer(_hostingEnvironment, _options, baseResourceName, null);
} public IStringLocalizer Create(string baseName, string location)
{
location = location ?? _applicationName; string baseResourceName = baseName;
baseResourceName = TrimPrefix(baseName, location + "."); return new JsonStringLocalizer(_hostingEnvironment, _options, baseResourceName, null);
} private static string TrimPrefix(string name, string prefix)
{
if (name.StartsWith(prefix, StringComparison.Ordinal))
{
return name.Substring(prefix.Length);
} return name;
}
}

2, JsonStringLocalizer

public class JsonStringLocalizer : IStringLocalizer
{
private readonly ConcurrentDictionary<string, string> _all; private readonly IHostingEnvironment _hostingEnvironment;
private readonly LocalizationOptions _options; private readonly string _baseResourceName;
private readonly CultureInfo _cultureInfo; public LocalizedString this[string name] => Get(name);
public LocalizedString this[string name, params object[] arguments] => Get(name, arguments); public JsonStringLocalizer(IHostingEnvironment hostingEnvironment, LocalizationOptions options, string baseResourceName, CultureInfo culture)
{
_options = options;
_hostingEnvironment = hostingEnvironment; _cultureInfo = culture ?? CultureInfo.CurrentUICulture;
_baseResourceName = baseResourceName + "." + _cultureInfo.Name;
_all = GetAll(); } public IEnumerable<LocalizedString> GetAllStrings(bool includeParentCultures)
{
return _all.Select(t => new LocalizedString(t.Key, t.Value, true)).ToArray();
} public IStringLocalizer WithCulture(CultureInfo culture)
{
if (culture == null)
return this; CultureInfo.CurrentUICulture = culture;
CultureInfo.DefaultThreadCurrentCulture = culture; return new JsonStringLocalizer(_hostingEnvironment, _options, _baseResourceName, culture);
} private LocalizedString Get(string name, params object[] arguments)
{
if (_all.ContainsKey(name))
{
var current = _all[name];
return new LocalizedString(name, string.Format(_all[name], arguments));
}
return new LocalizedString(name, name, true);
} private ConcurrentDictionary<string, string> GetAll()
{
var file = Path.Combine(_hostingEnvironment.ContentRootPath, _baseResourceName + ".json");
if (!string.IsNullOrEmpty(_options.ResourcesPath))
file = Path.Combine(_hostingEnvironment.ContentRootPath, _options.ResourcesPath, _baseResourceName + ".json"); Debug.WriteLineIf(!File.Exists(file), "Path not found! " + file); if (!File.Exists(file))
return new ConcurrentDictionary<string, string>(); try
{
var txt = File.ReadAllText(file); return JsonConvert.DeserializeObject<ConcurrentDictionary<string, string>>(txt);
}
catch (Exception)
{
} return new ConcurrentDictionary<string, string>();
}
}

3,添加注入

services.AddSingleton<IStringLocalizerFactory, JsonStringLocalizerFactory>();

4,json 文件

上面的代码只是简单的实现了 使用 点(.) 作为分隔符的json 文件作为资源文件。(其实上面的代码运行后有个小问题)

代码已经放到 Github

2)。待实现~~~

链接:http://blog.wuliping.cn/post/aspnet-core-localization-and-custom-resource-service-with-file

最新文章

  1. SQL 数据优化之不建立索引的情况
  2. 【ORACLE】IN 后跟&amp;参数字符串的处理方法
  3. C#常用类库(100多个)
  4. 云计算之路-阿里云上:RDS用户的烦恼
  5. RESTful的理解
  6. Spring事务解析3-增强方法的获取
  7. vim 简单配置
  8. resultMap / resultType
  9. Android对象类系列化public class User implements Parcelable
  10. Qt:使用自定义的字体
  11. iOS开发——高级技术&amp;生成二维码
  12. 【模拟】CSU 1807 最长上升子序列~ (2016湖南省第十二届大学生计算机程序设计竞赛)
  13. Qt5.5.1和Qt5.3.2编译OCI驱动教程及验证方法
  14. tesseract-ocr字库训练图文讲解
  15. 微信小程序之页面跳转路径问题
  16. 关于react组件之间的通信
  17. 【Java多线程通信】syncrhoized下wait()/notify()与ReentrantLock下condition的用法比较
  18. 【转载】Spring Cloud全家桶主要组件及简要介绍
  19. 使用VueCLI的User Interface Tool(GUI)创建app的图文讲解
  20. mybatis大于号,小于号,去地址符,单引号,双引号转义说明

热门文章

  1. Python的交互模式和命令行模式
  2. asp.net 打印控件使用方法
  3. 动态规划算法(后附常见动态规划为题及Java代码实现)
  4. LeetCode第五题:Longest Palindromic Substring
  5. 如果有多个集合的迭代处理情况【使用MAP】
  6. mybatis sql中的条件语句
  7. eclipse插件安装(个人版)
  8. List&lt;T&gt; JIT 分配策略
  9. jhipster初接触
  10. CentOS 7.2 部署Rsync + Lsyncd服务实现文件实时同步/备份 (一)