如何实现资源文件本地化ASP-NET.core?

How to implement resource files localization ASP-NET.core?

我被要求在 net.core 解决方案中实现本地化,如下所示:

所以我被要求有这样的东西:

我开始阅读 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