如何在asp.net核心中获取.resx文件字符串

Ila*_*a.B 23 c# asp.net-core

如何在asp.net核心中获取resx文件字符串?我在mvc中使用ResxResourceReader获取字符串.但是我无法在asp.net核心中获得相同的功能.

Dan*_*enz 35

.NET Core改变了资源文件的工作方式,我认为这种方式低于标准并令人困惑(花了我几天的时间来弄清楚),但这是你需要做的:

  1. 将以下代码添加到Startup.cs - 注意:更改您支持的语言,"资源"的ResourcePath将只是您以后存储.resx文件的文件夹

            services.AddLocalization(o => o.ResourcesPath = "Resources");
            services.Configure<RequestLocalizationOptions>(options =>
            {
                var supportedCultures = new[]
                {
                    new CultureInfo("en-US"),
                    new CultureInfo("en-GB"),
                    new CultureInfo("de-DE")
                };
                options.DefaultRequestCulture = new RequestCulture("en-US", "en-US");
    
                // You must explicitly state which cultures your application supports.
                // These are the cultures the app supports for formatting 
                // numbers, dates, etc.
    
                options.SupportedCultures = supportedCultures;
    
                // These are the cultures the app supports for UI strings, 
                // i.e. we have localized resources for.
    
                options.SupportedUICultures = supportedCultures;
            });
    
    Run Code Online (Sandbox Code Playgroud)
  2. 在要存储resx文件的任何项目中创建一个文件夹 - 默认情况下,将其命名为"Resources".

  3. 创建一个新的resx文件,其中包含您稍后将查找的特定文化和文件名:如果您有共享文件,则可以执行以下操作:SharedResource.en-US.resx.然后关闭自动代码生成,因为它现在没用.

  4. 在与resx文件相同的位置创建一个名为"SharedResource"的类.它可以是空白的,它只需要在那里,以便您以后可以参考它.

  5. 无论您想在何处使用资源,IoC都会注入(在此示例中)IStringLocalizer <SharedResource>,其名称为"_localizer"或其他内容.

  6. 最后,您可以通过_localizer ["My_Resource_Name"]引用资源文件中的条目

  7. 通过在同一文件夹中创建名为"SharedResource.de-DE.resx"的新resx文件或其他任何内容来添加另一种语言.

将在所有程序集中使用"Resource"文件夹以查看所有程序集.因此,这个文件夹可能会变得非常混乱,特别是如果你开始在这里获取视图特定的东西.

我看到开发人员在这里尝试做什么,但是他们放弃了太多而无法到达那里.人们可以编码和添加翻译内容,而无需实际翻译任何内容.他们让开发人员从一开始就更容易考虑翻译,但他们最终会为实际使用翻译的开发人员提供更多的工作.现在我们无法自动生成任何内容.我们必须向IoC注入对翻译的引用才能访问它们(除非你想使用ServiceLocater反模式,否则不再是静态的).所有的名字都是硬编码的字符串,所以现在如果你拼写错误的翻译它只会吐回你给它的字符串,从而打破了首先进行翻译的目的,这意味着你可能需要一个包装器这样你就不会依赖常数了.

说实话,我简直不敢相信有人认为这是个好主意.无论如何,为什么不关心翻译的开发者会向后弯腰?

我最终围绕这种风格创建了一个包装器.唯一的好处是,如果您决定从数据库获取资源,则不需要更改上面的代码,但现在您必须添加资源条目,将其添加到接口,然后实现它以拉动它再次退出.我使用了nameof()所以我不需要使用常量,但这仍然很脆弱,就好像属性名称或resx文件名更改一样,它会破坏翻译而不会发生任何崩溃 - 我可能需要进行集成测试确保我没有得到我发送的相同值:

public interface ICommonResource
{
    string ErrorUnexpectedNumberOfRowsSaved { get; }
    string ErrorNoRecordsSaved { get; }
    string ErrorConcurrency { get; }
    string ErrorGeneric { get; }

    string RuleAlreadyInUse { get; }
    string RuleDoesNotExist { get; }
    string RuleInvalid { get; }
    string RuleMaxLength { get; }
    string RuleRequired { get; }
}

public class CommonResource : ICommonResource
{
    private readonly IStringLocalizer<CommonResource> _localizer;

    public CommonResource(IStringLocalizer<CommonResource> localizer) =>
        _localizer = localizer;

    public string ErrorUnexpectedNumberOfRowsSaved => GetString(nameof(ErrorUnexpectedNumberOfRowsSaved));
    public string ErrorNoRecordsSaved => GetString(nameof(ErrorNoRecordsSaved));
    public string ErrorConcurrency => GetString(nameof(ErrorConcurrency));
    public string ErrorGeneric => GetString(nameof(ErrorGeneric));

    public string RuleAlreadyInUse => GetString(nameof(RuleAlreadyInUse));
    public string RuleDoesNotExist => GetString(nameof(RuleDoesNotExist));
    public string RuleInvalid => GetString(nameof(RuleInvalid));
    public string RuleMaxLength => GetString(nameof(RuleMaxLength));
    public string RuleRequired => GetString(nameof(RuleRequired));

    private string GetString(string name) =>
        _localizer[name];
}
Run Code Online (Sandbox Code Playgroud)

  • @Mayako看来您需要在ASP.NET Core 2中调用它:`services.AddLocalization();`-我知道对您来说可能为时已晚,但可能会对其他人有所帮助:) (3认同)
  • 我相信你仍然可以使用`ResXFileCodeGenerator`来生成编译时道具(如下所示:https://christianspecht.de/2017/11/29/fixing-resourcedesignercs-generation-in-net-core/ ). (2认同)

Pop*_*rei 5

旧的方式版本(如在 asp.net 中)是创建一个默认资源文件,如 MyResources.resx 和其他不同文化的文件 MyResources.fr.resx,...并从中检索值 MyResources.MyValue1 。创建 MyResources.resx 将生成一个 .cs 文件,其中包含您的所有资源值作为静态属性。

.Net Core 建议使用IStringLocalizer<T>where T 是您创建的与您的资源文件名称匹配的类。您可以在没有任何资源文件的情况下开始开发并稍后添加它们。您必须在控制器上注入(IStringLocalizer< MyResources > localizer),然后使用 _localizer["MyValue1"]; 获取值;

您可以在此处查看 .net core 官方文档

  • 他们为什么要那样做?现在我们必须使用字符串来让你得到运行时崩溃...... (6认同)
  • @DanielLorenz:我同意你的看法;我更喜欢设计器方法(在 .Net Core 中仍然有效)。您为静态定义每个资源字符串所付出的代价是您的资源类与您的应用程序紧密耦合。该成本与 Microsoft 试图避免所有依赖项以支持模块化、可注入组件的尝试不相容。在第三方库的情况下,避免耦合有很大的好处。在特定于应用程序的本地化的情况下,您的翻译本质上与您的应用程序耦合,因此紧密耦合的缺点最小。 (3认同)

far*_*121 5

为了更直接的替换,我创建了ResXResourceReader.NetStandard,它针对 .NET Standard(也意味着 .NET Core)重新ResXResourceReader打包ResXResourceWriter