如何实现资源文件本地化ASP-NET.core?
How to implement resource files localization ASP-NET.core?
我被要求在 net.core
解决方案中实现本地化,如下所示:
资源文件必须在单独的项目中(如“MyProject.Common”)才能在解决方案的所有其他项目中使用,
资源必须按“部分”划分,例如,我们在 Web 项目中有 3 个区域,如下所示:
Users
,
Content
,
Administration
,
所以我被要求有这样的东西:
- UsersResources.fr-CA.resx,
- UsersResources.en-CA.resx,
- ContentResources.fr-Ca.resx,
- ...
我开始阅读 Localization is AP-NET core 的文档,但我对 itr 的工作原理有点困惑。
似乎我被告知要做的事情是不可能的。
事实是,我可能需要使用业务、视图和控制器中的资源,所以我正在寻找一种实现它的方法,以便团队可以通过调用 ContentResources.MyCustomResource
.
有没有办法接近它?
我发现 post 有人提到 https://www.nuget.org/packages/ResXResourceReader.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
我添加了资源:
在SharedResources.fr.resx
我添加了资源:
现在在我的 UserService
层中,我这样做了:
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 的默认本地化设置可以基于one shared resource file or based on the class name。
在您的情况下,您可以使用共享资源方法,但您必须通过为工厂提供所需的资源类型来在每个 controller/class 中创建自定义本地化程序。
首先用所需的资源创建一个class库,为每个你想要的资源类型创建一个public虚拟class,这样class库结构就可以了如下所示:
// SharedResourcesLibrary.csproj
- UsersResources.cs
- UsersResources.fr-ca.resx
- UsersResources.en-ca.resx
- ContentResources.cs
- ContentResources.fr-ca.resx
- ContentResources.en-ca.resx
...
The dummy classes are empty, they are used just as a type to call the relevant resx file.
// Dummy users resources class
public class UsersResources { }
然后将ResourcesLibrary项目引用到其他项目中后,就可以通过调用相关资源类型(dummy class)来使用资源了。:
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."];
}
}
不同的方式可以参考这篇文章Registering multiple implementation with the same interface in Asp.Net Core
我被要求在 net.core
解决方案中实现本地化,如下所示:
资源文件必须在单独的项目中(如“MyProject.Common”)才能在解决方案的所有其他项目中使用,
资源必须按“部分”划分,例如,我们在 Web 项目中有 3 个区域,如下所示:
Users
,Content
,Administration
,
所以我被要求有这样的东西:
- UsersResources.fr-CA.resx,
- UsersResources.en-CA.resx,
- ContentResources.fr-Ca.resx,
- ...
我开始阅读 Localization is AP-NET core 的文档,但我对 itr 的工作原理有点困惑。 似乎我被告知要做的事情是不可能的。
事实是,我可能需要使用业务、视图和控制器中的资源,所以我正在寻找一种实现它的方法,以便团队可以通过调用 ContentResources.MyCustomResource
.
有没有办法接近它?
我发现 post 有人提到 https://www.nuget.org/packages/ResXResourceReader.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
我添加了资源:
在SharedResources.fr.resx
我添加了资源:
现在在我的 UserService
层中,我这样做了:
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 的默认本地化设置可以基于one shared resource file or based on the class name。
在您的情况下,您可以使用共享资源方法,但您必须通过为工厂提供所需的资源类型来在每个 controller/class 中创建自定义本地化程序。
首先用所需的资源创建一个class库,为每个你想要的资源类型创建一个public虚拟class,这样class库结构就可以了如下所示:
// SharedResourcesLibrary.csproj
- UsersResources.cs
- UsersResources.fr-ca.resx
- UsersResources.en-ca.resx
- ContentResources.cs
- ContentResources.fr-ca.resx
- ContentResources.en-ca.resx
...
The dummy classes are empty, they are used just as a type to call the relevant resx file.
// Dummy users resources class
public class UsersResources { }
然后将ResourcesLibrary项目引用到其他项目中后,就可以通过调用相关资源类型(dummy class)来使用资源了。:
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."];
}
}
不同的方式可以参考这篇文章Registering multiple implementation with the same interface in Asp.Net Core