如何在asp.net核心中获取resx文件字符串? 我在mvc中使用ResxResourceReader获取字符串。但我无法在asp.net核心中获得同样的效果。
答案 0 :(得分:26)
.NET Core改变了资源文件的工作方式,我认为这种方式低于标准并令人困惑(花了我几天才弄明白),但这就是你需要做的事情:
将以下代码添加到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;
});
在任何要存储resx文件的项目中创建一个文件夹 - 默认情况下,将其命名为“Resources”。
创建一个新的resx文件,其中包含您稍后将查找的特定文化和文件名:如果您有共享文件,则可以执行以下操作:SharedResource.en-US.resx。然后关闭自动代码生成,因为它现在没用了。
在与resx文件相同的位置创建一个名为“SharedResource”的类。它可以是空白的,只需要在那里就可以在以后引用它。
无论您想在何处使用资源,IoC注入(在此示例中)IStringLocalizer&lt; SharedResource&gt;名称为“_localizer”或其他。
最后,您可以通过执行_localizer [“My_Resource_Name”]
通过在同一文件夹中创建名为“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];
}
答案 1 :(得分:3)
要进行更直接的替换,我创建了release notes,它为.NET Standard(也意味着.NET Core)重新打包了ResXResourceReader
和ResXResourceWriter
。
答案 2 :(得分:0)
旧方式版本(如在asp.net中)是创建一个默认资源文件,如MyResources.resx和其他文件,用于不同的文化MyResources.fr.resx,...并使用MyResources.MyValue1从中检索值。创建MyResources.resx将生成一个.cs文件,其中包含所有资源值作为静态属性。
.Net Core建议使用IStringLocalizer<T>
,其中T是由您创建的与资源文件名称匹配的类。您可以在没有任何资源文件的情况下开始开发并稍后添加它您必须在控制器上注入(IStringLocalizer&lt; MyResources&gt; localizer),然后使用_localizer获取值[&#34; MyValue1&#34;];
您可以查看.net核心官方文档here
答案 3 :(得分:-3)