Flersproget understøttelse af standardmeddelelser, der vises under inputvalidering
miljø
- ASP.NET kerne
-
- 5,0 MVC
Først
Den flersprogede understøttelse af standardinputvalideringsmeddelelserne med disse tip er muligvis ikke fuldført. Vær venlig at håndtere de manglende.
Hvis du ændrer sproget afhængigt af sessionstilstanden eller cachetilstanden, kan der også stadig vises i tekst fra det forrige sprog.
Du kan ændre standardinputvalideringsmeddelelsen på flere måder, som hver især kan kombineres. Det er ikke en af dem, så hvis du vil ændre det pålideligt, skal du svare til alle mønstre.
forudsætning
Dette tip er skrevet som forståelse af følgende tips:
- ASP.NET De indbyggede funktioner i Core MVC til flersproget skift
- Flersproget understøttelse af dataannotationer, der bruges til parameternavne, inputvalideringsmeddelelser osv.
Hvis du opretter et nyt projekt, skal du også have tilføjet følgende filer og kode baseret på tip ovenfor.
- Opret en SharedResource.resx-fil (+en, es). (Da kun meddelelsen i dette tip oversættes, kan indholdet være tomt).
- Oprette en SharedResource.cs-fil
- Føj lokaliseringskode til Startup.ConfigureServices
- Føj lokaliseringskode til Startup.Configure
- Tilføjet UserViewModel (denne gang taster vi ikke eksplicit standardmeddelelserne på flere sprog)
- Tilføjede brugeroprettede skærmhandlinger og -visninger (Create.cshtml)
Startkode
På grundlag af ovenstående antagelser skal hver kode være som følger:
Opstart.cs
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System.Globalization;
namespace LocalizationDefaultValidation
{
public class Startup
{
// 省略
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews();
services.AddMvc()
// ローカライズに必要。Resx ファイルのフォルダパスを指定
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix, opts => { opts.ResourcesPath = "Resources"; })
// DataAnnotations のローカライズに必要
.AddDataAnnotationsLocalization(options =>
{
// DataAnnotation を使ったときのメッセージは SharedResource に集約する
options.DataAnnotationLocalizerProvider = (type, factory) => factory.Create(typeof(SharedResource));
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
// 標準の機能で切り替えたい言語を定義します。
var supportedCultures = new[]
{
new CultureInfo("ja"),
new CultureInfo("en"),
new CultureInfo("es"),
};
// 標準の言語切り替え機能を有効にします。対応しているのは「クエリ文字列」「Cookie」「Accept-Language HTTP ヘッダー」です。
app.UseRequestLocalization(new RequestLocalizationOptions
{
DefaultRequestCulture = new RequestCulture("ja"),
SupportedCultures = supportedCultures,
SupportedUICultures = supportedCultures
});
app.UseHttpsRedirection();
app.UseStaticFiles();
// 省略
}
}
}
HomeController.cs
using LocalizationDefaultValidation.Models;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Rendering;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
namespace LocalizationDefaultValidation.Controllers
{
public class HomeController : Controller
{
// 省略
public IActionResult Create()
{
SetDayOfWeeksViewData();
return View();
}
[HttpPost]
public IActionResult Create(UserViewModel model)
{
SetDayOfWeeksViewData();
// エラーなら差し戻し
if (ModelState.IsValid == false) return View(model);
// 正常に登録できた場合は Index に戻る
return RedirectToAction(nameof(Index));
}
<summary>曜日の一覧を ViewData に設定します。</summary>
private void SetDayOfWeeksViewData()
=> ViewData["DayOfWeeks"] = ((DayOfWeek[])Enum.GetValues(typeof(DayOfWeek))).Select(x => new SelectListItem(x.ToString(), ((int)x).ToString()));
}
}
Index.cshtml
@{
ViewData["Title"] = "Home Page";
}
<div class="text-center">
<h1 class="display-4">Welcome</h1>
<p>Learn about <a href="https://docs.microsoft.com/aspnet/core">building Web apps with ASP.NET Core</a>.</p>
</div>
<p>ユーザー作成画面に遷移します。リンクごとに選択した言語で表示できます。</p>
<ul>
<li><a asp-action="Create">Create</a></li>
<li><a asp-action="Create" asp-route-culture="ja">Create (ja)</a></li>
<li><a asp-action="Create" asp-route-culture="en">Create (en)</a></li>
<li><a asp-action="Create" asp-route-culture="es">Create (es)</a></li>
</ul>
Create.cshtml
@model LocalizationDefaultValidation.Models.UserViewModel
@using System.Globalization;
@{
ViewData["Title"] = "Create";
}
<h1>Create</h1>
<h4>UserViewModel</h4>
<hr />
<div class="row">
<div class="col-md-4">
<form asp-action="Create" enctype="multipart/form-data" >
<div asp-validation-summary="ModelOnly" class="text-danger"></div>
<div class="form-group">
<label asp-for="ID" class="control-label"></label>
<input asp-for="ID" class="form-control" />
<span asp-validation-for="ID" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Name" class="control-label"></label>
<input asp-for="Name" class="form-control" />
<span asp-validation-for="Name" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Password" class="control-label"></label>
<input asp-for="Password" class="form-control" />
<span asp-validation-for="Password" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="ConfirmPassword" class="control-label"></label>
<input asp-for="ConfirmPassword" class="form-control" />
<span asp-validation-for="ConfirmPassword" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Email" class="control-label"></label>
<input asp-for="Email" class="form-control" />
<span asp-validation-for="Email" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Age" class="control-label"></label>
<input asp-for="Age" class="form-control" />
<span asp-validation-for="Age" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Gender"></label>
<div>
<label><input type="radio" asp-for="Gender" value="@(GenderType.None)" />@(GenderType.None)</label>
<label><input type="radio" asp-for="Gender" value="@(GenderType.Man)" />@(GenderType.Man)</label>
<label><input type="radio" asp-for="Gender" value="@(GenderType.Woman)" />@(GenderType.Woman)</label>
</div>
<span asp-validation-for="Gender" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Birthday" class="control-label"></label>
<input asp-for="Birthday" class="form-control" />
<span asp-validation-for="Birthday" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Phone" class="control-label"></label>
<input asp-for="Phone" class="form-control" />
<span asp-validation-for="Phone" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="PostalCode" class="control-label"></label>
<input asp-for="PostalCode" class="form-control" />
<span asp-validation-for="PostalCode" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="CreditCard" class="control-label"></label>
<input asp-for="CreditCard" class="form-control" />
<span asp-validation-for="CreditCard" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Money" class="control-label"></label>
<input asp-for="Money" class="form-control" />
<span asp-validation-for="Money" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="StartDateTime" class="control-label"></label>
<input asp-for="StartDateTime" class="form-control" />
<span asp-validation-for="StartDateTime" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="WakeUpTime" class="control-label"></label>
<input asp-for="WakeUpTime" class="form-control" />
<span asp-validation-for="WakeUpTime" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Homepage" class="control-label"></label>
<input asp-for="Homepage" class="form-control" />
<span asp-validation-for="Homepage" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="MyImage" class="control-label"></label>
<input asp-for="MyImage" class="form-control" />
<span asp-validation-for="MyImage" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="MyColor" class="control-label"></label>
<input asp-for="MyColor" class="form-control" type="color" />
<span asp-validation-for="MyColor" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="WorkingDays" class="control-label"></label>
<select asp-for="WorkingDays" class="form-control" asp-items="@((IEnumerable<SelectListItem>)ViewData["DayOfWeeks"])" multiple></select>
<span asp-validation-for="WorkingDays" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="VacationDay" class="control-label"></label>
<select asp-for="VacationDay" class="form-control" asp-items="@((IEnumerable<SelectListItem>)ViewData["DayOfWeeks"])" multiple></select>
<span asp-validation-for="VacationDay" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Comment" class="control-label"></label>
<textarea asp-for="Comment" class="form-control"></textarea>
<span asp-validation-for="Comment" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="FileName" class="control-label"></label>
<input asp-for="FileName" class="form-control" />
<span asp-validation-for="FileName" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="UploadFile" class="control-label"></label>
<input asp-for="UploadFile" type="file" multiple />
<span asp-validation-for="UploadFile" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Month" class="control-label"></label>
<input asp-for="Month" class="form-control" type="month" />
<span asp-validation-for="Month" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Search" class="control-label"></label>
<input asp-for="Search" class="form-control" type="search" />
<span asp-validation-for="Search" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Range" class="control-label"></label>
<input asp-for="Range" class="form-control" type="range" min="10" max="100" />
<span asp-validation-for="Range" class="text-danger"></span>
</div>
<div class="form-group">
<label asp-for="Week" class="control-label"></label>
<input asp-for="Week" class="form-control" type="week" />
<span asp-validation-for="Week" class="text-danger"></span>
</div>
<div class="form-group form-check">
<label class="form-check-label">
<input class="form-check-input" asp-for="IsAccepted" /> @Html.DisplayNameFor(model => model.IsAccepted)
</label>
</div>
<div class="form-group">
<input type="submit" value="Create" class="btn btn-primary" asp-route-culture="@CultureInfo.CurrentCulture.Name" />
</div>
</form>
</div>
</div>
<div>
<a asp-action="Index">Back to List</a>
</div>
@section Scripts {
@{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
UserViewModel.cs
using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
namespace LocalizationDefaultValidation.Models
{
public class UserViewModel
{
[Required]
[Display(Name = "ID (半角英数字)")]
[StringLength(20)]
[RegularExpression(@"^[0-9a-zA-Z]*$")]
public string ID { get; set; }
[StringLength(50)]
public string Name { get; set; }
[StringLength(50, MinimumLength = 8)]
[DataType(DataType.Password)]
[RegularExpression(@"^[0-9a-zA-Z]*$")]
public string Password { get; set; }
[StringLength(50, MinimumLength = 8)]
[DataType(DataType.Password)]
[Compare(nameof(Password))]
public string ConfirmPassword { get; set; }
[EmailAddress]
[DataType(DataType.EmailAddress)] // スキャフォールディングするときはコメントアウトする
public string Email { get; set; }
//[Int]
[Range(0, 150)]
public int Age { get; set; }
[Required]
[EnumDataType(typeof(GenderType))]
public GenderType Gender { get; set; }
[DataType(DataType.Date)]
public DateTime Birthday { get; set; }
[Phone()]
[DataType(DataType.PhoneNumber)] // スキャフォールディングするときはコメントアウトする
public string Phone { get; set; }
[DataType(DataType.PostalCode)]
public string PostalCode { get; set; }
[CreditCard()]
[DataType(DataType.CreditCard)] // スキャフォールディングするときはコメントアウトする
public string CreditCard { get; set; }
[DataType(DataType.Currency)]
public decimal Money { get; set; }
[DataType(DataType.DateTime)]
public DateTime StartDateTime { get; set; }
[DataType(DataType.Time)]
public TimeSpan WakeUpTime { get; set; }
[Url]
[DataType(DataType.Url)] // スキャフォールディングするときはコメントアウトする
public string Homepage { get; set; }
[Url]
[DataType(DataType.ImageUrl)] // スキャフォールディングするときはコメントアウトする
public string MyImage { get; set; }
public string MyColor { get; set; }
[MaxLength(5)]
public DayOfWeek[] WorkingDays { get; set; }
[MinLength(3)]
public DayOfWeek[] VacationDay { get; set; }
[StringLength(200)]
[DataType(DataType.MultilineText)]
public string Comment { get; set; }
[Display(Name = "ファイル名 (.png)")]
[FileExtensions(Extensions = "png")]
public string FileName { get; set; }
[DataType(DataType.Upload)]
public List<IFormFile> UploadFile { get; set; }
public DateTime Month { get; set; }
public string Search { get; set; }
[Range(10, 100)]
public int Range { get; set; }
public string Week { get; set; }
[Required]
public bool IsAccepted { get; set; }
}
public enum GenderType
{
None,
Man,
Woman,
Other,
}
}
SharedResource.cs
namespace LocalizationDefaultValidation
{
// クラス名は作成した .resx のファイル名と同じにする必要がある
public class SharedResource { }
}
Meddelelser om modelbinding
Hvis du angiver modelegenskabstypen int
til eller binder den til visningen og forsøger at registrere den ikke DateTime
indtastet, vises en meddelelse som "Værdien '' er ugyldig.".
Disse meddelelser vises, når en tom streng int
ikke kan bindes til f.eks.
Da det er en tidsindstilling, der ikke kan bindes, sker den kun før anden værdivalidering og serverbehandling.
Disse meddelelser DefaultModelBindingMessageProvider
defineres som .
Startup.cs
Føj til argumenterne for den metode, der er defineret siden begyndelsen services.AddControllersWithViews
i , og tilføj derefter Action
.
Du kan være flersproget ved at angive det overførte options
ModelBindingMessageProvider
argument.
Der er 11 typer meddelelser, du kan angive, så du skal først definere meddelelsen på følgende måde: SharedResource.resx
Navnet på nøglen er valgfrit. Den engelske standardmeddelelse i kommentarkolonnen er (kommentarer behøver ikke at blive medtaget).
Du behøver ikke at oversætte hvert sprog, så du skal lave din egen oversættelse (eksempelkoden indeholder også den oversatte SharedResource.resx).
Kommentar | til navnværdi | |
---|---|---|
ModelBinding_AttemptedValueIsInvalid | '{0}' er en ugyldig værdi i {1}. | Værdien '{0}' er ikke gyldig for {1}. |
ModelBinding_MissingBindRequiredValue | Værdien for {0} er ikke angivet. | Der blev ikke angivet en værdi for parameteren '{0}'. |
ModelBinding_MissingKeyOrValue | Kræves. | Der kræves en værdi. |
ModelBinding_MissingRequestBodyRequiredValue | Anmodningen skal have et lig. | Der kræves et ikke-tomt anmodningsorgan. |
ModelBinding_NonPropertyAttemptedValueIsInvalid | '{0}' er ikke gyldig. | Værdien '{0}' er ugyldig. |
ModelBinding_NonPropertyUnknownValueIsInvalid | Værdien er ugyldig. | Den angivne værdi er ugyldig. |
ModelBinding_NonPropertyValueMustBeANumber | Der skal angives et nummer. | Feltet skal være et tal. |
ModelBinding_UnknownValueIsInvalid | Værdien af {0} er ugyldig. | Den angivne værdi er ugyldig for {0}. |
ModelBinding_ValueIsInvalid | '{0}' er ikke gyldig. | Værdien '{0}' er ugyldig. |
ModelBinding_ValueMustBeANumber | {0} skal være et tal. | Feltet {0} skal være et tal. |
ModelBinding_ValueMustNotBeNull | Påkrævet input. | Værdien '{0}' er ugyldig. |
Løs start.cs på følgende måde:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc.Razor;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Localization;
using System;
using System.Globalization;
using System.Reflection;
namespace LocalizationDefaultValidation
{
public class Startup
{
// 省略 (初期コード)
<summary>
検証メッセージローカライズで使用。
</summary>
private IServiceProvider ServiceProvider { get; set; }
private IStringLocalizer _localizer = null;
<summary>
検証メッセージローカライズで使用。
</summary>
private IStringLocalizer Localizer
=> _localizer ?? (_localizer = ServiceProvider.GetService<IStringLocalizerFactory>()
.Create(nameof(SharedResource), new AssemblyName(typeof(SharedResource).Assembly.FullName).Name));
// このメソッドはランタイムによって呼び出されます。 このメソッドを使用して、コンテナーにサービスを追加します。
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews(options =>
{
// 検証メッセージのローカライズで使用
// モデルバインディング失敗時のエラーメッセージをカスタマイズ
// サーバ側でモデルに値を格納する際に発生する可能性がある
// メッセージの {0} や {1} を置換するための関数を定義
static string f1(string f, string a1) => string.Format(f, a1);
static string f2(string f, string a1, string a2) => string.Format(f, a1, a2);
// 各メソッドを読んでメッセージを置き換えます
var mp = options.ModelBindingMessageProvider;
mp.SetAttemptedValueIsInvalidAccessor((x, y) => f2(Localizer["ModelBinding_AttemptedValueIsInvalid"], x, y));
mp.SetMissingBindRequiredValueAccessor((x) => f1(Localizer["ModelBinding_MissingBindRequiredValue"], x));
mp.SetMissingKeyOrValueAccessor(() => Localizer["ModelBinding_MissingKeyOrValue"]);
mp.SetMissingRequestBodyRequiredValueAccessor(() => Localizer["ModelBinding_MissingRequestBodyRequiredValue"]);
mp.SetNonPropertyAttemptedValueIsInvalidAccessor((x) => f1(Localizer["ModelBinding_NonPropertyAttemptedValueIsInvalid"], x));
mp.SetNonPropertyUnknownValueIsInvalidAccessor(() => Localizer["ModelBinding_NonPropertyUnknownValueIsInvalid"]);
mp.SetNonPropertyValueMustBeANumberAccessor(() => Localizer["ModelBinding_NonPropertyValueMustBeANumber"]);
mp.SetUnknownValueIsInvalidAccessor((x) => f1(Localizer["ModelBinding_UnknownValueIsInvalid"], x));
mp.SetValueIsInvalidAccessor((x) => f1(Localizer["ModelBinding_ValueIsInvalid"], x));
mp.SetValueMustBeANumberAccessor((x) => f1(Localizer["ModelBinding_ValueMustBeANumber"], x));
mp.SetValueMustNotBeNullAccessor((x) => f1(Localizer["ModelBinding_ValueMustNotBeNull"], x));
});
services.AddMvc()
// ローカライズに必要。Resx ファイルのフォルダパスを指定
.AddViewLocalization(LanguageViewLocationExpanderFormat.Suffix, opts => { opts.ResourcesPath = "Resources"; })
// DataAnnotations のローカライズに必要
.AddDataAnnotationsLocalization(options =>
{
// DataAnnotation を使ったときのメッセージは SharedResource に集約する
options.DataAnnotationLocalizerProvider = (type, factory) => factory.Create(typeof(SharedResource));
});
}
// このメソッドはランタイムによって呼び出されます。 このメソッドを使用して、HTTP要求パイプラインを構成します。
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
// ローカライズで使用するため IServiceProvider をプロパティに保持しておきます。
ServiceProvider = app.ApplicationServices;
// 標準の機能で切り替えたい言語を定義します。
var supportedCultures = new[]
{
new CultureInfo("ja"),
new CultureInfo("en"),
new CultureInfo("es"),
};
// 標準の言語切り替え機能を有効にします。対応しているのは「クエリ文字列」「Cookie」「Accept-Language HTTP ヘッダー」です。
app.UseRequestLocalization(new RequestLocalizationOptions
{
DefaultRequestCulture = new RequestCulture("ja"),
SupportedCultures = supportedCultures,
SupportedUICultures = supportedCultures
});
// 省略 (初期コード)
}
}
}
Det centrale punkt er services.AddControllersWithViews
at føje en til den metode, der modtager option
Action
,
options.ModelBindingMessageProvider
Jeg angiver lokaliseret tekst for hver Set-metode i .
Den oversatte tekst IStringLocalizer
hentes fra .
Der er ingen måde at modtage direkte IStringLocalizer
kode, som er lidt af en rund kode.
SharedResource.resx
Hvis du genererer kode fra, får du lokaliserede værdier direkte fra den.
IStringLocalizer
Den nøgle, du angiver i SharedResource.resx
, angiver den nøgle, du har føjet til .
Indstil den, så den svarer til indholdet af hver set-metode.
Også, fordi hver meddelelse har et format streng argument, såsom, jeg {0}{1}
bruger Simple med, så du kan erstatte de modtagne string.Format
Func
værdier.
Lokalisere standardvalideringsmeddelelser
Standardfejlmeddelelsen, når attributterne Required
for en models egenskaber er angivet til eller deromkring, bestemmes af strukturen og er grundlæggende på StringLength
engelsk.
Disse kan IValidationAttributeAdapterProvider
lokaliseres ved at definere en klasse, der er afledt af grænsefladen.
Først og SharedResource.resx
fremmest skal du registrere den tekst, der er flersproget.
Navnet på nøglen er vilkårligt, men for at forenkle programmet skal du registrere det i form af "Validator_< valideringsattributnavn>".
Kommentar | til navnværdi | |
---|---|---|
Validator_CompareAttribute | {0} og {1} stemmer ikke overens. | '{0}' og '{1}' stemmer ikke overens. |
Validator_CreditCardAttribute | {0} er ikke et gyldigt kortnummer. | Feltet {0} er ikke et gyldigt kreditkortnummer. |
Validator_DataTypeAttribute_Date | Angiv en gyldig dato. | Angiv en gyldig dato. |
Validator_EmailAddressAttribute | {0} er ikke en gyldig e-mail-adresse. | Feltet {0} er ikke en gyldig e-mail-adresse. |
Validator_FileExtensionsAttribute | {0} accepterer kun filer med følgende udvidelser: : {1} | Feltet {0} accepterer kun filer med følgende filtypenavne: {1} |
Validator_MaxLengthAttribute | {0} skal være en streng- eller matrixtype med en maksimal længde på '{1}'. | Feltet {0} skal være en streng- eller matrixtype med en maksimal længde på '{1}'. |
Validator_MinLengthAttribute | {0} skal være en streng- eller matrixtype med en længde på mindst '{1}'. | Feltet {0} skal være en streng- eller matrixtype med en længde på '{1}'. |
Validator_PhoneAttribute | {0} er ikke et gyldigt telefonnummer. | Feltet {0} er ikke et gyldigt telefonnummer. |
Validator_RangeAttribute | {0} skal variere fra {1} til {2}. | Feltet {0} skal være mellem {1} og {2}. |
Validator_RegularExpressionAttribute | {0} skal matche det regulære udtryk '{1}'. | Feltet {0} skal svare til det regulære udtryk '{1}'. |
Validator_RequiredAttribute | {0} er påkrævet. | Feltet {0} er påkrævet. |
Validator_StringLengthAttribute | {0} skal være inden for {1} cifre. | Feltet {0} skal være en streng med en maksimal længde på {1}. |
Validator_UrlAttribute | {0} er ikke en gyldig URL-adresse. | Feltet {0} er ikke en gyldig fuldt kvalificeret http-, https- eller ftp-URL-adresse. |
Validator_StringLengthAttributeWithMin | {0} skal være mindst {2} {1} cifre. | Feltet {0} skal være en streng med en maksimal længde på {1} og en {2} længde. |
Opret derefter følgende AdapterProvider-klasse:
Klassenavnet er vilkårligt, men denne gang CustomValidationAttributeAdapterProvider
vil jeg skrive en klasse kaldet og skrive koden som følger:
Placeringen af kodefilen er vilkårlig, men eksemplet placeres i en mappe med navnet Adapter.
using Microsoft.AspNetCore.Mvc.DataAnnotations;
using Microsoft.Extensions.Localization;
using System;
using System.ComponentModel.DataAnnotations;
namespace LocalizationDefaultValidation
{
public class CustomValidationAttributeAdapterProvider : IValidationAttributeAdapterProvider
{
<summary>コード簡略化のためのリソースキー命名規則プリフィックス</summary>
private const string RESOURCE_KEY_PREFIX = "Validator_";
private readonly IValidationAttributeAdapterProvider _fallback = new ValidationAttributeAdapterProvider();
<summary>
指定された ValidationAttribute の IAttributeAdapter を返します。
</summary>
<param name="attribute">IAttributeAdapter を作成するための ValidationAttribute。</param>
<param name="stringLocalizer">メッセージの作成に使用される IStringLocalizer。</param>
<returns>指定された属性の IAttributeAdapter。</returns>
IAttributeAdapter IValidationAttributeAdapterProvider.GetAttributeAdapter(ValidationAttribute attribute, IStringLocalizer stringLocalizer)
{
// すでにエラーメッセージが設定されている場合はそれを使用するのでここでは何も設定しない
if (attribute.ErrorMessageResourceName != null) return _fallback.GetAttributeAdapter(attribute, stringLocalizer);
// attribute には「Required」や「StringLength」などが設定されています
Type attrType = attribute.GetType();
// プリフィックスと属性のクラス名からローカライズ用のキーを生成します
var key = RESOURCE_KEY_PREFIX + attrType.Name;
// IStringLocalizer から指定したキーでローカライズされたテキストを取得します
// ない場合は getString にそのまま key の値が入ります
var getString = stringLocalizer[key];
// 正しくローカライズされたテキストが取得できた場合は ErrorMessage に値をセットします。
if (key != getString && attribute.ErrorMessage != getString)
{
attribute.ErrorMessage = getString;
}
// 設定した attribute を渡します
return _fallback.GetAttributeAdapter(attribute, stringLocalizer);
}
}
}
Hvis du angiver egenskaberne for modellen til Required
eller , kaldes metoden for hver StringLength
IValidationAttributeAdapterProvider.GetAttributeAdapter
validering.
ErrorMessageResourceName
Hvis egenskaben indeholder en værdi, har koden på modelsiden allerede en meddelelses- eller lokaliseringsnøgle, så den returneres, som den er.
Hvis det er tomt, skal du matche klassenavnene på præfikset og valideringsattributten for at gøre den til lokaliseringsnøglen og derefter hente den lokaliserede tekst fra nøglen og angive den ErrorMessage
til .
Dette gør det muligt at lokalisere de fleste standardmeddelelser.
Registrer derefter denne klasse i start .cs. Dybest set kan du tilføje det som følger.
// 省略
using Microsoft.AspNetCore.Mvc.DataAnnotations;
namespace LocalizationDefaultValidation
{
public class Startup
{
// 省略
// このメソッドはランタイムによって呼び出されます。 このメソッドを使用して、コンテナーにサービスを追加します。
public void ConfigureServices(IServiceCollection services)
{
// 省略
// 作成した CustomValidationAttributeAdapterProvider をシングルトンとして登録します
services.AddSingleton<IValidationAttributeAdapterProvider, CustomValidationAttributeAdapterProvider>();
}
// 省略
}
}
Kør det for at sikre, at det fungerer korrekt.
Ændre en eksisterende meddelelse efter parametre
StringLength
Attributmeddelelsen {1} {0} er f.eks.
MinimumLength
Hvis egenskaben er angivet, kan du ændre {0} som "Angiv {2} cifre eller flere {1} inden for et antal cifre".
I CustomValidationAttributeAdapterProvider
så fald skal klassen udvides på følgende måde:
// 省略
namespace LocalizationDefaultValidation
{
public class CustomValidationAttributeAdapterProvider : IValidationAttributeAdapterProvider
{
// 省略
IAttributeAdapter IValidationAttributeAdapterProvider.GetAttributeAdapter(ValidationAttribute attribute, IStringLocalizer stringLocalizer)
{
if (attribute is StringLengthAttribute slAttribute)
{
// attribute が StringLengthAttribute で MinimumLength が設定されている場合はメッセージを変える
if (slAttribute.MinimumLength >= 1)
{
attribute.ErrorMessage = stringLocalizer["Validator_StringLengthAttributeWithMin"];
return _fallback.GetAttributeAdapter(slAttribute, stringLocalizer);
}
}
// 省略
}
}
}
Da metoden kaldes for hver GetAttributeAdapter
validering, skal du kontrollere egenskaben, hvis den overførte variabel attribute
var StringLengthAttribute
en MinimumLength
attribut,
Hvis den er angivet, skal du hente en meddelelse, der også tager højde for det mindste antal cifre og ErrorMessage
erstatter .
Hvis du kører det, skal du kontrollere, og meddelelsen ændres, er det OK.
Andre generiske meddelelser
Nogle meddelelser er ikke lokaliseret, når du har gjort det indtil videre. Meddelelser, der f.eks.
Destinationen er jquery.validate.js
den meddelelse, der er angivet i filen.
Da denne fil ikke bør redigeres direkte, skal du for at erstatte disse meddelelser med lokaliseret tekst input
føje en attribut som til koden og angive data-val-XXXX
lokaliseret tekst der.
XXXX-delen indeholder nøglen i figuren jquery.validate.js
ovenfor. (f.eks. data-val-number
osv.)
data-val-XXXX
Hvis du vil angive lokaliseret tekst til attributter i
Lad os lokalisere meddelelsen, når ikke-numeriske tegn medtages i feltet Aldersinput som eksempel.
UserViewModel.Age
har Range
en attribut, og output-HTML-html'en data-val-range
tilføjer inputattributten.
<div class="form-group">
<label class="control-label" for="Age">Age</label>
<input class="form-control" type="number" data-val="true" data-val-range="Ageは0から150の範囲で指定してください。" data-val-range-max="150" data-val-range-min="0" data-val-required="Ageは必須です。" id="Age" name="Age" value="" />
<span class="text-danger field-validation-valid" data-valmsg-for="Age" data-valmsg-replace="true"></span>
</div>
Den data-val-number
numeriske kontrolmeddelelse er dog ikke lokaliseret, fordi der ikke er nogen attribut.
Du skal også tilføje en anden attribut på modelsiden for at udskrive den lokaliserede attribut, der er tilføjet af data-val-number
meddelelsen.
Det første trin er at oprette en attributklasse, der kontrollerer, om det er IntAttribute
et tal: Det er begrænset til her, men du er int
fri til at ændre det afhængigt af situationen.
Kodefilen kan være hvor som helst, men denne gang er den i mappen Adapter.
using System.ComponentModel.DataAnnotations;
namespace LocalizationDefaultValidation
{
public class IntAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
// 渡された値が int であれば有効な値とする
return value is int;
}
}
}
Hvis den angivne værdi er int
en type, er det en attribut, der kun er en normal dom, men i praksis er den 100% normal, hvis den er angivet til en egenskab af type int, så behandlingen af denne klasse selv giver ingen mening.
Formålet med denne tid er at vise lokaliserede fejlmeddelelser i klienten.
Opret derefter følgende IntAttributeAdapter
kortklasse: Dette findes også i mappen Kort.
using Microsoft.AspNetCore.Mvc.DataAnnotations;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using Microsoft.Extensions.Localization;
namespace LocalizationDefaultValidation
{
<summary>Int 属性のアダプター。</summary>
public class IntAttributeAdapter : AttributeAdapterBase<IntAttribute>
{
<summary>受け取った IStringLocalizer を保持しておく</summary>
IStringLocalizer _stringLocalizer;
public IntAttributeAdapter(IntAttribute attribute, IStringLocalizer stringLocalizer)
: base(attribute, stringLocalizer)
{
_stringLocalizer = stringLocalizer;
}
<summary>バリデーションの追加処理として呼ばれる。</summary>
public override void AddValidation(ClientModelValidationContext context)
{
// 新たに data-val-number 属性をマージして追加します。値はローカライズしたテキストをセットします。
MergeAttribute(context.Attributes, "data-val-number", _stringLocalizer["ModelBinding_NonPropertyValueMustBeANumber"]);
}
<summary>サーバーのエラーメッセージはそのまま返します。</summary>
public override string GetErrorMessage(ModelValidationContextBase validationContext) => Attribute.ErrorMessage;
}
}
Pointen her er AddValidation
den metode, der er beskrevet i MergeAttribute
metoden.
Flette attributter som attributter for inputkoden for at vende tilbage data-val-number
til klienten.
Den værdi, der skal angives i attributten, angiver en lokaliseret fejlmeddelelse.
Returner dette kort i den klasse, du oprettede CustomValidationAttributeAdapterProvider
tidligere.
// 省略
namespace LocalizationDefaultValidation
{
public class CustomValidationAttributeAdapterProvider : IValidationAttributeAdapterProvider
{
// 省略
IAttributeAdapter IValidationAttributeAdapterProvider.GetAttributeAdapter(ValidationAttribute attribute, IStringLocalizer stringLocalizer)
{
// IntAttribute の場合は IntAttributeAdapter 経由で返す
if (attribute is IntAttribute intAttribute)
{
return new IntAttributeAdapter(intAttribute, stringLocalizer);
}
// 省略 (前に追加したコード)
}
}
}
Hvis den IntAttribute
værdi, der skal valideres, er , skal du returnere den, du oprettede IntAttributeAdapter
tidligere.
Egenskaben med attributten Int tilføjes nu, når den vises på data-val-number
klientsiden.
Endelig skal UserViewModel.Age
IntAttribute
du tilføje til .
Når du har rettet din kode, kan du prøve den for at se, om du vil tjekke den ud.
<div class="form-group">
<label class="control-label" for="Age">Age</label>
<input class="form-control" type="number" data-val="true" data-val-number="数字を指定してください。" data-val-range="Ageは0から150の範囲で指定してください。" data-val-range-max="150" data-val-range-min="0" data-val-required="Ageは必須です。" id="Age" name="Age" value="" />
<span class="text-danger field-validation-valid" data-valmsg-for="Age" data-valmsg-replace="true"></span>
</div>
Der er andre ikke-lokaliserede meddelelser, men du kan lokalisere dem i de metoder, der er beskrevet ovenfor. Tilføj kode, når du har brug for det.