解决方法
>将以下代码添加到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< SharedResource>名称为“_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]; }