我理解如何在从Controller派生的类中使用IStringLocalizer接口,例如所描述的here或here。
在不从Controller派生的类中使用IStringLocalizer的正确方法是什么?
我找不到解决这个问题的任何例子。
是否始终需要将IStringLocalizer或IStringLocalizerFactory传递给构造函数?
注意。
我知道这是一个相当普遍的问题(Stack Overflow用于具体的编程问题)。背景是我为.NET项目制作了一个本地化工具。我试图找出我的工具必须对源代码进行哪些更改以支持ASP.NET Core项目中的本地化。
答案 0 :(得分:3)
如果一个类派生自Controller,那无关紧要。
您的对象必须由依赖注入容器创建,而不是使用new运算符,如here所述。如果要在所有类中使用ASP.NET Core本地化机制,则必须采用此模式进行对象创建。
This page给出了如何创建对象的良好描述,但我将尝试举例说明它如何与本地化一起工作。
我创建了一个MyHelper类。该类期望将localizer对象传递给构造函数。它包含一个属性Hello,它返回一个本地化的字符串。
namespace AddingLocalization.Classes
{
public class MyHelper
{
private readonly IStringLocalizer<MyHelper> _localizer;
public MyHelper(IStringLocalizer<MyHelper> localizer)
{
_localizer = localizer;
}
public string Hello
{
get
{
return _localizer["Hello World."];
}
}
}
}
在Startup类的ConfigureServices方法中,我添加了描述here的样板代码,并添加了一行来注册带有依赖注入容器的MyHelper类。
public void ConfigureServices(IServiceCollection services)
{
services.AddLocalization(opts => opts.ResourcesPath = "Resources");
services.AddMvc()
.AddViewLocalization (
LanguageViewLocationExpanderFormat.Suffix,
opts => opts.ResourcesPath = "Resources" )
.AddDataAnnotationsLocalization();
// This line registers the class MyHelper with the
// Dependency Injection Container.
services.AddTransient<MyHelper>();
}
在我的控制器类中,我向构造函数添加了一个MyHelper类型的参数,该参数存储在一个成员变量中。
public class HomeController : Controller
{
private readonly IStringLocalizer<HomeController> _localizer ;
private readonly MyHelper _h ;
public HomeController ( IStringLocalizer<HomeController> localizer,
MyHelper h )
{
_localizer = localizer;
_h = h ;
}
...
public IActionResult About()
{
ViewData["Message"] = _h.Hello ;
return View();
}
...
}
因为已经使用依赖注入容器注册了类MyHelper,所以它会创建此对象并自动将其传递给构造函数。这是依赖注入容器执行的魔术。
在About()方法中,我从MyHelper对象中获取属性。
关于代码的问题,但我想确定它实际上会从资源文件中读取字符串。
资源文件的命名约定描述为here:
它基于类的全名,没有程序集的名称。在我的情况下,类称为AddingLocalization.Classes.MyHelper,程序集称为AddingLocalization,因此相关名称为Classes.MyHelper。
实际上有两个命名约定,使用点或子目录,所以我们可以调用资源文件之一
ConfigureServices中的样板代码指定了ResourcesPath&#34; Resources&#34;,因此这是我们必须放置资源文件的地方。我选择了第二个命名选项,所以我的资源文件是
我们不需要Visual Studio创建文件MyHelper.Designer.cs来访问资源,因此我们应该清除资源文件的CustomTool属性。
这很重要,因为如果我们不禁用自定义工具,名称将不是有效的资源名称,并且可能会生成错误消息。
(以前的本地化方法(来自Microsoft)一直使用伪造的资源名称(例如,使用undercrore而不是space)来访问资源。新的ASP.NET核心本地化使用原始字符串作为资源名称。)
最后我定义了一个资源字符串,如下所示:
我还没有真正尝试用其他语言访问资源(但是),但是本地化程序对象确实正确地读取了资源。
答案 1 :(得分:0)
您可以通过创建一个名为“Resources”而不是 on Web/API 项目。 但请确保启动时资源位置相对路径的值为空。
services.AddLocalization(options => options.ResourcesPath = "");
您的 SharedResouce.cs 文件如下所示。
namespace your.business.library.namespace.Resources
{
public interface ISharedResource
{
}
public class SharedResource : ISharedResource
{
private readonly IStringLocalizer _localizer;
public SharedResource(IStringLocalizer<SharedResource> localizer)
{
_localizer = localizer;
}
public string this[string index]
{
get
{
return _localizer[index];
}
}
}
}
定义访问所需业务类的字段。
private readonly IStringLocalizer<SharedResource> _localizer;
public AppointmentBookingBL(IStringLocalizer<SharedResource> localizer)
{
_localizer = localizer;
}
从如下资源中获取消息
public void ModifyBooking(BookingModel model)
{
......... code here
var message = _localizer["BOOKINGNOTAVAILABLE"];
..... code here
}