如何使用 IStringLocalizer 从 ASP.NET Core 控制器获取本地化字符串?

dap*_*pug 3 c# localization asp.net-core asp.net-core-localization asp.net-core-2.0

这里有点困惑,ASP.Net Core 2.0 中本地化的超级简单 hello-world 示例。我的关于页面设置为呈现两个本地化字符串:

  1. 从视图(使用IViewLocalizer
  2. 来自代码(IStringLocalizer<HomeController>通过控制器使用)

控制器中的代码拒绝适当地获取 loc 字符串。这并不复杂,我错过了什么明显的东西?

关于.cshtml

@using Microsoft.AspNetCore.Mvc.Localization

@inject IViewLocalizer Localizer
@{
    ViewData["Title"] = "About";
}
<h2>@ViewData["Title"]</h2>
<h3>@ViewData["Message"]</h3>

<p>@Localizer["Use this area to provide additional information."]</p>
Run Code Online (Sandbox Code Playgroud)

^ 请注意这两个字符串:“Message”将使用代码本地化IStringLocalizer(请参阅下面的 HomeController),@Localizer 将使用IViewLocalizer该类。

家庭控制器.cs

public class HomeController : Controller
{
    private readonly IStringLocalizer _localizer;

    public HomeController(IStringLocalizer<HomeController> localizer)
    {
       _localizer = localizer;
    }

    public IActionResult Index()
    {
        return View();
    }

    public IActionResult About()
    {
        ViewData["Message"] = _localizer["Your application description page."];

        return View();
    }
}
Run Code Online (Sandbox Code Playgroud)

Startup.cs(相关部分)

    public void ConfigureServices(IServiceCollection services)
    {
        services.AddLocalization(options => options.ResourcesPath = "Resources");

        services.AddMvc()
            .AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
            .AddDataAnnotationsLocalization();

        services.Configure<RequestLocalizationOptions>(options =>
        {
            var supportedCultures = new[]
            {
                new CultureInfo("en-US"),
                new CultureInfo("fr-CH"),
            };

            options.DefaultRequestCulture = new RequestCulture(culture: "en-US", uiCulture: "en-US");
            options.SupportedCultures = supportedCultures;
            options.SupportedUICultures = supportedCultures;
        });
    }

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        var locOptions = app.ApplicationServices.GetService<IOptions<RequestLocalizationOptions>>();
        app.UseRequestLocalization(locOptions.Value);

        if (env.IsDevelopment())
        {
            app.UseBrowserLink();
            app.UseDeveloperExceptionPage();
        }
        else
        {
            app.UseExceptionHandler("/Home/Error");
        }

        app.UseStaticFiles();

        app.UseMvc(routes =>
        {
            routes.MapRoute(
                name: "default",
                template: "{controller=Home}/{action=Index}/{id?}");
        });
    }
Run Code Online (Sandbox Code Playgroud)

资源:

Views.Home.About.fr-CH.resx

^ 有两个值:

  • “使用此区域提供更多信息。” = "使用这个区域...... fr-CH 成功!"
  • “您的应用程序描述页面。” = "您的应用描述... fr-CH 成功!"

我的结果:

本地主机:56073/首页/关于

^ 这会在 en-US 中按预期呈现字符串(默认找不到任何内容,使用实际硬编码的字符串)

本地主机:56073/家/关于?culture=fr-CH

^ 这仅呈现第二个字符串:“使用此区域... fr-CH 成功!”,这显然意味着连接的所有代码都在工作并按预期找到 fr-CH.resx。

但是,第一个字符串(在代码中设置为ViewData["Message"])没有得到 fr-CH 版本!这就像IStringLocalizer<HomeController> 没有意识到指定了一个 lang,或者没有找到明显可用的 fr-CH.resx。

为什么???

另外顺便说一句,我也尝试使用 ShareResource 示例(参见下面的链接),并将工厂传递给 HomeController ctor as IStringLocalizerFactory factory,同样没有爱,仍然没有获得 fr-CH 资源。叹。

其他注意事项:

将此作为我的主要参考:https : //docs.microsoft.com/en-us/aspnet/core/fundamentals/localization

使用 VS 2017,最新更新,ASP.Net Core 2.0

Ond*_*nek 12

问题在于 ASP .NET Core 使用 IStringLocalizer 创建了错误的 RESX 命名空间以进行本地化。如果你的代码中有

services.AddLocalization(options => options.ResourcesPath = "Resources");
Run Code Online (Sandbox Code Playgroud)

那么注入的服务 IStringLocalizer 的实例在命名空间中有两次“Resources”,命名空间看起来为“Resources.Resources”。这就是RESX找不到的根本原因。


Rez*_*aei 7

IStringLocalizer<HomeController>在控制器中用作定位器来查找本地化字符串。本地化程序将在Resources文件夹中查找YouControllerNameSpace.HomeController资源文件,由于找不到它,它将返回您传递给本地化程序的原始密钥。

要解决此问题,您可以使用以下任一选项:

  • 注入 IStringLocalizer<T>
  • 注入 IStringLocalizerFactory

有关资源文件名的更多信息,请查看文档中的资源文件命名部分。

注入 IStringLocalizer<T>

使用此选项,您应该有一个与 T 的全名同名的资源文件,在您的情况下,控制器代码应该与它相同:

IStringLocalizer _localizer;
public HomeController(IStringLocalizer<HomeController> localizer)
{
   _localizer = localizer;
}
Run Code Online (Sandbox Code Playgroud)

对于资源文件:

  • 确保你有YouControllerNameSpace.HomeController资源文件。(YouControllerNameSpace只是一个占位符,使用您的控制器命名空间。)
  • 确保您在资源文件中有指定的字符串。
  • 确保你有不同文化的资源文件。

注入 IStringLocalizerFactory

使用此选项,您可以将任何文件用作资源文件。例如,如果您想从Views.Home.About资源文件中读取资源,您应该将控制器代码更改为:

IStringLocalizer _localizer;
public HomeController(IStringLocalizerFactory factory)
{
    _localizer = factory.Create("Views.Home.About", 
        System.Reflection.Assembly.GetExecutingAssembly().GetName().Name);
}
Run Code Online (Sandbox Code Playgroud)

对于资源文件:

  • 确保你有Views.Home.About资源文件。
  • 确保您在资源文件中有指定的字符串。
  • 确保你有不同文化的资源文件。