I understand how to use the IStringLocalizer interface in a class which derives from Controller, for example as described here or here.
What would be the correct way to use IStringLocalizer in a class which does not derive from Controller?
I cannot find any examples addressing this question.
Is it always necessary to pass in an IStringLocalizer or IStringLocalizerFactory to the constructor?
Note.
I know that this is a fairly generic question (and Stack Overflow is for concrete programming questions). The background is that I make a localization tool for .NET projects. I am trying to figure out what changes my tool has to make to the source code to support localization in ASP.NET Core projects.
Globalization is the process of designing the application in such a way that it can be used by users from across the globe (multiple cultures). Localization, on the other hand, is the process of customization to make our application behave as per the current culture and locale.
It doesn't matter if a class derives from Controller.
It is important that your objects are created by the Dependency Injection Container and not by using the new operator, as described here. If you want to use the ASP.NET Core localization mechanism in all your classes, you must adopt this pattern for object creation.
This page gives a good description of how to create objects, but I will try to give an example of how it works with localization.
I have created a class MyHelper. The class expects the localizer object to be passed in to the constructor. It contains a single property Hello, which returns a localized string.
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."];
}
}
}
}
In the ConfigureServices method in the Startup class, I have added the boilerplate code described here and added a line to register the class MyHelper with the Dependency Injection container.
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>();
}
In my controller class, I have added a parameter of type MyHelper to the constructor, which is stored in a member variable.
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();
}
...
}
Because the class MyHelper has been registered with the dependency injection container, it creates this object and passes it in to the constructor automatically. This is the magic performed by the dependency injection container.
In the About() method, I fetch the property from the MyHelper object.
That's about it for the code, but I wanted to be certain that it will actually read the string from a resource file.
The naming convention for resource files is described here:
It is based on the full name of the class, without the name of the assembly. In my case class is called AddingLocalization.Classes.MyHelper and the assembly is called AddingLocalization, so the relevant name is Classes.MyHelper.
There are actually two naming conventions, using dots or subdirectories, so we can call the resource file one of
The boilerplate code in ConfigureServices specified the ResourcesPath "Resources", so this is where we must place the resource file. I chose the second naming option, so my resource file is
as you can see in the solution explorer
We do not need Visual Studio to create a file MyHelper.Designer.cs to access the resources, so we should clear out the CustomTool property for the resource file.
This is important, because the names will not be valid resource names and will probably generate error messages, if we do not disable the custom tool.
(Previous localization methods (from Microsoft) have always used fabricated resource names (e.g. with underscrore instead of space) to access resources. The new ASP.NET core localization uses the original string as the resource name.)
Finally I have defined a resource string as shown below:
I haven't actually tried accessing resources in a different language (yet), but the localizer object did read the resource correctly.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With