A paraméterek nevére, bemeneti érvényesítési üzenetekhez stb. használt DataAnnotations többnyelvű támogatása.

Oldal létrehozásának dátuma :

környezet

ASP.NET mag
  • 5,0 MVC

előtétel

Ez a tipp a következő tippek megértéseként íródott:

Továbbá, ha új projektet hoz létre, a fenti tippek alapján hozzá kell adnia a következő fájlokat és kódot.

  • Hozzon létre egy SharedResource.resx (+en, es) fájlt. (Lehet, hogy a tartalom üres.)
  • SharedResource.cs fájl létrehozása
  • Honosítási kód hozzáadása a Startup.ConfigureServices szolgáltatáshoz
  • Honosítási kód hozzáadása a Startup.Configure

Indítási .cs javítások

Mivel a DataAnnotations-hez kapcsolódó további többnyelvű beállításokra van szükség, Startup.ConfigureServices módosítsa a módszert az alábbiak szerint:

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));
     });
}

Modellezés a bemenethez

Hozzon létre egy modellt, amely a bemeneti képernyőhöz kötődik. Ebben a mintában számos tulajdonságot hoztunk létre a különböző bemeneti vezérlők befogadására. Ha problémái vannak az alkotáshoz, csak kettőt hozhat létre.

Hozzon létre egy UserViewModel .cs a Modellek mappában.

A kódnak így kell kinéznie: A névtérnek megfelelőnek kell lennie. A beállított attribútumok nem túl relevánsak több nyelvre, mert csak hozzájuk vannak rendelve. A többnyelvű támogatásra később kerül sor.

using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace LocalizationDataAnnotation.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]*$", ErrorMessage = "Password")]
    public string Password { get; set; }

    // 省略
  }

  // 省略
}

Művelet létrehozása

Műveleteket hozhat létre a felhasználó regisztrációs képernyőjének megjelenítéséhez és a regisztrációs HomeController műveletek végrehajtásához.

A képernyők és műveletek létrehozása nem a tippek fő témája, ezért helyénvaló. Ezenkívül a tényleges regisztrációs folyamat nem történik meg.

// 初期コードは省略

namespace LocalizationDataAnnotation.Controllers
{
  public class HomeController : Controller
  {
    // 初期コードは省略

    public IActionResult Create()
    {
      return View();
    }

    [HttpPost]
    public IActionResult Create(UserViewModel model)
    {
      // エラーなら差し戻し
      if (ModelState.IsValid == false) return View(model);

      // 正常に登録できた場合は Index に戻る
      return RedirectToAction(nameof(Index));
    }
  }
}

Hivatkozás a felhasználói regisztrációs képernyőre

Hozzon létre egy hivatkozást a felhasználói regisztrációs képernyőre a Views\Home\Index.cshtml-ben. Bármit írhat, amíg képernyőátmenetet kaphat.

asp-route-culture Az attribútum a megadott nyelven nyitja meg az oldalt.

<!-- 初期コード省略 -->

<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>

Felhasználói regisztrációs képernyő létrehozása

Create Kattintson a jobb gombbal a műveletre, és válassza a Nézet hozzáadása lehetőséget.

Válassza a Razor View lehetőséget.

Készítse el a "Létrehozás" sablont és a "UserViewModel" modellosztályt. Ha a UserViewModel mintakódot használja, megjegyzéseket is belefoglaltam a kódba. Ha bizonyos attribútumokat helyez el egy tulajdonságban, hibaüzenet jelenik meg, amikor kódot hoz létre az állványzatban. A nézet létrehozása előtt ideiglenesen megjegyzést fűz.

Ha valóban hibaüzenetet kap a létrehozásakor, hozzon létre egy üres Razor nézetet, és adja meg a következő kódot:

@model LocalizationDataAnnotation.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">
      <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">
        <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");}
}

Most, mint előkészítő szakaszban, eddig sikeresen felépítheti a kódot, és megpróbálhatja helyesen látni és futtatni a képernyőt.

Többnyelvű szöveges regisztráció DataAnnotations

Minden tulajdonságot hosszú ideig magyarázni kell, ezért ID beszélünk és beszélünk. Name Más tulajdonságok hasonló módon többnyelvűek, ezért próbálja ki őket.

A következő szövegek több nyelven érhetők el itt.

Többnyelvű szövegbillentyűk
Azonosító paraméter megjelenítendő neve ID_DisplayName
Hibaüzenet jelenik meg, ha az azonosító nincs beírva Validate_Required
Hibaüzenet jelenik meg, ha az azonosító beviteli karaktere meghaladja a 20 karaktert Validate_StringLength
Hibaüzenet jelenik meg, ha az azonosító nem numerikus karakterekkel van beírva Validate_Alphanumeric
Névparaméter megjelenítendő neve Name_DisplayName
Hibaüzenet jelenik meg, ha a név több mint 50 karaktert írt be Validate_StringLength

