Mulilingual data annotation in .NET 4.6.2

I have the following view model:

public class LoginViewModel
    {
        [DisplayName("Email Address")]
        [Required(ErrorMessage = "PleaseEnterYourEmail")]
        public string EmailAddress { get; set; }

    }

I have the following resource file named: DataAnnotation.Localization.de-DE.resx, it is inside the App_LocalResources folder

App_LocalResources

Resource file

With the following properties:

The properties

Now, according to the blog post announcement announcecing.net 4.6.2 , this should work, as I have to get a localized version of my message back to view.

However, it just shows:

View

I checked the current culture and installed: de-DE so that the application is aware of the language it needs to show. The target structure is also 4.6.2.

Am I missing something here?

+4
source share
2

DataAnnotations, , .NET Framework 4.6.2, ASP.NET WebForms.

WebForms...

.NET Framework 4.6.2 System.Web.ModelBinding.DataAnnotationsModelValidator, StringLocalizerProviders.DataAnnotationStringLocalizerProvider.GetLocalizedString .

System.Web.Mvc.DataAnnotationsModelValidator System.Web.Globalization.ResourceFileStringLocalizerProvider. DLL "App_LocalResources.root" Temporary ASP.NET Files -.

, :

private bool UseStringLocalizerProvider {
    get {
        // if developer already uses existing localization feature,
        // then we don't opt in the new localization feature.
        return (!string.IsNullOrEmpty(Attribute.ErrorMessage) &&
            string.IsNullOrEmpty(Attribute.ErrorMessageResourceName) &&
            Attribute.ErrorMessageResourceType == null);
    }
}

, , :

[Required(ErrorMessage = "FirstName is required")]
public string FirstName { get; set; }

ErrorMessage . :

[Required]
public string FirstName { get; set; }

.

MVC 5 , ...

MVC 5 , , , System.Web.Mvc.DataAnnotationsModelValidator. Microsoft.AspNet.Mvc 5.x.x .NET Framework 4.6.2. .

