【问题标题】:How to get resource strings in strongly typed way in asp.net core?如何在asp.net核心中以强类型方式获取资源字符串?
【发布时间】:2021-01-20 00:01:59
【问题描述】:

在下面的程序中,为了获取资源字符串,我使用 _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"];
        }
    }
}

【问题讨论】:

  • resx 资源支持本地化,值的访问是强类型的,这要归功于为您创建类的代码生成器。您可以从 Visual Studio 中的 Add > New Item 添加资源文件。

标签: c# .net asp.net-core asp.net-core-localization


【解决方案1】:
  1. 使用您的翻译创建一个资源文件 (.resx)。例如,如果您正在本地化 AboutController,则类似于 AboutController.String.resx

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

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

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

    这也适用于 using static 技巧:

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

    您也可以将它与 ASP 的本地化程序一起使用。在这种特殊情况下,这不会增加任何价值,但对 IHtmlLocalizer 很有用,因为它会为您转义值。

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

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

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

对于许多开发人员来说,没有默认语言 .resx 文件并简单地包装字符串文字的新工作流程可以减少本地化应用程序的开销。其他开发人员会更喜欢传统的工作流程,因为它可以更轻松地处理更长的字符串文字并更轻松地更新本地化字符串。

【讨论】:

  • 如何在视图中使用它?
  • 您需要将其设置为公开才能在 Razor 页面中工作 (@Localizer(nameof(Thing)])
  • 哥们,你刚刚太棒了
【解决方案2】:

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

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

    // ... other keys here
}

然后你可以在任何地方消费它。好处之一是,由于这是该类的成员,如果密钥发生更改,您可以使用通用重构工具安全地替换对它的所有引用,而不是尝试对“魔术字符串”进行全局字符串替换。另一个好处是您可以在访问课程时使用智能感知。我想人们可以认为这是“强类型”。

你会这样消费它:

[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,你也可以使用静态使用。这将允许您引用您指定的类型的成员。最后,对于简单的“单行”返回,我们可以使它们成为表达式体。例如:

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
    }
}

【讨论】:

  • 伙计们,但是您如何更改语言?您是否只是设置当前线程的 ui 文化?在具有多个线程的 asp.net 核心应用程序中,它似乎不适用于我,因为它仅更改 1 个线程,并且用户可能有多个线程
  • 嘿@AJ222,这是一个单独的问题。我建议你创建一个新问题,引用这个问题。
【解决方案3】:

仅供今天查看此内容的人使用:我不知道,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”项目中可以正常工作。

【讨论】:

    猜你喜欢
    • 2011-05-20
    • 2011-01-06
    • 2023-03-19
    • 2011-05-30
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多