Validate_XXXXX legyen univerzális. Nincs kulcs elnevezési konvenció, így szabadon csatolhatja.

Ezeket a kulcsokat használva, SharedResource.resx a lefordított szöveget a SharedResource.en.resx , , SharedResource.es.resx .

SharedResource.resx

Névérték
Validate_Required "{0}" szükséges.
Validate_StringLength A "{1}" a "{0}" -ban adhatja meg.
Validate_Alphanumeric {0} csak alfanumerikus lehet.
ID_DisplayName Azonosító (alfanumerikus)
Name_DisplayName azonosság

SharedResource.hu.resx

Névérték
Validate_Required A "{0}" szükséges bemenet.
Validate_StringLength A "{0}" karakter maximális száma "{1}".
Validate_Alphanumeric Csak alfanumerikus karaktereket lehet beírni a "{0}" szöveghez.
ID_DisplayName AZONOSÍTÓ (alfanumerikus karakterek)
Name_DisplayName Teljes név

SharedResource.es.resx

Névérték
Validate_Required "{0}" es una entrada obligatoria.
Validate_StringLength El número máximo de caracteres que se pueden ingresar en "{0}" es "{1}".
Validate_Alphanumeric Solo se pueden ingresar caracteres alfanuméricos para "{0}".
ID_DisplayName AZONOSÍTÓ (caracteres alfanuméricos)
Name_DisplayName Nombre completo

A bemeneti érvényesítési hibaüzenetek a paraméterneveket és -számokat {0} és {1} cserélik. Használjuk pozitívan.

Többnyelvű alkalmazás a DataAnnotations-ra

Minden többnyelvű beállítás a modell attribútumaira (DataAnnotations) vonatkozik.

Ha a paraméter megjelenítendő nevére szeretné alkalmazni, Display csatoljon és adjon meg egy Name sharedResource.resx kulcsot a tulajdonságban.

Ha a bemeneti ellenőrzés során hibaüzenetekre szeretne alkalmazni, adjon meg egy ErrorMessage sharedResource.resx kulcsot az egyes érvényesítési attribútumok tulajdonságában.

public class UserViewModel
{
  [Required(ErrorMessage = "Validate_Required")]
  [Display(Name = "ID_DisplayName")]
  [StringLength(20, ErrorMessage = "Validate_StringLength")]
  [RegularExpression(@"^[0-9a-zA-Z]*$", ErrorMessage = "Validate_Alphanumeric")]
  public string ID { get; set; }

  [Display(Name = "Name_DisplayName")]
  [StringLength(50, ErrorMessage = "Validate_StringLength")]
  public string Name { get; set; }

  // 省略
}

Ezzel befejeződik a beállítás. Ezután futtassa le, hogy megnézze, hogyan működik.

Egyébként a bemeneti karakterek számát korlátozza a bemeneti maxlength címke attribútuma. Ha látni szeretné az üzenetet, el kell távolítania a korlátozásokat, például a webböngésző fejlesztői eszközeiben.

By the way, van néhány üzenet jelenik meg, amikor regisztrálja a kor, dátum, stb üres. Ez egy olyan üzenet, amely a keretrendszer oldalán van beállítva, de egy másik tipp megmutatja, hogyan támogathatja azt több nyelven.

Minden kódhoz

Ez a tipp csak néhány tulajdonságot tartalmaz, de a mintakód az összes html5-kompatibilis beviteli mezőt lefedi. Ha ellenőrizni szeretné, kérjük, olvassa el az oldal feletti linket.

Részben alább felsorolt

UserViewModel.cs

using Microsoft.AspNetCore.Http;
using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;

namespace LocalizationDataAnnotation.Models
{
  public class UserViewModel
  {
    [Required(ErrorMessage = "Validate_Required")]
    [Display(Name = "ID_DisplayName")]
    [StringLength(20, ErrorMessage = "Validate_StringLength")]
    [RegularExpression(@"^[0-9a-zA-Z]*$", ErrorMessage = "Validate_Alphanumeric")]
    public string ID { get; set; }

    [Display(Name = "Name_DisplayName")]
    [StringLength(50, ErrorMessage = "Validate_StringLength")]
    public string Name { get; set; }

    [Display(Name = "Password_DisplayName")]
    [StringLength(50, MinimumLength = 8, ErrorMessage = "Validate_StringLengthRange")]
    [DataType(DataType.Password)]
    [RegularExpression(@"^[0-9a-zA-Z]*$", ErrorMessage = "Validate_Alphanumeric")]
    public string Password { get; set; }

    [Display(Name = "ConfirmPassword_DisplayName")]
    [StringLength(50, MinimumLength = 8, ErrorMessage = "Validate_StringLengthRange")]
    [DataType(DataType.Password)]
    [Compare(nameof(Password), ErrorMessage = "Validate_Compare")]
    public string ConfirmPassword { get; set; }

