.NETCore
ASP.NET_Core

ASP.NET Core のValidationエラメッセージを一括で日本語化する

More than 1 year has passed since last update.

最初にですが、.NET初心者なので間違っていましたら申し訳ないです。
また正しい日本語化の方法がありましたら是非教えて頂きたいです_| ̄|○

https://docs.microsoft.com/en-us/aspnet/core/fundamentals/localization

のURLを参照しながら、ローカライゼーションをしてみたところ、アノテーションで設定したRequireAttributeなどのエラーメッセージが日本語化できなかったのです。
色々検索してみても、アノテーションのパラメータのErrorMessageやErrorMessageResourceTypeを使うように書いてあるのですが・・・・

共通のメッセージをわざわざ個別に設定するのはおかしくないですか!?

方針

怠惰なプログラマとしてはありえないと思いまして、もう少し調べてみましたら

https://blogs.msdn.microsoft.com/mvpawardprogram/2017/05/09/aspnetcore-mvc-error-message/
という記事を見かけまして、この記事の通りにしてみたいと思います。

こちらの記事では、ModelMetadataDetailsProvidersを設定することにより各Attributeに対してErrorMessageResourceType、ErrorMessageResourceNameを強制的に一括で設定できるようです。

未確認ではありますが、多分多言語化にはならないので注意してください。

手順

基本的にこちらの記事通りですが、一部省略しています。

リソースファイルの作成

下記のようにResourcesフォルダを作成し、その中にSharedResource.resxという名前でリソースファイルを作成します。

folder20171024.png

少しだけしか登録していませんが下記のように文字列リソースを定義してきます。アノテーションのクラスの名前をキーとしてエラーメッセージを定義してきます。

resource20171024.png

CustomValidationMetadataProviderクラスの作成

このクラスでアノテーションで指定した属性のエラーメッセージを変更します。
リソースファイルには属性名称(例: RequireAttribute)で名前付けされたテキストが取得、設定します。
リソースファイルに対象の文言がなければデフォルト(英語)表示されるようにします。

public class CustomValidationMetadataProvider : IValidationMetadataProvider
{
    private ResourceManager resourceManager; private Type resourceType;
    public CustomValidationMetadataProvider(Type type)
    {
        resourceType = type;
        resourceManager = new ResourceManager(
            type);
    }
    public void CreateValidationMetadata(
        ValidationMetadataProviderContext context)
    {
        foreach (var attribute in context.ValidationMetadata.ValidatorMetadata)
        {
            ValidationAttribute tAttr = attribute as ValidationAttribute;
            if (tAttr != null && tAttr.ErrorMessage == null
                    && tAttr.ErrorMessageResourceName == null)
            {
                var name = tAttr.GetType().Name;
                if (resourceManager.GetString(name) != null)
                {
                    tAttr.ErrorMessageResourceType = resourceType;
                    tAttr.ErrorMessageResourceName = name;
                    tAttr.ErrorMessage = null;
                }
            }
        }
    }
}

Startup.csの変更

services.AddMvcでオプションを設定します。この設定によりCustomValidationMetadataProviderの設定、また属性のアノテーション以外で表示されるエラーメッセージを設定します。

なお、Resources.SharedResourceは一番最初に指定したリソースのクラスとなります。

Startup.cs
public void ConfigureServices(IServiceCollection services) =>
    services.AddMvc(o =>
    {
        o.ModelBindingMessageProvider.SetValueMustNotBeNullAccessor( (value) => {
            return string.Format(Resources.SharedResource.ValueMustNotBeNull, value);
        });
        o.ModelMetadataDetailsProviders.Add(
            new CustomValidationMetadataProvider(
                typeof(Resources.SharedResource)));
    });

あとは実行するだけ

適当にViewModel作成し、フォームを作成してValidationを行うと、下記のように日本語化されたメッセージが表示されます(´▽`)

form20171024.png

その他、思ったこと

Windows PCもあるので、リソースファイル作成できましたがVisual Studio Codeを使った開発だとリソースファイル作成できないのですね。
せっかくLinuxやMacでも.NET Coreが動作するようになっているのでリソースファイル含めてWindows以外のプラットフォームで開発できるようになって欲しいです。