ASP.NET Core DisplayAttribute Localization
Asked Answered
C

6

17

According to the documentation:

The runtime doesn’t look up localized strings for non-validation attributes. In the code above, “Email” (from [Display(Name = "Email")]) will not be localized.

I'm looking for a way to localize text in DisplayAttribute. Any suggestions to do it in a proper way(s)?

Chretien answered 15/6, 2016 at 11:6 Comment(1)
To concerned modern readers like me who happen to arrive here: this is not an issue in later versions of the framework. As Microsoft states, "In ASP.NET Core MVC 1.1.0 and higher, non-validation attributes are localized."Carny
B
19

You can set the ResourceType on the DisplayAttribute which can be used to localize your text.

Add a resource .resx file to your project e.g. MyResources.resx, and add a resource for your field:

enter image description here

Then reference the name of the field and the MyResources type in your DisplayAttribute

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

The localized resource will be pulled through automatically (see the text box)

enter image description here

Bergschrund answered 17/6, 2016 at 16:20 Comment(4)
It seems odd that non-validation attributes are not localized according to this new asp.net core localization mechanism. Do you think it is possible implement it for non-validation attributes too, or is there a reason that mvc guys skipped non-validation attributes?Chretien
I agree, it is a bit odd! I assume there must be a reason why they decided not to but I'm not sure off the top of my head. You could always ask on GitHub and see what they say.Bergschrund
I'm getting The type or namespace 'MyResources' could not be found. What am I missing?Knudsen
Hello, I'm using .NET Core 1.0.0 and this implementation throws the following error: InvalidOperationException: Cannot retrieve property 'Name' because localization failed. Type '<full_typename>' is not public or does not contain a public static string property with the name 'RememberMe'. Does anybody have any experience with this error?Wulf
P
11

Having a Central location for all your localization whether in view or dataannotations is the best approach I can think of, and this how I got to work. In Startup.cs file after you installed nuget packages for localization add the following code

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

This way the DataAnnotationLocalizerProvider will be from the Resources.{culture}.rex -( The Resource file must have an access modifier of No code gen)- assuming that no resources will be needed for the default language, and to be able to access the resource file since no code will be generated and empty class with the same name must be created.

and in _ViewImports.cshtml file inject the following

@inject IHtmlLocalizer<Resources> Localizer

by doing this you now have a global variable Localizer to be used in any of the views for localization purposes.

This is how a Central Location for String Localization

you can find further information on Globalization and localization in ASP.NET Core

Piscatelli answered 11/9, 2017 at 16:11 Comment(0)
C
7

For those who struggle (@lucius, @vladislav) with error:

Cannot retrieve property 'Name' because localization failed. Type 'Xxxx.EmployeeResx' is not public or does not contain a public static string property with the name 'FirstName'.

It is caused by access modifier on .resx files which is by default set to Internal (in my case it was No code generation). Change it to public in Access Modifier dropdown in the resource file toolbar.

[https://static.mcmap.net/file/mcmap/ZG-AbGLDKwfpKmltX1ywKmMva3/q3BK8T5.png]

After that you should be able to see the properties from the resource type:

enter image description here

Also, consider not using special signs in field names as they are a basis for auto-generated C# property names. The field names are converted into C# friendly names and that is why you can end up with inconsistency between name of resource file field and name of auto-generated property. Best to avoid any hyphens - or dots . Underscores _ are fine. You can always look up how the auto-generated properties look like in resource_file_name.Designer.cs class under the related resource file.

enter image description here

Many thanks to Bala Murugan who wrote a good article concerning this topic on Code Digest.

Crystallo answered 24/5, 2018 at 11:25 Comment(0)
E
3

Actually I found an simple solution for the followers. The display name in most of time is used in the label of an input field. So do this if you like:

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

of course, you can pass the property name by @Html.DisplayNameFor, but most of time, this one already works well.

Erode answered 3/12, 2016 at 1:33 Comment(3)
Works as expected, thanks.. after many hours spend, i see your answer and it works like a charm !!Jezebel
I'm looking for similar solution for even declaring Display. Because most of the time, the property name is display name, we should be able to declare <code> [Display] [EmailAddress] public string Email { get; set; } </code> This should automatically use the property name 'Email' to translateSpongin
The problem with this approach is that validation attributes cannot pick up and translate the field name. Add the [Required] attribute to your model property and its default message "{0} is required." fills in the technical name of the field rather than the translated name of the field.Trough
S
1

I have just created a project which demonstrates localization including localization of Display attribute for class properties as well as enums.

The project can be found here https://github.com/feradz/ASPNetCoreLocalization/wiki

The Display attribute has to be localized using the approach prior to ASP.NET Core 1.0. Have a look at the DataAnnotations.resx file in the project.

The Name property of Display cannot contain empty spaces, and special characters.

[Display(Name = "NoSpacesAndSpecialChanractersHere", ResourceType = typeof(Resources.DataAnnotations))]
public string FirstName { get; set; }

ResourceType should be the fully qualified resource class name (i.e. including the name space).

Swartz answered 11/9, 2016 at 15:9 Comment(0)
E
1

In my asp.net core 7 Razor projects, I add this in program.cs to have Display attrib localized automatically:

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; }
Ednaedny answered 23/6, 2023 at 10:31 Comment(1)
This one worked for me in .NET 7.0. Had to use reflection like this to get it to work In my case, as we did some refactoring of code and moved Models to a different project (e.g. MyProject.Core), which resulted in Resources.resx files situated in MyProject.Presentation project would not be "connected". Previous code: options.DataAnnotationLocalizerProvider = (_, factory) => factory.Create(typeof(SharedResouce));Syst

© 2022 - 2024 — McMap. All rights reserved.