这里有点困惑,超级简单的 Hello-world ASP.Net Core 2.0 本地化示例。">我的关于">页面设置为呈现两个本地化字符串:
- 从视图中(使用
IViewLocalizer
) - 从代码(通过控制器使用
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
类。
首页控制器.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();
}
}
启动.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/首页/关于?文化=fr-CH
^ 这只呈现第二个字符串:"使用此区域...fr-CH!"的成功!",这显然意味着所有连接的代码都在工作并按预期找到fr-CH.resx。
但是,第一个字符串(在代码中设置为ViewData["Message"]
)不会获得 fr-CH 版本! 这就像IStringLocalizer<HomeController>
没有意识到有一个指定的语言,或者没有找到明显可用的 fr-CH.resx。
为什么???
顺便说一句,我也尝试使用共享资源示例(见下面的链接),并在工厂中作为IStringLocalizerFactory factory
传递给HomeController ctor,也没有爱,仍然没有得到fr-CH资源。 叹息。
其他注意事项:
以此作为我的主要参考: https://learn.microsoft.com/en-us/aspnet/core/fundamentals/localization
使用VS 2017,最新更新,ASP.Net 核心2.0
问题是ASP .NET Core使用IStringLocalizer为本地化创建了错误的RESX命名空间。如果你在代码中有
services.AddLocalization(options => options.ResourcesPath = "Resources");
然后注入的服务IStringLocalizer的实例在命名空间中有两次"资源",命名空间看起来是"Resources.Resources"。这是找不到RESX的根本原因。
在控制器中使用IStringLocalizer<HomeController>
作为本地化器来查找本地化字符串。本地化工具将在Resources
文件夹中查找YouControllerNameSpace.HomeController
资源文件,由于找不到它,它将返回您传递给本地化人员的原始密钥。
若要解决此问题,可以使用以下任一选项:
- 注入
IStringLocalizer<T>
- 注入
IStringLocalizerFactory
有关资源文件名的详细信息,请查看文档中的资源文件命名部分。
Inject IStringLocalizer
使用此选项,您应该有一个与 T 的全名同名的资源文件,在您的情况下,控制器代码应与原样相同:
IStringLocalizer _localizer;
public HomeController(IStringLocalizer<HomeController> localizer)
{
_localizer = localizer;
}
对于资源文件:
- 确保您有
YouControllerNameSpace.HomeController
资源文件。(YouControllerNameSpace
只是一个占位符,请使用控制器命名空间。 - 请确保资源文件中具有指定的字符串。
- 确保具有不同区域性的资源文件。
Inject 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
资源文件。 - 请确保资源文件中具有指定的字符串。
- 确保具有不同区域性的资源文件。
试试 tmg 在此答案中描述的技术。
具体来说,尝试添加行
options.RequestCultureProviders = new List<IRequestCultureProvider>
{
new QueryStringRequestCultureProvider(),
new CookieRequestCultureProvider()
};
到你的 ConfigureServices() 函数