ASP.NET Core DisplayAttribute 本地化

17
根据文档说明:

运行时不会查找非验证属性的本地化字符串。在上述代码中,“Email”(来自[Display(Name =“Email”)])将不会被本地化。

我正在寻找一种在DisplayAttribute中本地化文本的方法。有什么适合的建议吗?

对于像我这样关注现代技术的读者,如果你们恰好来到这里,请注意:这在框架的后续版本中已经不再是一个问题。正如微软所述,“在ASP.NET Core MVC 1.1.0及更高版本中,非验证属性已本地化。” - MarredCheese
6个回答

19

您可以在DisplayAttribute上设置ResourceType,用于本地化您的文本。

向您的项目中添加一个资源文件.resx,例如MyResources.resx,并为您的字段添加一个资源:

enter image description here

然后在您的DisplayAttribute中引用该字段的名称和MyResources类型即可。

[Display(Name = "RememberMe", ResourceType  = typeof(MyResources))]
public bool RememberMe { get; set; }

本地化资源将自动拉取(请参见文本框)

在此输入图像描述


1
根据这个新的ASP.NET Core本地化机制,非验证属性没有本地化似乎有些奇怪。您认为是否可能将其实现到非验证属性中,或者MVC开发人员跳过非验证属性是有原因的? - David
我同意,这有点奇怪!我想他们决定不这样做一定有原因,但我一时也说不清楚。你可以在GitHub上问问,看看他们会怎么说。 - Sock
4
我收到了 "The type or namespace 'MyResources' could not be found" 的错误信息。我缺少什么? - Lucius
1
你好,我正在使用.NET Core 1.0.0,但是这个实现会抛出以下错误:InvalidOperationException: 无法检索属性“Name”,因为本地化失败。类型'<full_typename>'不是公共的,或者不包含一个名为'RememberMe'的公共静态字符串属性。有人遇到过这个错误吗? - Vladislav

11

我认为将所有本地化放在一个中心位置,无论是视图还是数据注释,是最好的方法,这也是我的做法。 在Startup.cs文件中,在安装了本地化的NuGet软件包后,请添加以下代码。

services.AddMvc().AddViewLocalization().AddDataAnnotationsLocalization(options => 
    options.DataAnnotationLocalizerProvider = (type, factory) => new StringLocalizer<Resources>(factory));

services.Configure<RequestLocalizationOptions>(options => {
   var cultures = new[]
   {
       new CultureInfo("en"),
       new CultureInfo("ar")
   };
   options.DefaultRequestCulture = new RequestCulture("en", "en");
   options.SupportedCultures = cultures;
   options.SupportedUICultures = cultures;
});

这样,DataAnnotationLocalizerProvider 将来自于 Resources.{culture}.resx (资源文件必须有一个访问修饰符为 No code gen)- 假设默认语言不需要任何资源,并且要能够访问资源文件,由于不会生成任何代码,必须创建一个同名的空类。

并且在 _ViewImports.cshtml 文件中注入以下内容:

@inject IHtmlLocalizer<Resources> Localizer
通过这样做,您现在拥有一个全局变量 Localizer ,可用于任何视图进行本地化。

这是字符串本地化的中央位置

您可以在 ASP.NET Core中的全球化和本地化 中找到更多信息


7

对于那些遇到错误(@lucius,@vladislav)的人:

无法检索属性“Name”,因为本地化失败。类型“Xxxx.EmployeeResx”不是公共的,或者不包含具有名称“FirstName”的公共静态字符串属性。

这是由.resx文件上的访问修饰符引起的,默认情况下设置为Internal(在我的情况下是无代码生成)。在资源文件工具栏中的访问修饰符下拉菜单中将其更改为public

[https://i.imgur.com/q3BK8T5.png]

之后,您应该能够查看资源类型的属性:

enter image description here

此外,考虑不在字段名称中使用特殊符号,因为它们是自动生成的C#属性名称的基础。字段名称会转换为C#友好的名称,这就是为什么资源文件字段名称和自动生成的属性名称之间可能存在不一致的原因。最好避免任何连字符 - 或点 . 下划线 _ 是可以的。您始终可以查看相关资源文件下的resource_file_name.Designer.cs类中自动生成的属性的外观。

enter image description here

非常感谢Bala Murugan在Code Digest上写了一篇关于这个主题的好文章。


3

实际上,我为追随者找到了一个简单的解决方案。大多数情况下,显示名称用于输入字段的标签中。因此,如果您喜欢,请执行以下操作:

<label asp-for="Email">@Localizer["Email"]</label>

当然,你可以通过 @Html.DisplayNameFor 来传递属性名称,但大多数情况下,这个已经很有效了。

一切正常,谢谢。花了很多时间后,看到了你的答案,它非常有效! - vivek ramasamy
我正在寻找类似的解决方案,甚至可以声明Display。因为大多数情况下,属性名称就是显示名称,我们应该能够声明<code> [Display] [EmailAddress] public string Email { get; set; } </code> 这样就可以自动使用属性名称“Email”进行翻译。 - Nathan

1
我刚刚创建了一个项目,演示了本地化,包括类属性和枚举的Display属性的本地化。 该项目可以在此处找到https://github.com/feradz/ASPNetCoreLocalization/wiki
在ASP.NET Core 1.0之前,必须使用一种方法本地化Display属性。请查看项目中的DataAnnotations.resx文件。
Display的Name属性不能包含空格和特殊字符。
[Display(Name = "NoSpacesAndSpecialChanractersHere", ResourceType = typeof(Resources.DataAnnotations))]
public string FirstName { get; set; }

ResourceType 应该是完全限定的资源类名称(即包括命名空间)。


1
在我的 asp.net core 7 Razor 项目中,我在 program.cs 中添加了以下代码以实现自动本地化 Display 属性:
builder.Services.AddMvc()
derFormat.Suffix)
.AddViewLocalization()
.AddDataAnnotationsLocalization(options =>
{
    options.DataAnnotationLocalizerProvider = (type, factory) =>
    {
        var assemblyName = new AssemblyName(typeof(SharedResource).GetTypeInfo().Assembly.FullName);
        return factory.Create("SharedResource", assemblyName.Name);
    };
});


[Display(Name = "RememberMe_QuestionMark")]
public bool RememberMe { get; set; }

这个在.NET 7.0中对我有用。必须像这样使用反射才能让它工作。 在我的情况下,由于我们对代码进行了一些重构,并将模型移动到了不同的项目(例如MyProject.Core),导致了MyProject.Presentation项目中的Resources.resx文件无法“连接”。 之前的代码: options.DataAnnotationLocalizerProvider = (_, factory) => factory.Create(typeof(SharedResouce)); - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接