Daudzvalodu atbalsts noklusējuma ziņojumiem, kas tiek parādīti ievades validācijas laikā
vide
- ASP.NET kodols
-
- 5.0 MVC
Sākumā
Noklusējuma ievades validācijas ziņojumu daudzvalodu atbalsts ar šiem padomiem var nebūt pabeigts. Lūdzu, nodarbojieties ar trūkstošajiem.
Arī valodas maiņa atkarībā no sesijas stāvokļa vai kešatmiņas stāvokļa joprojām var tikt parādīta iepriekšējās valodas tekstā.
Ir vairāki veidi, kā mainīt noklusējuma ievades validācijas ziņojumu, no kuriem katru var kombinēt. Tas nav viens no tiem, tāpēc, ja vēlaties to droši mainīt, jums jāatbilst visiem modeļiem.
Premisu
Šie padomi ir rakstīti kā izpratne par šādiem padomiem:
- ASP.NET Core MVC iebūvētās funkcijas daudzvalodu pārslēgšanai
- Daudzvalodu atbalsts DataAnnotations, ko izmanto parametru nosaukumiem, ievades validācijas ziņojumiem utt.
Turklāt, ja veidojat jaunu projektu, ir jāpievieno šādi faili un kods, pamatojoties uz iepriekš minētajiem padomiem.
- Izveidojiet SharedResource.resx (+en, es) failu. (Tā kā tiek tulkots tikai šī padomu ziņojums, saturs var būt tukšs.)
- SharedResource.cs faila izveide
- Lokalizācijas koda pievienošana startēšanai.ConfigureServices
- Pievienot lokalizācijas kodu startēšanai.Konfigurēt
- Pievienots UserViewModel (šoreiz mēs skaidri nenoraisām noklusējuma ziņojumus vairākās valodās)
- Pievienotās lietotāja izveidotās ekrāna darbības un skati (Create.cshtml)
Sākuma kods
Pamatojoties uz iepriekš minētajiem pieņēmumiem, katrs kods ir šāds:
Startēšana.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();
// 省略
}
}
}
SākumsKontrollers.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 { }
}
Saistošo ziņojumu paraugs
Ja iestatāt modeļa rekvizīta tipu int
uz skatu vai saistāt to ar to DateTime
un mēģināt to reģistrēt bezraksta, tiks parādīts ziņojums, piemēram, "Vērtība '' nav derīga".
Šie ziņojumi tiek parādīti, ja tukšu virkni int
nevar saistīt, piemēram, modelī.
Tā kā tas ir laiks, ko nevar saistīt, tas notiek tikai pirms citas vērtības validācijas un servera puses apstrādes.
Šie ziņojumi tiek DefaultModelBindingMessageProvider
definēti kā .
Startup.cs
Pievienojiet metodes argumentiem, kas definēti kopš sākuma services.AddControllersWithViews
programmā , un pēc tam pievienojiet Action
.
Jūs varat būt daudzvalodīgs, iestatot options
ModelBindingMessageProvider
argumentu nodoto.
Ir 11 ziņojumu tipi, kurus var iestatīt, tāpēc vispirms ziņojums ir jādefinē šādi: SharedResource.resx
Atslēgas nosaukums nav obligāts. Noklusējuma ziņojums angļu valodā komentāru slejā ir (komentāri nav jāiekļauj).
Jums nebūs jātulko katra valoda, tāpēc jums vajadzētu veikt savu tulkojumu (koda paraugā ir iekļauts arī tulkotais SharedResource.resx).
Nosaukuma | vērtības | komentārs |
---|---|---|
ModelBinding_AttemptedValueIsInvalid | "{0}" ir nederīga {1} vērtība. | Vērtība "{0}" nav derīga {1}. |
ModelBinding_MissingBindRequiredValue | Nav norādīta {0} vērtība. | Parametra vai rekvizīta "{0}" vērtība netika norādīta. |
ModelBinding_MissingKeyOrValue | Nepieciešams. | Nepieciešama vērtība. |
ModelBinding_MissingRequestBodyRequiredValue | Pieprasījumam jābūt iestādei. | Ir nepieciešama pieprasījuma struktūra, kas nav tukša. |
ModelBinding_NonPropertyAttemptedValueIsInvalid | "{0}" nav derīgs. | Vērtība "{0}" nav derīga. |
ModelBinding_NonPropertyUnknownValueIsInvalid | Vērtība nav derīga. | Norādītā vērtība nav derīga. |
ModelBinding_NonPropertyValueMustBeANumber | Jānorāda numurs. | Laukam ir jābūt skaitlim. |
ModelBinding_UnknownValueIsInvalid | {0} vērtība nav derīga. | Norādītā vērtība nav derīga {0}. |
ModelBinding_ValueIsInvalid | "{0}" nav derīgs. | Vērtība "{0}" nav derīga. |
ModelBinding_ValueMustBeANumber | {0} jābūt skaitlim. | Lauka {0} jābūt skaitlim. |
ModelBinding_ValueMustNotBeNull | Nepieciešamā ievade. | Vērtība "{0}" nav derīga. |
Novērsiet startēšanu.cs šādi:
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
});
// 省略 (初期コード)
}
}
}
Galvenais ir services.AddControllersWithViews
pievienot metodi, kas saņem option
Action
,
options.ModelBindingMessageProvider
Katrai kopas metodei programmā tiek iestatīts lokalizēts teksts.
Tulkotais teksts tiek IStringLocalizer
izgūts no .
Nav iespējams saņemt tiešo IStringLocalizer
kodu, kas ir mazliet apaļš kods.
SharedResource.resx
Ja ģenerējat kodu, jūs iegūsit lokalizētas vērtības tieši no tā.
IStringLocalizer
Programmā norādītā atslēga SharedResource.resx
norāda atslēgu, kuru pievienojāt programmā .
Iestatiet to atbilstoši katras kopas metodes saturam.
Turklāt, tā kā katram ziņojumam ir formāta virknes arguments, piemēram, , es {0}{1}
izmantoju Vienkārši ar, lai varētu aizstāt saņemtās string.Format
Func
vērtības.
Noklusējuma validācijas ziņojumu lokalizācija
Noklusējuma kļūdas ziņojumu, kad Required
modeļa rekvizītu atribūti ir iestatīti uz vai tā, nosaka sistēma, un būtībā tas ir StringLength
angļu valodā.
Tos var IValidationAttributeAdapterProvider
lokalizēt, definējot klasi, kas atvasināta no interfeisa.
SharedResource.resx
Pirmkārt, reģistrējiet daudzvalodu tekstu.
Atslēgas nosaukums ir patvaļīgs, bet, lai vienkāršotu programmu, reģistrējiet to kā "Validator_< validācijas atribūta nosaukumu>".
Nosaukuma | vērtības | komentārs |
---|---|---|
Validator_CompareAttribute | {0} un {1} nesakrīt. | "{0}" un "{1}" nesakrīt. |
Validator_CreditCardAttribute | {0} nav derīgs kartes numurs. | Lauks {0} nav derīgs kredītkartes numurs. |
Validator_DataTypeAttribute_Date | Ievadiet derīgu datumu. | Lūdzu, ievadiet derīgu datumu. |
Validator_EmailAddressAttribute | {0} nav derīga e-pasta adrese. | Lauks {0} nav derīga e-pasta adrese. |
Validator_FileExtensionsAttribute | {0} pieņem tikai failus ar šādiem paplašinājumiem: : {1} | Lauks {0} pieņem tikai failus ar šādiem paplašinājumiem: {1} |
Validator_MaxLengthAttribute | {0} jābūt virknei vai masīva tipam ar maksimālo garumu "{1}". | Lauka {0} jābūt virknei vai masīva tipam ar maksimālo garumu "{1}". |
Validator_MinLengthAttribute | {0} jābūt virknei vai masīva tipam ar minimālo garumu "{1}". | Lauka {0} jābūt virknei vai masīva tipam ar minimālo garumu "{1}". |
Validator_PhoneAttribute | {0} nav derīgs tālruņa numurs. | Lauks {0} nav derīgs tālruņa numurs. |
Validator_RangeAttribute | {0} jābūt no {1} līdz {2}. | Lauka {0} jābūt no {1} līdz {2}. |
Validator_RegularExpressionAttribute | {0} jāatbilst regulārajai izteiksmei "{1}". | Lauku {0} jāatbilst regulārajai izteiksmei "{1}". |
Validator_RequiredAttribute | {0} ir nepieciešams. | Ir nepieciešams lauks {0}. |
Validator_StringLengthAttribute | {0} jābūt {1} ciparu robežās. | Lauka {0} jābūt virknei ar maksimālo garumu {1}. |
Validator_UrlAttribute | {0} nav derīgs URL. | Lauks {0} nav derīgs pilnībā kvalificēts http, https vai ftp URL. |
Validator_StringLengthAttributeWithMin | {0} jābūt vismaz {2} {1} cipariem. | Lauka {0} jābūt virknei ar maksimālo garumu {1} un minimālo {2} garumu. |
Pēc tam izveidojiet šādu AdapterProvider klasi:
Klases nosaukums ir patvaļīgs, bet šoreiz CustomValidationAttributeAdapterProvider
es uzrakstīšu klasi ar nosaukumu un uzrakstīšu kodu šādi:
Koda faila atrašanās vieta ir patvaļīga, bet paraugs tiek ievietots mapē ar nosaukumu 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);
}
}
}
Ja iestatāt modeļa rekvizītus uz Required
vai , metode tiek izsaukta katrai StringLength
IValidationAttributeAdapterProvider.GetAttributeAdapter
validācijai.
ErrorMessageResourceName
Ja rekvizītā ir vērtība, modeļa puses kodam jau ir ziņojuma vai lokalizācijas atslēga, tāpēc tas atgriežas tāds, kāds tas ir.
Ja tas ir tukšs, saskaņojiet prefiksa un validācijas atribūta klašu nosaukumus, lai padarītu to par lokalizācijas atslēgu, un pēc tam izgūstiet lokalizēto tekstu no atslēgas un iestatiet to ErrorMessage
uz .
Tas ļauj lokalizēt lielāko daļu noklusējuma ziņojumu.
Pēc tam reģistrējiet šo klasi startēšanas .cs. Būtībā to var pievienot šādi.
// 省略
using Microsoft.AspNetCore.Mvc.DataAnnotations;
namespace LocalizationDefaultValidation
{
public class Startup
{
// 省略
// このメソッドはランタイムによって呼び出されます。 このメソッドを使用して、コンテナーにサービスを追加します。
public void ConfigureServices(IServiceCollection services)
{
// 省略
// 作成した CustomValidationAttributeAdapterProvider をシングルトンとして登録します
services.AddSingleton<IValidationAttributeAdapterProvider, CustomValidationAttributeAdapterProvider>();
}
// 省略
}
}
Palaidiet to, lai pārliecinātos, ka tas darbojas pareizi.
Esoša ziņojuma mainīšana pēc parametriem
Piemēram, StringLength
atribūta ziņojums ir lokalizēts, piemēram, "{0} jābūt {1} ciparu robežās."
MinimumLength
Ja rekvizīts ir iestatīts, iespējams, vēlēsities mainīt {0} kā "Norādīt {2} ciparus vai vairāk {1} ciparu skaitā".
Tādā CustomValidationAttributeAdapterProvider
gadījumā paplašināt kategoriju šādi:
// 省略
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);
}
}
// 省略
}
}
}
Tā kā metode tiek izsaukta katrai GetAttributeAdapter
validācijai, ja nodotais mainīgais attribute
bija StringLengthAttribute
MinimumLength
atribūts, pārbaudiet rekvizītu,
Ja ir iestatīts, iegūstiet ziņojumu, kurā ņemts vērā arī minimālais ciparu skaits un ErrorMessage
tiek aizstāts .
Ja to palaižat, pārbaudiet un ziņojums mainās, viss ir kārtībā.
Citi vispārīgi ziņojumi
Daži ziņojumi netiek lokalizēti pēc tam, kad esat to jisijis līdz šim. Piemēram, ziņojumi, kas tiek noteikti tikai Javascriptā.
Mērķis ir jquery.validate.js
failā norādītais ziņojums.
Tā kā šo failu nedrīkst rediģēt tieši, lai aizstātu šos ziņojumus ar lokalizētu tekstu, input
tagam jāpievieno atribūts, piemēram, un data-val-XXXX
jāiestata lokalizēts teksts.
XXXX daļā ir jquery.validate.js
atslēga iepriekš redzamajā attēlā. (piemēram, data-val-number
u. c.)
data-val-XXXX
Lai iestatītu lokalizētu tekstu atribūtiem
Lokalizēt ziņojumu, ja kā piemērs vecuma ievades laukā ir iekļautas rakstzīmes, kas nav skaitliskas.
UserViewModel.Age
ir Range
atribūts, un data-val-range
izvades HTML pievieno ievades atribūtu.
<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>
Tomēr data-val-number
skaitliskās pārbaudes ziņojums nav lokalizēts, jo atribūta nav.
Modeļa pusē tiks pievienots vēl viens atribūts, lai drukātu arī lokalizēto ziņojumu pievienoto data-val-number
atribūtu.
Pirmais solis ir izveidot atribūtu klasi, kas pārbauda, vai tas ir IntAttribute
skaitlis: Tas aprobežojas ar šeit, bet jūs int
varat to mainīt atkarībā no situācijas.
Koda fails var būt jebkurā vietā, bet šoreiz tas atrodas mapē Adapteris.
using System.ComponentModel.DataAnnotations;
namespace LocalizationDefaultValidation
{
public class IntAttribute : ValidationAttribute
{
public override bool IsValid(object value)
{
// 渡された値が int であれば有効な値とする
return value is int;
}
}
}
Ja iestatītā vērtība ir int
veids, tas ir atribūts, kas ir tikai parasts spriedums, bet praksē tas ir 100% normāls, ja tas ir iestatīts uz int tipa īpašību, tāpēc šīs klases apstrādei nav nekādas jēgas.
Šī laika mērķis ir parādīt lokalizētus kļūdu ziņojumus klientā.
Pēc tam izveidojiet šādu adaptera IntAttributeAdapter
klasi: Tas ir arī adaptera mapē.
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;
}
}
Šeit ir AddValidation
metode, kas aprakstīta MergeAttribute
metodē.
Atribūtu sapludināšana kā ievades taga atribūti, data-val-number
lai atgrieztos klientā.
Atribūtā iestatāmā vērtība iestata lokalizētu kļūdas ziņojumu.
Atgrieziet šo adapteri iepriekš izveidotajā CustomValidationAttributeAdapterProvider
klasē.
// 省略
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);
}
// 省略 (前に追加したコード)
}
}
}
Ja validamā vērtība IntAttribute
ir , atgrieziet IntAttributeAdapter
iepriekš izveidoto.
Rekvizīts ar int atribūtu tagad tiek pievienots, kad tas tiek parādīts klienta data-val-number
pusē.
Visbeidzot, UserViewModel.Age
IntAttribute
papildiniet .
Kad esat nofiksējis kodu, izmēģiniet to, lai redzētu, vai vēlaties to paņemt.
<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>
Ir arī citi nelokalizēti ziņojumi, bet tos var lokalizēt iepriekš aprakstītajās metodēs. Pievienojiet kodu, kad tas ir nepieciešams.