    [Display(Name = "Email_DisplayName")]
    [EmailAddress(ErrorMessage = "Validate_EmailAddress")]
    [DataType(DataType.EmailAddress)] // スキャフォールディングするときはコメントアウトする
    public string Email { get; set; }

    [Display(Name = "Age_DisplayName")]
    [Required(ErrorMessage = "Validate_Required")]
    [Range(0, 150, ErrorMessage = "Validate_Range")]
    public int Age { get; set; }

    [Display(Name = "Gender_DisplayName")]
    [Required(ErrorMessage = "Validate_Required")]
    [EnumDataType(typeof(GenderType))]
    public GenderType Gender { get; set; }

    [Display(Name = "Birthday_DisplayName")]
    [DataType(DataType.Date)]
    public DateTime Birthday { get; set; }

    [Display(Name = "Phone_DisplayName")]
    [Phone(ErrorMessage = "Validate_Phone")]
    [DataType(DataType.PhoneNumber)] // スキャフォールディングするときはコメントアウトする
    public string Phone { get; set; }

    [Display(Name = "PostalCode_DisplayName")]
    [DataType(DataType.PostalCode)]
    public string PostalCode { get; set; }

    [Display(Name = "CreditCard_DisplayName")]
    [CreditCard(ErrorMessage = "Validate_CreditCard")]
    [DataType(DataType.CreditCard)] // スキャフォールディングするときはコメントアウトする
    public string CreditCard { get; set; }

    [Display(Name = "Money_DisplayName")]
    [DataType(DataType.Currency)]
    public decimal Money { get; set; }

    [Display(Name = "StartDateTime_DisplayName")]
    [DataType(DataType.DateTime)]
    public DateTime StartDateTime { get; set; }

    [Display(Name = "WakeUpTime_DisplayName")]
    [DataType(DataType.Time)]
    public TimeSpan WakeUpTime { get; set; }

    [Display(Name = "Homepage_DisplayName")]
    [Url(ErrorMessage = "Validate_Url")]
    [DataType(DataType.Url)] // スキャフォールディングするときはコメントアウトする
    public string Homepage { get; set; }

    [Display(Name = "MyImage_DisplayName")]
    [Url(ErrorMessage = "Validate_Url")]
    [DataType(DataType.ImageUrl)] // スキャフォールディングするときはコメントアウトする
    public string MyImage { get; set; }

    [Display(Name = "MyColor_DisplayName")]
    public string MyColor { get; set; }

    [Display(Name = "WorkingDays_DisplayName")]
    [MaxLength(5, ErrorMessage = "Validate_MaxLength")]
    [EnumDataType(typeof(DayOfWeek))]
    public DayOfWeek[] WorkingDays { get; set; }

    [Display(Name = "VacationDay_DisplayName")]
    [MinLength(3, ErrorMessage = "Validate_MinLength")]
    [EnumDataType(typeof(DayOfWeek))]
    public DayOfWeek[] VacationDay { get; set; }

    [Display(Name = "Comment_DisplayName")]
    [StringLength(200, ErrorMessage = "Validate_StringLength")]
    [DataType(DataType.MultilineText)]
    public string Comment { get; set; }

    [Display(Name = "FileName_DisplayName")]
    [FileExtensions(Extensions = "png", ErrorMessage = "Validate_FileExtensions")]
    public string FileName { get; set; }

    [Display(Name = "UploadFile_DisplayName")]
    [DataType(DataType.Upload)]
    public List<IFormFile> UploadFile { get; set; }

    [Display(Name = "Month_DisplayName")]
    public DateTime Month { get; set; }

    [Display(Name = "Search_DisplayName")]
    public string Search { get; set; }

    [Display(Name = "Range_DisplayName")]
    [Range(10, 100, ErrorMessage = "Validate_Range")]
    public int Range { get; set; }

    [Display(Name = "Week_DisplayName")]
    public string Week { get; set; }

    [Display(Name = "IsAccepted_DisplayName")]
    [Required(ErrorMessage = "Validate_Required")]
    public bool IsAccepted { get; set; }
  }

  public enum GenderType
  {
    None,
    Man,
    Woman,
    Other,
  }
}

HomeController.cs

using LocalizationDataAnnotation.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 LocalizationDataAnnotation.Controllers
{
  public class HomeController : Controller
  {
    private readonly ILogger<HomeController> _logger;

    public HomeController(ILogger<HomeController> logger)
    {
      _logger = logger;
    }

    public IActionResult Index()
    {
      return View();
    }

    public IActionResult Privacy()
    {
      return View();
    }

    [ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
    public IActionResult Error()
    {
      return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
    }

    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()));
  }
}

Create.cshtml

@model LocalizationDataAnnotation.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");}
}