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

问题描述 投票:0回答:4

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

  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>

^ 请注意这两个字符串:“Message”将使用

IStringLocalizer

 从代码中本地化(请参阅下面的 HomeController),@Localizer 将使用 
IViewLocalizer
 类。

HomeController.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(); } }

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?}"); }); }

资源:

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>
 
failed 无法意识到指定了 lang,或者无法找到明显可用的 fr-CH.resx。

为什么???

顺便说一句,我也尝试使用 ShareResource 示例(请参阅下面的链接),并将工厂作为

IStringLocalizerFactory factory

 传递给 HomeController ctor,同样没有爱,仍然没有获得 fr-CH 资源。  叹息。

其他注意事项:

以此作为我的主要参考:

https://learn.microsoft.com/en-us/aspnet/core/fundamentals/localization

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

c# asp.net-core localization asp.net-core-2.0 asp.net-core-localization
4个回答
12
投票
您正在使用

IStringLocalizer<HomeController>

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

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

    注入
  • IStringLocalizer<T>
    
    
  • 注入
  • IStringLocalizerFactory
    
    
有关资源文件名的更多信息,请查看文档中的

资源文件命名部分。

注入 IStringLocalizer

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

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

资源文件:

    确保您有
  • 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); }

资源文件:

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

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

services.AddLocalization(options => options.ResourcesPath = "Resources");

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


0
投票
尝试 tmg 在

这个答案中描述的技术。

具体来说,尝试添加行

options.RequestCultureProviders = new List<IRequestCultureProvider> { new QueryStringRequestCultureProvider(), new CookieRequestCultureProvider() };

到您的ConfigureServices()函数


0
投票
出现错误是因为找不到.resx文件的路径。通过修改Startup.cs或Program.cs中的路径解决

builder.Services.AddLocalization(options => options.ResourcesPath = "");
    
© www.soinside.com 2019 - 2024. All rights reserved.