我被要求在ASP-NET.core中实现资源文件的本地化。net.core
解决办法如下。
资源文件必须在一个单独的项目中(如 "MyProject.Common"),才能在解决方案中的所有其他项目中使用。
资源必须以 "部分 "来分割,例如,我们在Web项目中有以下3个区域。
Users
, Content
,Administration
,所以我被要求有类似于:
我开始阅读本地化是AP-NET核心的文档,我有点搞不懂它是如何工作的.似乎并不像我被告知要做的事情是可能的.事情是,我可能需要在业务,视图和控制器中使用资源,所以我'寻找一种方法来实现它,使团队可以使用旧的方式,通过调用。
事情是,我可能需要使用资源的业务,视图和控制器,所以我在寻找一种方法来实现它,所以团队可以使用旧的方式,通过呼吁 ContentResources.MyCustomResource
.
有什么办法可以接近它吗?
如果发现一个帖子,其中有人提到 https:/www.nuget.orgpackagesResXResourceReader.NetStandard.
但我不知道它是否适合我的需求... ...
所以,试图实现Laz的共享资源解决方案。
到目前为止,在启动时,我有这样的功能:在? ConfigureServices
:
services.AddMvc()
.SetCompatibilityVersion(CompatibilityVersion.Version_2_1)
.AddDataAnnotationsLocalization(options => {
options.DataAnnotationLocalizerProvider = (type, factory) =>
factory.Create(typeof(SharedResources));
services.AddLocalization();
services.Configure<RequestLocalizationOptions>(
opts =>
{
/* your configurations*/
var supportedCultures = new List<CultureInfo>
{
new CultureInfo("en"),
new CultureInfo("fr")
};
opts.DefaultRequestCulture = new RequestCulture("fr", "fr");
opts.SupportedCultures = supportedCultures;
opts.SupportedUICultures = supportedCultures;
}
);
并在 Configure
:
app.UseRequestLocalization();
// used to force culture to fr but doen't seem to work
var cultureInfo = new CultureInfo("fr");
CultureInfo.DefaultThreadCurrentCulture = cultureInfo;
CultureInfo.DefaultThreadCurrentUICulture = cultureInfo;
在MyProject.Common中,我有这样的结构。
MyProject.Common
-Resources
--SharedResources.cs
---SharedResources.fr.resx
---SharedResources.en.resx
--UsersResources.cs
---UsersResources.fr.resx
---UsersResources.en.resx
比方说,我想使用 SharedResources
.在 SharedResources.en.resx
我增加了资源。In SharedResources.fr.resx
我添加了资源。
现在在我的 UserService
,在 Business
层,我这样做。
private readonly IStringLocalizer Localizer;
public UserService(IStringLocalizerFactory factory)
{
var type = typeof(SharedResources);
var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName);
_localizer = factory.Create(type);
}
public void Test()
{
var test = Localizer["Test"]; //using the key of resources file i want
}
但我得到的结果是 test
变量是 "Test",也就是 "测试"。key
的资源,而不是 value
...
.net core的默认本地化设置可以基于以下几点 一个共享资源文件 或 基于类名.
在你的情况下,你可以使用共享资源的方法,但是你必须在每个controllerclass中创建cutomized localizer,为工厂提供所需的资源类型。
首先创建一个包含所需资源的类库,为每个你想要的资源类型创建一个public dummy类,这样类库结构就可以像下面这样。
// SharedResourcesLibrary.csproj
- UsersResources.cs
- UsersResources.fr-ca.resx
- UsersResources.en-ca.resx
- ContentResources.cs
- ContentResources.fr-ca.resx
- ContentResources.en-ca.resx
...
虚类是空的,它们只是作为调用相关resx文件的类型。
// Dummy users resources class
public class UsersResources { }
然后将ResourcesLibrary项目引用到其他项目中后,就可以通过调用相关资源类型(虚类)来使用资源了。
using SharedResourcesLibrary;
public class UsersController : Controller
{
private readonly IStringLocalizer _localizer;
public UsersController(IStringLocalizerFactory factory)
{
var type = typeof(UsersResources);
_localizer = factory.Create(type);
}
public IActionResult About()
{
ViewData["Message"] = _localizer["Welcome."];
}
}
要使用其他资源,只需使用相关资源类型创建本地化器。
另一种方法可以通过创建自定义的多个 IStringLocalizer
根据你的区域,然后将它们注入控制器中。
// Create one localizer for each area
public class UsersLocalizer : IStringLocalizer
{
private readonly IStringLocalizer _localizer;
public UsersLocalizer(IStringLocalizerFactory factory)
{
var type = typeof(UsersResources);
var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName);
_localizer = factory.Create(type);
}
public LocalizedString this[string name] => _localizer[name];
public LocalizedString this[string name, params object[] arguments] => _localizer[name, arguments];
// ...
}
同样,你也可以为其他区域创建本地化器......然后在启动时注册。
services.AddTransient<IStringLocalizer, UsersLocalizer>();
services.AddTransient<IStringLocalizer, AdminsLocalizer>();
services.AddTransient<IStringLocalizer, ContentLocalizer>();
// ...
这样一来,所有的本地化器都会被注册,如果你只是简单地注入... IStringLocalizer
它将获得最后注册的一个,因为所有的本地化器都实现了相同的 IStringLocalizer
接口。
所以,你必须进行类型选择,以注入正确的定位器。
public UsersController : Controller
{
private readonly IStringLocalizer _localizer;
public UsersController(IEnumerable<IStringLocalizer> localizers)
{
_localizer = localizers.FirstOrDefault(x => x.GetType() == typeof(UsersLocalizer));
}
public IActionResult About()
{
ViewData["Message"] = _localizer["Welcome."];
}
}
你可以参考这篇文章,了解不同的方式。在Asp.Net Core中用同一接口注册多个实现