Kelių lingvistinis numatytųjų pranešimų, rodomų tikrinant įvestį, palaikymas
Aplinkos
- ASP.NET branduolys
-
- 5,0 MVC
Iš pradžių
Daugiakalbis numatytųjų įvesties tikrinimo pranešimų palaikymas naudojant šiuos patarimus gali būti nebaigtas. Prašome susidoroti su dingusiais.
Be to, kalbos keitimas atsižvelgiant į seanso būseną arba talpyklos būseną vis tiek gali būti rodomas ankstesnės kalbos tekste.
Yra keletas būdų, kaip pakeisti numatytąjį įvesties tikrinimo pranešimą, kurių kiekvieną galima sujungti. Tai nėra vienas iš jų, todėl, jei norite jį patikimai pakeisti, turite atitikti visus modelius.
Prielaida
Šie patarimai yra parašyta kaip suprasti šiuos patarimus:
- ASP.NET Pagrindinės MVC funkcijos, skirtos daugiakalbiam perjungimui
- Daugiakalbis "DataAnnotations", naudojamo parametrų pavadinimams, įvesties tikrinimo pranešimams ir kt., palaikymas.
Be to, jei kuriate naują projektą, turite pridėti šiuos failus ir kodą pagal anksčiau pateiktus patarimus.
- Sukurkite SharedResource.resx (+en, es) failą. (Kadangi išverstas tik šių patarimų pranešimas, turinys gali būti tuščias.)
- SharedResource.cs failo kūrimas
- Įtraukti lokalizacijos kodą į Startup.ConfigureServices
- Įtraukti lokalizacijos kodą į Startup.Configure
- Pridėta UserViewModel (šį kartą mes nėra aiškiai raktas numatytuosius pranešimus keliomis kalbomis)
- Pridėti vartotojo sukurti ekrano veiksmai ir rodiniai (Create.cshtml)
Pradinis kodas
Remiantis pirmiau pateiktomis prielaidomis, kiekvienas kodas yra toks:
Paleidimas.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 { }
}
Modelio susiejimo pranešimai
Jei nustatysite modelio ypatybės tipą int
arba susiesite jį su DateTime
rodiniu ir bandysite jį užregistruoti neįrašytą, pamatysite pranešimą "Reikšmė '' neleistina."
Šie pranešimai rodomi, kai tuščios eilutės int
negalima susieti, pvz., modelyje.
Kadangi tai yra laikas, kurio negalima susieti, jis įvyksta tik prieš kitų reikšmių tikrinimą ir serverio apdorojimą.
Šie pranešimai DefaultModelBindingMessageProvider
apibrėžiami kaip .
Startup.cs
Įtraukite į metodo argumentus, kurie buvo apibrėžti nuo pradžios services.AddControllersWithViews
, tada pridėkite Action
.
Galite būti daugiakalbiai nustatydami options
ModelBindingMessageProvider
argumente perduotas.
Yra 11 tipų pranešimų, kuriuos galite nustatyti, todėl pirmiausia turite apibrėžti pranešimą taip: SharedResource.resx
Rakto pavadinimas yra pasirinktinis. Numatytasis angliškas pranešimas komentarų stulpelyje yra (komentarų įtraukti nereikia).
Jums nereikės versti kiekvienos kalbos, todėl turėtumėte atlikti savo vertimą (kodo pavyzdyje taip pat yra išverstas SharedResource.resx).
Pavadinimo | reikšmės | komentaras |
---|---|---|
ModelBinding_AttemptedValueIsInvalid | "{0}" yra neleistina {1} reikšmė. | Reikšmė "{0}" netinkama {1}. |
ModelBinding_MissingBindRequiredValue | Nenurodyta {0} reikšmė. | Nepateikta parametro "{0}" arba ypatybės reikšmė. |
ModelBinding_MissingKeyOrValue | Reikalingas. | Būtina reikšmė. |
ModelBinding_MissingRequestBodyRequiredValue | Prašyme turi būti kūnas. | Reikalingas neištuštėjantis užklausos tekstas. |
ModelBinding_NonPropertyAttemptedValueIsInvalid | "{0}" negalioja. | Reikšmė "{0}" neleistina. |
ModelBinding_NonPropertyUnknownValueIsInvalid | Reikšmė neleistina. | Pateikta reikšmė neleistina. |
ModelBinding_NonPropertyValueMustBeANumber | Turi būti nurodytas numeris. | Laukas turi būti skaičius. |
ModelBinding_UnknownValueIsInvalid | {0} reikšmė neleistina. | Pateikta {0} reikšmė neleistina. |
ModelBinding_ValueIsInvalid | "{0}" negalioja. | Reikšmė "{0}" neleistina. |
ModelBinding_ValueMustBeANumber | {0} turi būti skaičius. | Lauko {0} turi būti skaičius. |
ModelBinding_ValueMustNotBeNull | Būtina įvestis. | Reikšmė "{0}" neleistina. |
Pataisykite paleisties.cs taip:
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
});
// 省略 (初期コード)
}
}
}
Svarbiausia yra services.AddControllersWithViews
įtraukti a į metodą, kuris gauna option
Action
,
options.ModelBindingMessageProvider
Kiekvienam nustatymo metodui nustatau lokalizuotą tekstą programoje .
Išverstas tekstas IStringLocalizer
nuskaitomas iš .
Nėra jokio būdo gauti tiesioginį IStringLocalizer
kodą, kuris yra šiek tiek apvalaus kodo.
SharedResource.resx
Jei generuojate kodą, lokalizuotas reikšmes gausite tiesiai iš jo.
IStringLocalizer
Raktas, kurį nurodote SharedResource.resx
dalyje, nurodo raktą, kurį įtraukėte į .
Nustatykite, kad jis atitiktų kiekvieno nustatymo metodo turinį.
Be to, kadangi kiekvienas pranešimas turi formato eilutės argumentą, pvz., , aš {0}{1}
naudoju paprasta, kad galėtumėte pakeisti gautas string.Format
Func
reikšmes.
Lokalizuoti numatytuosius tikrinimo pranešimus
Numatytasis klaidos pranešimas, kai modelio ypatybių atributai Required
yra nustatyti arba taip, nustatomas pagal sistemą ir iš esmės yra StringLength
anglų kalba.
Juos galima IValidationAttributeAdapterProvider
lokalizuoti apibrėžiant klasę, gautą iš sąsajos.
Visų pirma SharedResource.resx
užregistruokite daugiakalbį tekstą.
Rakto pavadinimas yra savavališkas, tačiau, siekiant supaprastinti programą, užregistruokite jį "Validator_< patvirtinimo atributo pavadinimą>" forma.
Pavadinimo | reikšmės | komentaras |
---|---|---|
Validator_CompareAttribute | {0} ir {1} nesutampa. | "{0}" ir "{1}" nesutampa. |
Validator_CreditCardAttribute | {0} nėra galiojantis kortelės numeris. | Laukas {0} nėra tinkamas kredito kortelės numeris. |
Validator_DataTypeAttribute_Date | Įveskite tinkamą datą. | Įveskite tinkamą datą. |
Validator_EmailAddressAttribute | {0} nėra galiojantis el. pašto adresas. | Laukas {0} nėra leistinas el. pašto adresas. |
Validator_FileExtensionsAttribute | {0} priima tik failus su šiais plėtiniais: : {1} | Lauke {0} priimami tik failai su šiais plėtiniais: {1} |
Validator_MaxLengthAttribute | {0} turi būti eilutės arba masyvo tipas, kurio maksimalus ilgis yra "{1}". | Lauko {0} turi būti eilutės arba masyvo tipas, kurio maksimalus ilgis yra "{1}". |
Validator_MinLengthAttribute | {0} turi būti eilutės arba masyvo tipas, kurio mažiausias ilgis yra "{1}". | Lauko {0} turi būti eilutės arba masyvo tipas, kurio mažiausias ilgis yra "{1}". |
Validator_PhoneAttribute | {0} nėra galiojantis telefono numeris. | Laukas {0} nėra tinkamas telefono numeris. |
Validator_RangeAttribute | {0} turi svyruoti nuo {1} iki {2}. | Lauko {0} turi būti nuo {1} iki {2}. |
Validator_RegularExpressionAttribute | {0} turi atitikti įprastą posakį "{1}". | Lauko {0} turi atitikti įprastą išraišką "{1}". |
Validator_RequiredAttribute | {0} reikia. | Laukas {0} yra būtinas. |
Validator_StringLengthAttribute | {0} turi būti {1} skaitmenų ribose. | Lauko {0} turi būti eilutė, kurios maksimalus ilgis turi būti {1}. |
Validator_UrlAttribute | {0} nėra leistinas URL. | Laukas {0} nėra tinkamas visiškai kvalifikuotas http, https arba ftp URL. |
Validator_StringLengthAttributeWithMin | {0} turi būti bent {2} {1} skaitmenų. | Lauko {0} turi būti eilutė, kurios maksimalus ilgis yra {1} ir mažiausias ilgis {2}. |
Tada sukurkite šią AdapterProvider klasę:
Klasės pavadinimas yra savavališkas, bet šį kartą CustomValidationAttributeAdapterProvider
aš parašyti klasės vadinamas ir parašyti kodą taip:
Kodo failo vieta yra savavališka, tačiau pavyzdys dedamas į aplanką, pavadintą Adapteris.
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);
}
}
}
Jei modelio ypatybes nustatysite Required
kaip arba , metodas bus iškviestas kiekvienam StringLength
IValidationAttributeAdapterProvider.GetAttributeAdapter
tikinimui.
ErrorMessageResourceName
Jei ypatybėje yra reikšmė, modelio pusėje yra pranešimas arba lokalizavimo raktas, todėl jis grįžta toks, koks yra.
Jei tuščia, sutapkite su priešdėlio ir tikrinimo atributo klasių pavadinimais, kad jis taptų lokalizavimo raktu, tada nuskaitykite lokalizuotą tekstą iš rakto ir nustatykite jį ErrorMessage
kaip .
Tai leidžia lokalizuoti daugumą numatytųjų pranešimų.
Tada užregistruokite šią klasę paleisties .cs. Iš esmės galite jį pridėti taip.
// 省略
using Microsoft.AspNetCore.Mvc.DataAnnotations;
namespace LocalizationDefaultValidation
{
public class Startup
{
// 省略
// このメソッドはランタイムによって呼び出されます。 このメソッドを使用して、コンテナーにサービスを追加します。
public void ConfigureServices(IServiceCollection services)
{
// 省略
// 作成した CustomValidationAttributeAdapterProvider をシングルトンとして登録します
services.AddSingleton<IValidationAttributeAdapterProvider, CustomValidationAttributeAdapterProvider>();
}
// 省略
}
}
Paleiskite jį, kad įsitikintumėte, jog jis veikia tinkamai.
Esamo pranešimo keitimas pagal parametrus
Pavyzdžiui, StringLength
atributo pranešimas yra lokalizuotas, pvz., "{0} turi būti {1} skaitmenyse".
MinimumLength
Jei ypatybė nustatyta, galbūt norėsite pakeisti {0} kaip "Nurodyti {2} skaitmenis ar daugiau {1} skaitmenų skaičiuje".
Tokiu CustomValidationAttributeAdapterProvider
atveju išplėskite klasę taip:
// 省略
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);
}
}
// 省略
}
}
}
Kadangi metodas iškviečiamas kiekvienam GetAttributeAdapter
patvirtinimui, jei perduotas kintamasis attribute
buvo StringLengthAttribute
MinimumLength
atributas, patikrinkite ypatybę,
Jei nustatyta, gaukite pranešimą, kuriame taip pat atsižvelgiama į minimalų skaitmenų skaičių ir ErrorMessage
pakeičiamas .
Jei jį paleisite, patikrinkite ir pranešimas pasikeis, viskas gerai.
Kiti bendrieji pranešimai
Kai kurie pranešimai nėra lokalizuoti po to, kai tai darote iki šiol. Pavyzdžiui, pranešimai, kurie nustatomi tik Javascript.
Tikslas yra jquery.validate.js
faile pateiktas pranešimas.
Kadangi šio failo negalima redaguoti tiesiogiai, norėdami pakeisti šiuos pranešimus lokalizuotu tekstu, input
turite pridėti atributą, pvz., žymę, ir ten nustatyti data-val-XXXX
lokalizuotą tekstą.
XXXX dalyje yra aukščiau pateikto paveikslo jquery.validate.js
raktas. (pvz., data-val-number
ir t. t.)
data-val-XXXX
Norint nustatyti lokalizuotą tekstą į atributus
Lokalizuokime pranešimą, kai ne skaitiniai simboliai įtraukiami į lauką Amžiaus įvestis kaip pavyzdys.
UserViewModel.Age
turi Range
atributą, o data-val-range
išvesties HTML pridedamas įvesties atributas.
<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>
Tačiau data-val-number
skaitinio tikrinimo pranešimas nėra lokalizuotas, nes nėra atributo.
Modelio pusėje įtrauksite kitą atributą, kad išspausdintumėte lokalizuotą prie pranešimo pridėtą data-val-number
atributą.
Pirmas žingsnis yra sukurti atributų klasę, kuri tikrina, ar tai yra IntAttribute
skaičius: Jis apsiriboja čia, bet jūs galite int
jį pakeisti priklausomai nuo situacijos.
Kodo failas gali būti bet kur, bet šį kartą jis yra aplanke Adapteris.
using System.ComponentModel.DataAnnotations;
namespace LocalizationDefaultValidation
{
public class IntAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
// 渡された値が int であれば有効な値とする
return value is int;
}
}
}
Jei nustatyta reikšmė yra int
tipas, tai yra atributas, kuris yra tik normalus verdiktas, tačiau praktiškai jis yra 100% normalus, jei nustatytas į int tipo savybę, todėl pačios šios klasės apdorojimas neturi jokios prasmės.
Šio laiko tikslas yra rodyti lokalizuotus klaidų pranešimus kliento.
Tada sukurkite šią adapterio IntAttributeAdapter
klasę: Tai taip pat yra aplanke Adapteris.
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;
}
}
Čia yra AddValidation
metodas, aprašytas MergeAttribute
metode.
Suliekite atributus kaip įvesties žymės atributus, kad data-val-number
grįžtumėte į klientą.
Atribute nustatyta reikšmė nustato lokalizuotą klaidos pranešimą.
Grąžinkite šį adapterį klasėje, kurią sukūrėte CustomValidationAttributeAdapterProvider
anksčiau.
// 省略
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);
}
// 省略 (前に追加したコード)
}
}
}
Jei tikrintina reikšmė IntAttribute
yra , grąžinkite anksčiau sukurtą IntAttributeAdapter
reikšmę.
Ypatybė su atributu Int dabar įtraukiama, kai ji rodoma kliento data-val-number
pusėje.
Galiausiai UserViewModel.Age
IntAttribute
pridėkite prie .
Kai nustatote kodą, pabandykite jį patikrinti, ar norite jį patikrinti.
<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>
Yra ir kitų ne lokalizuotų pranešimų, tačiau galite juos lokalizuoti pirmiau aprašytais metodais. Pridėkite kodą, kai jo reikia.