, ASP.NET MVC WebForms , , WebForms (ex: de\App_LocalResources.root.q_wjw-ce.resources.dll "), App_LocalResources ASP.NET MVC.

MVC WebForms WebForms " " MVC.

MVC 6 , -...

MVC 6 3- , Microsoft.AspNetCore.Mvc.DataAnnotations.Internal.DataAnnotationsModelValidator. IStringLocalizer stringLocalizer .

​​ Startup.cs :

// This method gets called by the runtime. Use this method to add services to the container.
public void ConfigureServices(IServiceCollection services)
{
    // Add framework services.
    services.AddMvc()
        .AddDataAnnotationsLocalization();
}

Startup.cs Configure(...), :

// Configure the localization options
app.UseRequestLocalization(new RequestLocalizationOptions
{
    DefaultRequestCulture = new RequestCulture(new CultureInfo("de-AT")),
    SupportedCultures = new List<CultureInfo>
    {
        new CultureInfo("de")
    },
    SupportedUICultures = new List<CultureInfo>
    {
        new CultureInfo("de-AT")
    }
});

ViewModel:

using System.ComponentModel.DataAnnotations;

namespace WebApplication1.Models
{
    public class User
    {
        [Required(ErrorMessage = "First name is required.")]
        public string FirstName { get; set; }
    }
}

Models.User.{culture}.resx WebApplication " ". .

Model.User.resx file.

, MVC 6 , ValidationAttribute , WebForms. ErrorMessage , ErrorMessageResourceName ErrorMessageResourceType .

+2

, .

, .

asp.net:

using System;
using Microsoft.Extensions.Localization;

namespace App.Utilities
{
    public static class StringLocalizerFactoryExtensions
    {
        public static IStringLocalizer CreateConventional<T>(this IStringLocalizerFactory factory)
        {
            return factory.CreateConventional(typeof(T));
        }

        public static IStringLocalizer CreateConventional(this IStringLocalizerFactory factory, Type type)
        {
            if (type.Module.ScopeName != "CommonLanguageRuntimeLibrary")
            {
                string[] parts = type.FullName.Split(new[] { type.Assembly.FullName.Split(',')[0] }, StringSplitOptions.None);

                string name = parts[parts.Length - 1].Trim('.');

                return factory.CreateConventional(name);
            }
            else
            {
                return factory.Create(type);
            }
        }

        public static IStringLocalizer CreateConventional(this IStringLocalizerFactory factory, string resourceName)
        {
            return factory.Create(resourceName, null);
        }

        public static IStringLocalizer CreateDataAnnotation(this IStringLocalizerFactory factory)
        {
            if (type.Module.ScopeName != "CommonLanguageRuntimeLibrary")
            {
                return factory.Create("DataAnnotation.Localization", "App_LocalResources");
            }
            else
            {
                return factory.Create(type);
            }
        }
    }
}

... Startup.cs :

services.AddLocalization(options => options.ResourcesPath = "Resources");

services.AddMvc()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
.AddDataAnnotationsLocalization();

... :

services.AddLocalization(options => options.ResourcesPath = "Resources");

services.AddMvc()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
//The following part includes the change:
.AddDataAnnotationsLocalization(options => options.DataAnnotationLocalizerProvider = (type, factory) => factory.CreateConventional(type));

, , , IStringLocalizerFactory.

, DataAnnotation.Localization.de-DE.resx App_LocalResources.

  • (Models.AccountViewModels.RegisterViewModel.en-US.resx Models/AccountViewModels/RegisterViewModel.sv-SE.resx Resources, services.AddLocalization(options => options.ResourcesPath = "Resources")), . TagHelpers HtmlHelpers .

  • , DisplayAttribute.Name . (v1.1.0-preview1-final +.net v4.6.2)

1: project.json:

{
  "userSecretsId": "...",

  "dependencies": {
    "Microsoft.NETCore.Platforms": "1.1.0-preview1-*",
    "Microsoft.AspNetCore.Authentication.Cookies": "1.1.0-preview1-final",
    "Microsoft.AspNetCore.Diagnostics": "1.1.0-preview1-final",
    "Microsoft.AspNetCore.DataProtection": "1.1.0-preview1-final",
    "Microsoft.AspNetCore.Diagnostics.EntityFrameworkCore": "1.1.0-preview1-final",
    "Microsoft.AspNetCore.Identity.EntityFrameworkCore": "1.1.0-preview1-final",
    "Microsoft.AspNetCore.Mvc": "1.1.0-preview1-final",
    "Microsoft.AspNetCore.Razor.Tools": "1.0.0-preview3-final",
    "Microsoft.ApplicationInsights.AspNetCore": "1.0.2",
    "Microsoft.AspNetCore.Mvc.Localization": "1.1.0-preview1-final",
    "Microsoft.AspNetCore.Mvc.Razor": "1.1.0-preview1-final",
    "Microsoft.AspNetCore.Mvc.TagHelpers": "1.1.0-preview1-final",
    "Microsoft.AspNetCore.Mvc.DataAnnotations": "1.1.0-preview1-final",
    "Microsoft.Extensions.Configuration.CommandLine": "1.1.0-preview1-final",
    "Microsoft.Extensions.Configuration.FileExtensions": "1.1.0-preview1-final",
    "Microsoft.AspNet.WebApi.Client": "5.2.3",
    "Microsoft.AspNetCore.Routing": "1.1.0-preview1-final",
    "Microsoft.AspNetCore.Server.IISIntegration": "1.1.0-preview1-final",
    "Microsoft.AspNetCore.Server.Kestrel": "1.1.0-preview1-final",
    "Microsoft.AspNetCore.StaticFiles": "1.1.0-preview1-final",
    "Microsoft.EntityFrameworkCore": "1.1.0-preview1-final",
    "Microsoft.EntityFrameworkCore.SqlServer.Design": "1.1.0-preview1-final",
    "Microsoft.Extensions.Configuration.EnvironmentVariables": "1.1.0-preview1-final",
    "Microsoft.Extensions.Configuration.Json": "1.1.0-preview1-final",
    "Microsoft.Extensions.Configuration.UserSecrets": "1.1.0-preview1-final",
    "Microsoft.Extensions.Logging": "1.1.0-preview1-final",
    "Microsoft.Extensions.Logging.Console": "1.1.0-preview1-final",
    "Microsoft.Extensions.Logging.Debug": "1.1.0-preview1-final",
    "Microsoft.Extensions.Options.ConfigurationExtensions": "1.1.0-preview1-final",
    "Microsoft.VisualStudio.Web.BrowserLink.Loader": "14.0.0",
    "Microsoft.VisualStudio.Web.CodeGeneration.Tools": "1.0.0-preview3-final",
    "Microsoft.VisualStudio.Web.CodeGenerators.Mvc": "1.0.0-preview3-final",
    "Microsoft.AspNetCore.Hosting": "1.1.0-preview1-final",
    "Microsoft.AspNetCore.Hosting.WindowsServices": "1.1.0-preview1-final",
    "Loggr.Extensions.Logging": "1.0.0",
    "Microsoft.EntityFrameworkCore.SqlServer": "1.1.0-preview1-final",
    "Microsoft.EntityFrameworkCore.Tools": "1.0.0-preview3-final",
    "BundlerMinifier.Core": "2.2.296"
  },
  "tools": {
    "Microsoft.AspNetCore.Razor.Tools": "1.0.0-preview3-final",
    "Microsoft.AspNetCore.Server.IISIntegration.Tools": "1.0.0-preview3-final",
    "Microsoft.EntityFrameworkCore.Tools.DotNet": "1.0.0-preview3-final",
    "Microsoft.Extensions.SecretManager.Tools": "1.0.0-preview3-final",
    "Microsoft.VisualStudio.Web.CodeGeneration.Tools": {
      "version": "1.0.0-preview3-final",
      "imports": [
        "portable-net45+win8"
      ]
    }
  },
  "frameworks": {
    "net462": {}
  },
  "buildOptions": {
    "emitEntryPoint": true,
    "preserveCompilationContext": true
  },
  "runtimeOptions": {
    "configProperties": {
      "System.GC.Server": true
    }
  },
  "publishOptions": {
    "include": [
      "wwwroot",
      "**/*.cshtml",
      "appsettings.json",
      "web.config"
    ]
  },
  "scripts": {
    "prepublish": [ "bower install", "dotnet bundle" ],
    "postpublish": [ "dotnet publish-iis --publish-folder %publish:OutputPath% --framework %publish:FullTargetFramework%" ]
  }
}

2:. - , DataAnnotation.Localization App_LocalResourses, StringLocalizerFactoryExtensions. Startup.cs .

services.AddLocalization(options => options.ResourcesPath = "Resources");

services.AddMvc()
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix)
//The following part includes the change:
.AddDataAnnotationsLocalization(options => options.DataAnnotationLocalizerProvider = (type, factory) => factory.CreateDataAnnotation());
+2

Source: https://habr.com/ru/post/1657387/


All Articles