Monikielinen tuki oletussanomia, jotka näkyvät syötteen tarkistuksen aikana
ympäristö
- ASP.NET ydin
-
- 5,0 MVC
Alun perin
Näiden vihjeiden oletustietojen vahvistussanomien monikielinen tuki ei ehkä ole valmis. Hoitakaa kadonneet.
Kielen vaihtaminen istunnon tilan tai välimuistitilan mukaan saattaa myös näkyä edellisen kielen tekstissä.
Voit muuttaa oletussyötteen vahvistussanomaa usealla eri tavalla, joista jokainen voidaan yhdistää. Se ei ole yksi niistä, joten jos haluat muuttaa sitä luotettavasti, sinun on vastattava kaikkia kuvioita.
premissi
Nämä vinkit on kirjoitettu seuraavien vinkkien ymmärtämiseksi:
- ASP.NET Core MVC:n sisäänrakennetut ominaisuudet monikieliseen vaihtamiseen
- Monikielinen tuki DataAnnotaatioille, joita käytetään parametrien nimiin, syötteen vahvistussanomisiin jne.
Jos luot uutta projektia, sinun on myös lisättävä seuraavat tiedostot ja koodi yllä olevien vihjeiden perusteella.
- Luo SharedResource.resx (+en, es) -tiedosto. (Koska vain tämän vihjeen viesti käännetään, sisältö voi olla tyhjä.)
- SharedResource.cs-tiedoston luominen
- Lisää lokalisointikoodi startup.configureServices-palveluun
- Lisää lokalisointikoodi startup.configure-tunnukseen
- Lisätty UserViewModel (tällä kertaa emme nimenomaisesti näppäile oletusviestejä useilla kielillä)
- Lisätty käyttäjän luomia näyttötoimintoja ja -näkymiä (Create.cshtml)
Aloituskoodi
Edellä mainittujen olettamusten perusteella kunkin koodin on oltava seuraava:
Käynnistys.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,
}
}
Jaetturesurssi.cs
namespace LocalizationDefaultValidation
{
// クラス名は作成した .resx のファイル名と同じにする必要がある
public class SharedResource { }
}
Mallin sidontasanomat
Jos määrität mallin int
ominaisuustyypiksi tai sidot sen DateTime
näkymään ja yrität rekisteröidä sen kirjoittamattomana, näyttöön tulee sanoma, jonka mukaan arvo ei kelpaa.
Nämä viestit tulevat näkyviin, kun tyhjää merkkijonoa int
ei voi sitoa esimerkiksi malliin.
Koska ajoitusta ei voi sitoa, se tapahtuu vain ennen muuta arvontarkistusta ja palvelinpuolen käsittelyä.
Nämä sanomat DefaultModelBindingMessageProvider
määritellään viesteiksi .
Startup.cs
Lisää -kohdassa alusta lähtien määritettyihin menetelmän argumenteihin services.AddControllersWithViews
ja lisää sitten Action
.
Voit olla monikielinen määrittämällä options
ModelBindingMessageProvider
argumentissa välitetty.
Voit määrittää 11 viestityyppiä, joten viesti on ensin määritettävä seuraavasti: SharedResource.resx
Avaimen nimi on valinnainen. Kommenttisarakkeen englanninkielinen oletusviesti on (kommentteja ei tarvitse sisällyttää).
Sinun ei tarvitse kääntää kutakin kieltä, joten sinun tulee tehdä oma käännös (mallikoodi sisältää myös käännetyn SharedResource.resx).
Nimen | arvon | kommentti |
---|---|---|
ModelBinding_AttemptedValueIsInvalid | {0} on virheellinen arvo {1}. | arvo {0} ei kelpaa {1}. |
ModelBinding_MissingBindRequiredValue | {0} arvoa ei ole määritetty. | {0}-parametrin tai ominaisuuden arvoa ei annettu. |
ModelBinding_MissingKeyOrValue | Pakollinen. | Arvo on pakollinen. |
ModelBinding_MissingRequestBodyRequiredValue | Pyynnössä on oltava ruumis. | Tarvitaan muu kuin tyhjä pyyntörunko. |
ModelBinding_NonPropertyAttemptedValueIsInvalid | {0} ei kelpaa. | Arvo {0} ei kelpaa. |
ModelBinding_NonPropertyUnknownValueIsInvalid | Arvo ei kelpaa. | Annettu arvo ei kelpaa. |
ModelBinding_NonPropertyValueMustBeANumber | Numero on määritettävä. | Kentän on oltava numero. |
ModelBinding_UnknownValueIsInvalid | {0} arvo ei kelpaa. | Annettu arvo ei kelpaa {0}. |
ModelBinding_ValueIsInvalid | {0} ei kelpaa. | Arvo {0} ei kelpaa. |
ModelBinding_ValueMustBeANumber | {0} on oltava numero. | kentän {0} on oltava numero. |
ModelBinding_ValueMustNotBeNull | Pakollinen syöttö. | Arvo {0} ei kelpaa. |
Korjaa käynnistys.cs seuraavasti:
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
});
// 省略 (初期コード)
}
}
}
Tärkeintä on services.AddControllersWithViews
lisätä -tapa tapa, joka vastaanottaa option
Action
.
options.ModelBindingMessageProvider
Määritän lokalisoitua tekstiä kullekin -set-menetelmälle.
Käännetty teksti IStringLocalizer
haetaan -kohdasta.
Suoraa koodia ei voi IStringLocalizer
vastaanottaa, mikä on hieman pyöreä koodi.
SharedResource.resx
Jos luot koodia kohteesta, saat siitä lokalisoituja arvoja suoraan.
IStringLocalizer
-kohdassa määritetty avain SharedResource.resx
määrittää -avaimeen lisäämisen.
Määritä se vastaamaan kunkin Set-menetelmän sisältöä.
Koska jokaisella viestillä on muotoilumerkkijonoargumentti, kuten , {0}{1}
käytän Yksinkertaista -toimintoa, jotta voit korvata string.Format
Func
vastaanotetut arvot.
Oletustarkistussanomien lokalisointi
Oletusvirheilmoitus, kun mallin ominaisuuksien määritteet Required
on määritetty tai niin, määräytyy kehyksen mukaan ja on StringLength
periaatteessa englanninkielinen.
Ne voidaan IValidationAttributeAdapterProvider
lokalisoida määrittämällä liittymästä johdettu luokka.
Ensinnäkin SharedResource.resx
rekisteröi monikielinen teksti.
Avaimen nimi on mielivaltainen, mutta ohjelman yksinkertaistamiseksi rekisteröi se muodossa "Validator_< vahvistusmääritteen nimi>".
Nimen | arvon | kommentti |
---|---|---|
Validator_CompareAttribute | {0} ja {1} eivät täsmää. | "{0}" ja "{1}" eivät vastaa toisiaan. |
Validator_CreditCardAttribute | {0} ei ole kelvollinen kortin numero. | {0} kenttä ei ole kelvollinen luottokortin numero. |
Validator_DataTypeAttribute_Date | Anna kelvollinen päivämäärä. | Anna kelvollinen päivämäärä. |
Validator_EmailAddressAttribute | {0} ei ole kelvollinen sähköpostiosoite. | {0} kenttä ei ole kelvollinen sähköpostiosoite. |
Validator_FileExtensionsAttribute | {0} hyväksyy vain tiedostot, joilla on seuraavat laajennukset: : {1} | {0}-kenttä hyväksyy vain tiedostot, joilla on seuraavat laajennukset: {1} |
Validator_MaxLengthAttribute | {0} on oltava merkkijono tai matriisityyppi, jonka enimmäispituus on {1}. | Kentän {0} on oltava merkkijono- tai matriisityyppi, jonka enimmäispituus on {1}. |
Validator_MinLengthAttribute | {0} on oltava merkkijono tai matriisityyppi, jonka vähimmäispituus on {1}. | kentän {0} on oltava merkkijono tai matriisityyppi, jonka vähimmäispituus on {1}. |
Validator_PhoneAttribute | {0} ei ole kelvollinen puhelinnumero. | {0} kenttä ei ole kelvollinen puhelinnumero. |
Validator_RangeAttribute | {0} on oltava {1} {2} välillä. | kentän {0} on oltava {1} ja {2} välissä. |
Validator_RegularExpressionAttribute | {0} on vastattava säännöllistä ilmaisua "{1}". | kentän {0} on vastattava säännöllistä lauseketta "{1}". |
Validator_RequiredAttribute | {0} tarvitaan. | {0} kenttä on pakollinen. |
Validator_StringLengthAttribute | {0} on oltava {1} numeroiden sisällä. | kentän {0} on oltava merkkijono, jonka enimmäispituus on {1}. |
Validator_UrlAttribute | {0} ei ole kelvollinen URL-osoite. | {0} kenttä ei ole kelvollinen http-, https- tai ftp-URL-osoite. |
Validator_StringLengthAttributeWithMin | {0} on oltava vähintään {2} {1} numeroa. | kentän {0} on oltava merkkijono, jonka enimmäispituus on {1} ja vähimmäispituus {2}. |
Luo seuraavaksi seuraava AdapterProvider-luokka:
Luokan nimi on mielivaltainen, mutta tällä kertaa CustomValidationAttributeAdapterProvider
kirjoitan luokan nimeltä ja kirjoitan koodin seuraavasti:
Kooditiedoston sijainti on mielivaltainen, mutta näyte sijoitetaan sovittimeksi kutsuttuun kansioon.
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);
}
}
}
Jos määrität mallin ominaisuuksiin Required
tai , menetelmää tarvitaan jokaiselle StringLength
IValidationAttributeAdapterProvider.GetAttributeAdapter
oikeellisuustarkistuksessa.
ErrorMessageResourceName
Jos ominaisuudessa on arvo, mallipuolen koodilla on jo sanoma tai lokalisointiavain, joten se palaa sellaisenaan.
Jos se on tyhjä, tee etuliitteen ja kelpoisuusmääritteen luokkanimet lokalisointiavaimeksi, hae lokalisoitu teksti avaimesta ja määritä sen ErrorMessage
arvoksi .
Näin useimmat oletusviestit voidaan lokalisoida.
Rekisteröi seuraavaksi tämä luokka käynnistys- .cs. Periaatteessa voit lisätä sen seuraavasti.
// 省略
using Microsoft.AspNetCore.Mvc.DataAnnotations;
namespace LocalizationDefaultValidation
{
public class Startup
{
// 省略
// このメソッドはランタイムによって呼び出されます。 このメソッドを使用して、コンテナーにサービスを追加します。
public void ConfigureServices(IServiceCollection services)
{
// 省略
// 作成した CustomValidationAttributeAdapterProvider をシングルトンとして登録します
services.AddSingleton<IValidationAttributeAdapterProvider, CustomValidationAttributeAdapterProvider>();
}
// 省略
}
}
Suorita se varmistaaksesi, että se toimii oikein.
Aiemmin luodun viestin muuttaminen parametrien mukaan
Esimerkiksi StringLength
määritesanoma on lokalisoitu, kuten "{0} on oltava {1} numeroiden sisällä".
MinimumLength
Jos ominaisuus on määritetty, haluat ehkä muuttaa {0} "Määritä {2} numerot tai enemmän {1} useissa numeroissa".
Laajenna CustomValidationAttributeAdapterProvider
tällöin luokkaa seuraavasti:
// 省略
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);
}
}
// 省略
}
}
}
Koska menetelmää kutsutaan jokaiselle GetAttributeAdapter
oikeellisuustarkistuksen oikeellisuustarkistukseen, attribute
StringLengthAttribute
tarkista MinimumLength
ominaisuus,
Jos tämä on määritetty, saat viestin, jossa otetaan huomioon myös numeroiden vähimmäismäärä ja ErrorMessage
korvataan .
Jos suoritat sen, tarkistat ja viesti muuttuu, se on OK.
Muut yleiset viestit
Joitakin viestejä ei ole lokalisoitu tähän mennessä. Esimerkiksi viestit, jotka määritetään vain Javascriptissä.
Kohde on jquery.validate.js
tiedostossa mainittu viesti.
Koska tätä tiedostoa ei pitäisi muokata suoraan, voit korvata nämä viestit lokalisoidulla tekstillä, sinun input
on lisättävä tunnisteeseen kaltainen määrite ja määritettävä data-val-XXXX
siellä lokalisoitu teksti.
XXXX-osa sisältää jquery.validate.js
avaimen yllä olevassa kuvassa. (esim. data-val-number
jne.)
data-val-XXXX
Jos haluat määrittää lokalisoidun tekstin
Lokalisoitaan viesti, kun esimerkiksi Ikäsyöttö-kenttään sisällytetään muita kuin numeerisia merkkejä.
UserViewModel.Age
-määritteellä on Range
määrite, ja tulosteen HTML data-val-range
liittää syötemääritteen.
<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>
data-val-number
Numeerista tarkistussanomaa ei kuitenkaan ole lokalisoitu, koska määritettä ei ole.
Lisäät mallipuolelle toisen määritteen, joka tulostaa myös lokalisoidun viestin data-val-number
lisätyn määritteen.
Ensimmäinen vaihe on luoda määriteluokka, joka tarkistaa, onko kyseessä IntAttribute
luku: Se rajoittuu tähän, mutta voit int
vapaasti muuttaa sitä tilanteesta riippuen.
Kooditiedosto voi olla missä tahansa, mutta tällä kertaa se on Sovitin-kansiossa.
using System.ComponentModel.DataAnnotations;
namespace LocalizationDefaultValidation
{
public class IntAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
// 渡された値が int であれば有効な値とする
return value is int;
}
}
}
Jos asetettu arvo on int
tyyppi, se on määrite, joka on vain normaali tuomio, mutta käytännössä se on 100% normaali, jos se on asetettu tyypiksi int, joten tämän luokan käsittely ei ole järkevää.
Tämän ajan tarkoituksena on näyttää lokalisoidut virhesanomat asiakkaassa.
Luo seuraavaksi seuraava IntAttributeAdapter
sovitinluokka: Tämä on myös Sovitin-kansiossa.
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;
}
}
Tässä on AddValidation
menetelmässä kuvattu MergeAttribute
menetelmä.
Määritteiden yhdistäminen syöttötunnisteen määritteinä data-val-number
asiakkaaseen palaamista vastaan.
Määritteessä määritettävä arvo määrittää lokalisoidun virhesanoman.
Palauta tämä sovitin aiemmin luomaasi CustomValidationAttributeAdapterProvider
luokkaan.
// 省略
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);
}
// 省略 (前に追加したコード)
}
}
}
Jos vahvistettava arvo IntAttribute
on , palauta aiemmin luomasi IntAttributeAdapter
arvo.
Ominaisuus, jolla on Int-määrite, lisätään nyt, kun se näkyy data-val-number
asiakaspuolella.
Lisää UserViewModel.Age
IntAttribute
lopuksi -lisäykseen .
Kun olet korjannut koodin, kokeile sitä nähdäksesi, haluatko tarkistaa sen.
<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>
On muitakin ei-lokalisoituja viestejä, mutta voit lokalisoida ne edellä kuvatuilla menetelmillä. Lisää koodi tarvittaessa.