ASP.Net Core MVC中的本地化未能正常工作-无法定位资源文件

23
尝试本地化我的应用程序,我按照这里的步骤进行操作:https://docs.asp.net/en/latest/fundamentals/localization.html 以下是我的代码:
Startup.cs
public List<IRequestCultureProvider> RequestCultureProviders { get; private set; }

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    services.AddLocalization(options => options.ResourcesPath = "Resources");

    services.AddMvc()
        .AddViewLocalization(options => options.ResourcesPath = "Resources")
        .AddDataAnnotationsLocalization();

    services.AddOptions();

    services.AddTransient<IViewRenderingService, ViewRenderingService>();

    services.AddTransient<IEmailSender, EmailSender>();
}

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

    app.UseStaticFiles();
    app.UseFileServer(new FileServerOptions()
    {
        FileProvider = new PhysicalFileProvider(
        Path.Combine(Directory.GetCurrentDirectory())),
        EnableDirectoryBrowsing = true
    });

    var supportedCultures = new[]
    {
        new CultureInfo("en-US"),
        new CultureInfo("fr"),
    };

    app.UseRequestLocalization(new RequestLocalizationOptions
    {
        DefaultRequestCulture = new RequestCulture("fr"),
        // Formatting numbers, dates, etc.
        SupportedCultures = supportedCultures,
        // UI strings that we have localized.
        SupportedUICultures = supportedCultures,
        RequestCultureProviders = new List<IRequestCultureProvider>
        {
           new QueryStringRequestCultureProvider
           {
               QueryStringKey = "culture",
               UIQueryStringKey = "ui-culture"
           }
        }
    });


}

MyController.cs

public class MyController : Controller
{
    private readonly IViewRenderingService _viewRenderingService;
    private IStringLocalizer<MyController> _localizer;
    private MyOptions _options;
    //Constructor for dependency injection principle
    public MyController(IViewRenderingService viewRenderingService, IStringLocalizer<MyController> localizer, IOptions<MyOptions> options)
    {
        _viewRenderingService = viewRenderingService;
        _localizer = localizer;
        _options = options.Value;
    }

    [HttpGet]
    public string Get()
    {
        // _localizer["Name"] 
        return _localizer["Product"];
    }
}

*.resx文件存储在Resources文件夹中,名称为Controllers.MyController.fr.resx(其中有一个"Product"的条目)。

然而,它无法找到资源文件,因此"Product"从未以法语返回。我正在使用查询字符串,因此这是查询字符串:

localhost:3333/my?culture=fr

在视图中,@Localizer["Product"] 返回 "Product"。

有人能帮我找到缺少的内容吗?

编辑:

经过一些调查,我发现文化正在改变,但无法定位资源文件。 我正在使用VS2015,请问有人能帮忙吗?


法国的文化字符串是 fr-FR - JK.
@JK。仍然是相同的结果,如果您检查我提供的链接,他们也只使用了“fr”文化。 - genericuser
2
你弄清楚问题出在哪里了吗? - Simon
15个回答

29

我曾遇到类似的问题,后来发现我的项目中缺少了 "Localization.AspNetCore.TagHelpers" NuGet 包。 看起来这是 QueryStringRequestCultureProvider 所必需的包。


1
谢谢您提供这个未记录的步骤! - Alessandro
4
为什么 Asp.net core 的本地化在 MSDN 文档中缺乏明确的记录和清晰的说明! - Mustafah
1
让我困惑了很长时间——阅读/观看了许多教程,都没有提及到这一点。随后找到了这条评论,添加了这个包,一切都正常工作了。谢谢。 - Matt
1
只是提醒一下,您应该意识到 Localization.AspNetCore.TagHelpers 包不是来自 Microsoft,对吧?当然这不是官方文档,也没有官方支持。 - Camilo Terevinto
1
对我来说,NuGet包Microsoft.Extensions.Localization非常重要。 - Kai Hartmann
显示剩余7条评论

7
我在 .net core 2.2 中遇到了同样的问题,在调试器中看到了 SearchedLocation 属性的属性值 enter image description here 因此,我首先创建了没有语言扩展名的 Controllers.HomeController.rsx 文件,并设置访问修饰符“Public”以访问该属性 enter image description here 使用 localizer["Property],我找到了正确的值。
之后,我创建了 Controllers.HomeController.fr.resx 文件,并通过 URL 中的区域设置找到了正确的值。

5
我通过将resx资源文件的构建操作设置为“嵌入式资源”来解决了这个问题。 在此输入图片描述

1
是的,在通过Visual Studio的添加新项窗口添加后,其默认构建操作为“无”。非常感谢! - ˈvɔlə

5

如果程序集的根命名空间与程序集名称不同:

默认情况下无法进行本地化。由于资源在程序集内部的搜索方式,本地化会失败。RootNamespace是编译时的值,不可在执行过程中使用。

如果RootNamespace与AssemblyName不同,在AssemblyInfo.cs中添加以下内容(将参数值替换为实际值):

using System.Reflection;
using Microsoft.Extensions.Localization;

[assembly: ResourceLocation("Resource Folder Name")]
[assembly: RootNamespace("App Root Namespace")]

更多信息请参见此处

那对我起作用了,我编辑了项目文件并删除了<RootNamespace>属性。 - Wael Alshabani
为了帮助您确定值未解析的原因,您可以注入IStringLocalizerFactory并查看_localizerCache非公共成员。您可以看到它正在尝试加载哪个资源。 - T Brown
1
这绝对是我的问题。我想分享一个建议,“在项目名称中不要使用连字符(-),因为它们在程序集中保持原样,但在命名空间中更改为下划线(_)”! - Antonio Buonaiuto

5
在我的情况下,问题是我指定了:
services.AddLocalization(options => options.ResourcesPath = "Resources");

并且:

options.DataAnnotationLocalizerProvider = (type, factory) => 
    factory.Create(typeof(DataAnnotations));

我的DataAnnotations.resx资源文件也位于“Resources”命名空间下。这导致本地化程序搜索"MyApp.Resources.Resources.DataAnnotations"中的字符串,而不是"MyApp.Resources.DataAnnotations"。

将第一行更改为:

services.AddLocalization();

协助解决了问题。


3

默认情况下,Visual Studio IDE会自动解析程序集引用,但需要使用Microsoft.Extensions.Localization和Microsoft.Extensions.Localization.Abstractions NuGets。一旦将它们添加到项目引用中,资源定位器就能够找到资源文件!


3
我花了一个小时去解决同样的问题,结果发现(在我的情况下)我没有将资源文件的访问修饰符设置为public。一旦设置为公共,它就可以正常工作了。 enter image description here 也许值得再次检查一下,以确保您不会无缘无故地进行一小时的调试 ;)

2

对我来说,问题在于项目文件夹的名称与根命名空间不同!Core 3.0。

最初的回答:

对我来说,一个问题是项目文件夹的名称与根命名空间不同。这是在使用 Core 3.0 时遇到的。


几个小时后,我这边出现了类似的问题! 项目名称以数字开头,命名空间自动分配“_”作为前缀,但本地化无法正常工作。并且所有路径都是正确的(在调试中也进行了检查)。Core 2.2 - miki

2

您需要从 nuget 添加以下引用:

Microsoft.Extensions.Localization

而且Localization.AspNetCore.TagHelpers可以作为一个很好的标签助手,而不是每次将本地化内容注入视图中。


1
在我的情况下,我实际上是缺少对ResourcesPath的显式设置:
services.AddLocalization(options => options.ResourcesPath = "Resources");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接