Večjezična podpora za privzeta sporočila, prikazana med preverjanjem vnosa
okolje
- ASP.NET Core
-
- 5.0 MVC
Sprva
Večjezična podpora privzetih sporočil za preverjanje veljavnosti vnosa s tem Nasveti morda ni dokončana. Prosim, opravite z manjkajočimi.
Tudi spreminjanje jezika, odvisno od stanja seje ali stanja predpomnilnika, se lahko še vedno prikaže v besedilu iz prejšnjega jezika.
Privzeto sporočilo o preverjanju veljavnosti vnosa lahko spremenite na več načinov, od katerih je vsako mogoče združiti. To ni eden od njih, tako da, če želite, da ga spremeniti zanesljivo, morate ujemati z vsemi vzorci.
Predpostavki
Ti nasveti so napisani kot razumevanje naslednjih nasvetov:
- ASP.NET Vgrajene funkcije jedra MVC za večjezično preklapljanje
- Večjezična podpora za DataAnnotations, ki se uporablja za imena parametrov, sporočila za preverjanje veljavnosti vnosa itd.
Če ustvarjate nov projekt, morate na podlagi zgornjih nasvetov dodati naslednje datoteke in kodo.
- Ustvarite datoteko SharedResource.resx (+sl, es). (Ker je prevedeno le sporočilo teh nasvetov, je vsebina lahko prazna.)
- Ustvarjanje datoteke v skupni rabi.cs datoteke
- Dodajanje kode lokalizacije zagonu.ConfigureServices
- Dodajte kodo za lokalizacijo v zagon.Konfiguriraj
- Dodan UserViewModel (tokrat ne tipkamo izrecno privzetih sporočil v več jezikih)
- Dodana dejanja in pogledi zaslona, ki jih je ustvaril uporabnik (Create.cshtml)
Začetna koda
Na podlagi zgornjih predpostavk je vsaka oznaka naslednja:
Zagon.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>
Ustvari.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,
}
}
Skupni presledki.cs
namespace LocalizationDefaultValidation
{
// クラス名は作成した .resx のファイル名と同じにする必要がある
public class SharedResource { }
}
Zavezujoča sporočila modela
Če nastavite vrsto lastnosti modela ali jo privezate na pogled in jo poskusite registrirati nepotipkano, se prikaže sporočilo, kot je »Vrednost '' ni int
DateTime
veljavno.«
Ta sporočila se prikažejo, ko praznega niza ni mogoče zavezati na primer int
v modelu.
Ker gre za časovni okvir, ki ga ni mogoče zavezati, se pojavi le pred drugim preverjanjem vrednosti in obdelavo na strani strežnika.
Ta sporočila so DefaultModelBindingMessageProvider
opredeljena kot .
Startup.cs
Dodajte argumentom metode, ki so bile opredeljene od začetka v services.AddControllersWithViews
in nato dodajte Action
.
Večjezični ste lahko tako, da nastavite podajano v options
ModelBindingMessageProvider
argumentu.
Na voljo je 11 vrst sporočil, ki jih lahko nastavite, zato morate najprej določiti sporočilo na naslednji način: SharedResource.resx
Ime ključa je neobvezno. Privzeto angleško sporočilo v stolpcu s komentarji je (komentarjev ni treba vključiti).
Ni vam treba prevajati vsakega jezika, zato morate narediti svoj prevod (vzorčna koda vključuje tudi prevedeni SharedResource.resx).
vrednosti | imena | |
---|---|---|
ModelBinding_AttemptedValueIsInvalid | "{0}" je neveljavna vrednost v {1}. | Vrednost "{0}" ni veljavna za {1}. |
ModelBinding_MissingBindRequiredValue | Vrednost za {0} ni določena. | Vrednost parametra ali lastnosti "{0}" ni bila zagotovljena. |
ModelBinding_MissingKeyOrValue | Zahteva. | Potrebna je vrednost. |
ModelBinding_MissingRequestBodyRequiredValue | Zahteva mora imeti truplo. | Potreben je neprazen organ zahteve. |
ModelBinding_NonPropertyAttemptedValueIsInvalid | "{0}" ni veljavna. | Vrednost "{0}" ni veljavna. |
ModelBinding_NonPropertyUnknownValueIsInvalid | Vrednost ni veljavna. | Priložena vrednost ni veljavna. |
ModelBinding_NonPropertyValueMustBeANumber | Določiti je treba številko. | Polje mora biti številka. |
ModelBinding_UnknownValueIsInvalid | Vrednost {0} ni veljavna. | Priložena vrednost ni veljavna za {0}. |
ModelBinding_ValueIsInvalid | "{0}" ni veljavna. | Vrednost "{0}" ni veljavna. |
ModelBinding_ValueMustBeANumber | {0} mora biti številka. | Polje {0} mora biti številka. |
ModelBinding_ValueMustNotBeNull | Zahtevan vnos. | Vrednost "{0}" ni veljavna. |
Popravite zagon.cs na naslednji način:
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
});
// 省略 (初期コード)
}
}
}
Ključna točka je dodati services.AddControllersWithViews
metodi, ki prejme option
Action
,
Nastavljam lokalizirano besedilo za vsako metodo options.ModelBindingMessageProvider
Nastavitev v programu .
Prevedeno besedilo je IStringLocalizer
pridobljeno iz .
Ni načina, da bi prejeli neposredno IStringLocalizer
kodo, ki je nekoliko okrogla koda.
Če ustvarjate kodo, boste iz tega neposredno dobili SharedResource.resx
lokalizirane vrednosti.
IStringLocalizer
Ključ, ki ga določite SharedResource.resx
v, določa ključ, ki ste ga dodali .
Nastavite ga tako, da se ujema z vsebino vsakega načina nabora.
Tudi zato, ker ima vsako sporočilo argument niza formata, na primer , uporabljam Preprosto s tako, da lahko zamenjate {0}{1}
prejete string.Format
Func
vrednosti.
Lokalizacija privzetih sporočil za preverjanje veljavnosti
Privzeto sporočilo o napaki, ko so atributi lastnosti modela nastavljeni na ali tako, je določeno s okvirom in je v bistvu v Required
StringLength
angleščini.
Te lahko lokalizirate tako, da določite razred, ki izhaja IValidationAttributeAdapterProvider
iz vmesnika.
Najprej registrirajte besedilo, ki je SharedResource.resx
večjezično.
Ime ključa je samovoljno, vendar za poenostavitev programa, ga registrirajte v obliki "Validator_< ime atributa za preverjanje>".
vrednosti | imena | |
---|---|---|
Validator_CompareAttribute | {0} in {1} se ne ujemata. | "{0}" in "{1}" se ne ujemata. |
Validator_CreditCardAttribute | {0} ni veljavna številka kartice. | Polje {0} ni veljavna številka kreditne kartice. |
Validator_DataTypeAttribute_Date | Vnesite veljaven datum. | Vnesite veljaven datum. |
Validator_EmailAddressAttribute | {0} ni veljaven e-poštni naslov. | Polje {0} ni veljaven e-poštni naslov. |
Validator_FileExtensionsAttribute | {0} sprejema samo datoteke z naslednjimi razširitvami: : {1} | Polje {0} sprejema samo datoteke z naslednjimi razširitvami: {1} |
Validator_MaxLengthAttribute | {0} mora biti vrsta niza ali polja z največjo dolžino "{1}". | Polje {0} mora biti vrsta niza ali polja z največjo dolžino "{1}". |
Validator_MinLengthAttribute | {0} mora biti vrsta niza ali polja z minimalno dolžino "{1}". | Polje {0} mora biti vrsta niza ali polja z minimalno dolžino "{1}". |
Validator_PhoneAttribute | {0} ni veljavna telefonska številka. | Polje {0} ni veljavna telefonska številka. |
Validator_RangeAttribute | {0} mora biti od {1} do {2}. | Polje {0} mora biti med {1} in {2}. |
Validator_RegularExpressionAttribute | {0} se mora ujemati z običajnim izrazom "{1}". | Polje {0} se mora ujemati z regularnim izrazom "{1}". |
Validator_RequiredAttribute | {0} je potrebno. | Polje {0} je potrebno. |
Validator_StringLengthAttribute | {0} mora biti znotraj {1} številk. | Polje {0} mora biti niz z največjo dolžino {1}. |
Validator_UrlAttribute | {0} ni veljaven URL. | Polje {0} ni veljaven popolnoma kvalificirani URL http, https ali FTP. |
Validator_StringLengthAttributeWithMin | {0} mora biti vsaj {2} {1} števk. | Polje {0} mora biti niz z največjo dolžino {1} in minimalno dolžino {2}. |
Nato ustvarite ta razred adapterProvider:
Ime razreda je poljubno, tokrat pa bom napisal razred, ki se imenuje in napisal kodo na CustomValidationAttributeAdapterProvider
naslednji način:
Lokacija kodne datoteke je poljubna, vendar je vzorec v mapo, imenovano 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);
}
}
}
Če nastavite lastnosti modela na ali , je metoda poklicana za Required
vsako StringLength
IValidationAttributeAdapterProvider.GetAttributeAdapter
preverjanje veljavnosti.
ErrorMessageResourceName
Če lastnost vsebuje vrednost, ima koda na strani modela že sporočilo ali ključ za lokalizacijo, zato se vrne, kot je.
Če je prazno, se ujemajo z imeni razredov predpone in atributa za preverjanje veljavnosti, da bo ključ za lokalizacijo, nato pa iz ključa pridobite lokalizirano besedilo in ga nastavite na ErrorMessage
.
To omogoča lokaliziranje večine privzetih sporočil.
Nato registrirajte ta razred v zagonskem .cs. V bistvu ga lahko dodate na naslednji način.
// 省略
using Microsoft.AspNetCore.Mvc.DataAnnotations;
namespace LocalizationDefaultValidation
{
public class Startup
{
// 省略
// このメソッドはランタイムによって呼び出されます。 このメソッドを使用して、コンテナーにサービスを追加します。
public void ConfigureServices(IServiceCollection services)
{
// 省略
// 作成した CustomValidationAttributeAdapterProvider をシングルトンとして登録します
services.AddSingleton<IValidationAttributeAdapterProvider, CustomValidationAttributeAdapterProvider>();
}
// 省略
}
}
Zaženi ga, da se prepričaš, da deluje pravilno.
Spreminjanje obstoječega sporočila po parametrih
Sporočilo atributa je na primer lokalizirano, na primer »{0} mora biti znotraj StringLength
{1} številk«.
Če je lastnost nastavljena, boste morda želeli spremeniti {0} kot »Navedite {2} številke ali več {1} znotraj več MinimumLength
števk«.
V tem CustomValidationAttributeAdapterProvider
primeru razred razširite na naslednji način:
// 省略
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);
}
}
// 省略
}
}
}
Ker je metoda poklicana za vsako preverjanje veljavnosti, če je bila uporabljena spremenljivka atribut, preverite GetAttributeAdapter
attribute
StringLengthAttribute
MinimumLength
lastnost,
Če je nastavljeno, se prikaže sporočilo, ki upošteva tudi minimalno število številk in ErrorMessage
zamenja .
Če ga zaženete, preverite in sporočilo se spremeni, je v redu.
Druga generična sporočila
Nekatera sporočila niso lokalizirana po tem, ko to storite do zdaj. Na primer sporočila, ki so določena samo v Javascriptu.
Cilj je sporočilo, jquery.validate.js
ki je našteto v datoteki.
Ker te datoteke ne smete urejati neposredno, če želite ta sporočila nadomestiti z lokaliziranim besedilom, morate dodati atribut, kot je oznaki, in tam nastaviti input
data-val-XXXX
lokalizirano besedilo.
XXXX del vsebuje ključ na zgornji jquery.validate.js
sliki. (npr. data-val-number
itd.)
data-val-XXXX
Če želite lokalizirano besedilo nastaviti na atribute v
Lokalizirajmo sporočilo, ko so neštevilični znaki kot primer vključeni v vnosno polje »Starost«.
ima UserViewModel.Age
Range
atribut, izhodni HTML pa data-val-range
pripiše vhodni atribut.
<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>
Vendar sporočilo številčnega preverjanja ni lokalizirano, ker data-val-number
atributa ni.
Dodali boste še en atribut na strani modela, da natisnete tudi lokaliziran atribut dodanega data-val-number
sporočila.
Prvi korak je ustvariti razred atributov, ki preveri, ali gre za IntAttribute
številko: To je omejeno na tukaj, vendar lahko to spremenite glede int
na situacijo.
Kodna datoteka je lahko kjerkoli, tokrat pa je v mapi Adapter.
using System.ComponentModel.DataAnnotations;
namespace LocalizationDefaultValidation
{
public class IntAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
// 渡された値が int であれば有効な値とする
return value is int;
}
}
}
Če je nastavljena vrednost vrsta, je atribut, ki je le običajna razsodba, v praksi pa je 100% normalna, če je nastavljena na lastnost tipa int, zato obdelava samega tega razreda nima nobenega int
smisla.
Namen tega časa je prikazati lokalizirana sporočila o napakah v odjemalcu.
Nato ustvarite ta razred IntAttributeAdapter
kartice: To je tudi v mapi Adapter.
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;
}
}
Tukaj je točka AddValidation
metoda, opisana v MergeAttribute
metodi.
Spajanje atributov kot atributov vhodne oznake za vrnitev data-val-number
v odjemalca.
Vrednost, ki jo nastavite v atributu, nastavi lokalizirano sporočilo o napaki.
Vrnite ta adapter v razredu, ki ste ga prej CustomValidationAttributeAdapterProvider
ustvarili.
// 省略
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);
}
// 省略 (前に追加したコード)
}
}
}
Če je vrednost za preverjanje veljavnosti , vrnite prej IntAttribute
IntAttributeAdapter
ustvarjeno vrednost.
Lastnost z atributom Int se zdaj doda, ko je prikazana na strani data-val-number
odjemalca.
Na koncu še UserViewModel.Age
IntAttribute
dodaj v .
Ko popravite kodo, jo poskusite preveriti, ali jo želite preveriti.
<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>
Obstajajo druga sporočila, ki niso lokalizirana, vendar jih lahko lokalizirate v zgoraj opisanih metodah. Dodaj kodo, ko jo potrebuješ.