如何在 asp.net 核心中以强类型方式获取资源字符串?

How to get resource strings in strongly typed way in asp.net core?

在下面的程序中,为了获取资源字符串,我使用了 _localizer["About Title"],其中 "About Title" 是一个魔法字符串。如何避免使用这样的字符串?有没有强类型的方法?

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Localization;

namespace Localization.StarterWeb.Controllers
{
    [Route("api/[controller]")]
    public class AboutController : Controller
    {
        private readonly IStringLocalizer<AboutController> _localizer;

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

        [HttpGet]
        public string Get()
        {
            return _localizer["About Title"];
        }
    }
}

如果您试图避免使用硬编码字符串(键)来查找本地化转换,您可以创建一个包含查找键的 LocalizationKeys class。然后,您可以利用 C# 6 nameof 运算符。这将有助于减轻 "magic strings".

的担忧
public static class LocalizationKeys
{
    public const string AboutTitle = nameof(AboutTitle); // Note: this is "AboutTitle"

    // ... other keys here
}

然后你可以在任何地方消费它。其中一个好处是,由于这是 class 的成员,如果键更改,您可以使用常见的重构工具安全地替换对它的所有引用,而不是尝试在 [= 上进行全局字符串替换28=]。另一个好处是您可以在访问 class 时使用智能感知。我想人们可以考虑这个 "strongly typed".

你会这样消费它:

[Route("api/[controller]")]
public class AboutController : Controller
{
    private readonly IStringLocalizer<AboutController> _localizer;

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

    [HttpGet]
    public string Get()
    {
        return _localizer[LocalizationKeys.AboutTitle];
    }
}

如果您真的想使用 C# 6,您也可以使用静态用法。这将允许您引用您指定类型的成员。最后,对于简单的"single line"returns,我们可以把它们做成表达式体。例如:

using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Localization;
using static Localization.StarterWeb.LocalizationKeys; // Note: static keyword

namespace Localization.StarterWeb.Controllers
{
    [Route("api/[controller]")]
    public class AboutController : Controller
    {
        private readonly IStringLocalizer<AboutController> _localizer;

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

        [HttpGet]
        public string Get() => _localizer[AboutTitle]; // Note: omission of qualifier
    }
}
  1. 使用您的翻译创建一个资源文件 (.resx)。例如,如果您要本地化 AboutController,那将类似于 AboutController.String.resx.

  2. 通过在编辑资源屏幕上将访问修饰符从“无代码生成”更改为“Public”或“内部”,为您的资源文件启用代码生成。保存时,这将为您的资源文件创建一个 .Designer.cs class。它将为资源文件中的每个键包含一个静态 属性。不要手动修改生成的class。每次修改 .resx.

    后都会自动重新生成

  1. 在您的控制器中使用生成的设计器 class 来获取翻译后的文本(在这种情况下不需要字符串本地化):

     [HttpGet]
     public string Get()
     {
         return AboutController_Strings.AboutTitle;
     }
    

    这也适用于 using static 技巧:

     using static Localization.StarterWeb.AboutController_Strings;
    
     //(...)
    
     [HttpGet]
     public string Get()
     {
         return AboutTitle;
     }
    

    或者,您可以将它与 ASP 的本地化程序一起使用。这在特定情况下没有任何价值,但对 IHtmlLocalizer 很有用,因为它会 html- 为您转义值。

     [HttpGet]
     public string Get()
     {
         return _localizer[nameof(AboutTitle)];
     }
    

为什么这比接受的答案更好?这样你就不需要手动创建和维护所有 LocalizationKeys-like classes 里面有很多 const 字符串。 (在更大的项目中会有成百上千个!)生成的 .Designer.cs class 将包含资源文件中的所有键。而已。没什么。如果您从资源填充中删除某些内容,它将从生成的代码中删除,并在使用删除的 属性 的任何地方在您的代码中产生编译错误。如果您向资源文件添加一些内容,它将在保存资源文件时自动生成一个新的 属性,它将出现在代码完成中。

这是一种更传统的方法,例如 WinForms 最初采用的方法。在 Microsoft 的 documentation for localizing ASP.NET Core 应用程序中有一个简短的解释,为什么他们添加了一种使用 IStringLocalizer 的新方法:硬编码翻译字符串使您的工作流程更快。除非需要,否则无需维护额外的东西。

For many developers the new workflow of not having a default language .resx file and simply wrapping the string literals can reduce the overhead of localizing an app. Other developers will prefer the traditional work flow as it can make it easier to work with longer string literals and make it easier to update localized strings.

仅供今天查看此内容的人使用:我不知道,当 Microsoft 添加此内容时,但在 .Net 5.0 中,您可以简单地对您的 Configure 函数执行此操作:

app.UseRequestLocalization(options =>
        {
            var supportedCultures = new[]
            {
                new CultureInfo("en"),
                new CultureInfo("de")
            };
            options.DefaultRequestCulture = new RequestCulture("en", "en");
            options.SupportedCultures = supportedCultures;
            options.SupportedUICultures = supportedCultures;
        });

并且只需使用带有静态生成 类 的普通资源文件,而不需要 IStringLocalizer 或类似的东西。 我不知道,如果你可以简单地在 razorpages 或类似的东西中使用它们,但它在普通的“webapi”项目中按预期工作。