レッスンの目的。 多言語サイトの作成を学びます。 DB構造 サイトのリソース。 言語の定義。 言語を切り替えます。 管理領域で作業します。
多言語ウェブサイトの問題
そのため、顧客はサイトを多言語にする、つまり ロシア語、フランス語、および英語で。 多言語のブログ、ホテルのサイト、不動産のサイトなどがあります。
最初に、翻訳対象を決定します。
- 選択した場所に応じて、日付、金額を書きます。 System.Globalizationクラスがこれを処理します。
- サイトの組み込みリソース-エラーメッセージ(「フィールドを空にすることはできません」、「フィールドは必須です」)およびその他のメッセージ。
- ロゴ、画像、コントロールのjsローカリゼーションなどの非埋め込みリソース。 それらを切り替えるには、ページ上の現在の言語値を知る必要があります。
- カスタム値。
この問題を解決するためのいくつかのオプションがあります。 それらを考慮してください。
- できる最も簡単なことは、さまざまなサイトです。 ロシアのサイトが必要-完了。 翻訳が必要です。サイトをコピーし、すべてのデータを翻訳しました。それだけです。 このオプションは、サイトが小さく、数ページのみで静的で、管理パネルがない場合に受け入れられます。
- 異なるデータベース。 選択したローカリゼーションに応じて、サイトは1つまたは別のデータベースに接続されます。 新しい言語を追加する必要がある場合は、データベースとサイトのリソース全体が翻訳されます。 しかし、データベースは異なる場合があり、ある言語で書かれた記事は別の言語に翻訳することはできません。また、原則として翻訳する必要のない画像を複製する必要があります。
- データベースを使用するときのローカリゼーション管理。
すぐに3番目のオプションを検討し、アプリケーションでこれを整理する方法を決定します。
- langパラメータがサイトアドレスに表示されるようになりました
- おそらくアドレスは次のようになります
our-site.com{lang}/{controller}/{action}
- おそらくアドレスは次のようになります
our-site.com{controller}/{action}?lang=ru
- langパラメーターは、ISO 2文字の言語定義です(ru-ロシア語、uk-ウクライナ語、cs-チェコ語)
- まず、System.Globalizationを使用して日付を正しく表示します。
- 特定の言語に関するエラーを表示するために内部リソースを編成します
- データベース内のテーブルを整理して、各レコードについて必要なフィールドの翻訳ができるようにします。
ロシア語と英語の2つのローカライズを作成します。ロシア語はデフォルトです。
ルーティング
DefaultAreaRegistrationで、lang処理(/Areas/Default/DefaultAreaRegistration.cs)を追加します。
context.MapRoute( name: "lang", url: "{lang}/{controller}/{action}/{id}", defaults: new { controller = "Home", action = "Index", id = UrlParameter.Optional }, constraints : new { lang = @"ru|en" }, namespaces: new[] { "LessonProject.Areas.Default.Controllers" } ); context.MapRoute( name : "default", url : "{controller}/{action}/{id}", defaults : new { controller = "Home", action = "Index", id = UrlParameter.Optional, lang = "ru" }, namespaces : new [] { "LessonProject.Areas.Default.Controllers" } );
したがって、行がlangで始まる場合、「lang」ルートの処理を使用します。 制約(制限)に注意してください。ここでは、言語はruまたはenのみであることが指定されています。 この条件が満たされない場合、次のルート処理に進みます-「デフォルト」。デフォルトではlang = ruです。
これを使用してDefaultControllerを初期化し、スレッドカルチャ(Thread.Current.CurrentCulture)(/Areas/Default/DefaultController.cs)を変更します。
public class DefaultController : BaseController { public string CurrentLangCode { get; protected set; } public Language CurrentLang { get; protected set; } protected override void Initialize(System.Web.Routing.RequestContext requestContext) { if (requestContext.HttpContext.Request.Url != null) { HostName = requestContext.HttpContext.Request.Url.Authority; } if (requestContext.RouteData.Values["lang"] != null && requestContext.RouteData.Values["lang"] as string != "null") { CurrentLangCode = requestContext.RouteData.Values["lang"] as string; CurrentLang = Repository.Languages.FirstOrDefault(p => p.Code == CurrentLangCode); var ci = new CultureInfo(CurrentLangCode); Thread.CurrentThread.CurrentUICulture = ci; Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(ci.Name); } base.Initialize(requestContext); } }
当然、BaseControllerでは、構成ファイル(/Controllers/BaseController.cs)を使用してストリームカルチャの初期化を削除します。
protected override void Initialize(System.Web.Routing.RequestContext requestContext) { if (requestContext.HttpContext.Request.Url != null) { HostName = requestContext.HttpContext.Request.Url.Authority; } base.Initialize(requestContext); }
開始し、日付出力がどのように変化するかを確認します。

第1段階が完了しました。 私たちは、サイトリソースの管理に目を向けます。
サイトのリソース
サイトリソースはすべて、翻訳が必要な静的な行です。
メインページには、ロール、ユーザー、ログイン、登録の4つの行があります。 リソースファイルを作成します。
- Asp.netフォルダーをApp_LocalResourcesフォルダーに追加します。

- GlobalRes.resxおよびGlobalRes.en.resxファイルをその中に作成します。

- GlobalRes-ロシア語翻訳、GlobalRes.en-英語で行を追加します:
- GlobalResのプロパティを開き、フィールドに次の値を設定します
- ビルドアクション:埋め込みリソース
- カスタムツール:PublicResXFileCodeGenerator

- system.web.webPages.razor(Web.config)のWeb.cofigに名前空間LessonProject.App_LocalResourcesを追加します。
<system.web.webPages.razor> <pages pageBaseType="System.Web.Mvc.WebViewPage"> <namespaces> <add namespace="LessonProject.Helper" /> <add namespace="LessonProject.Tools" /> <add namespace="LessonProject.App_LocalResources" /> </namespaces> </pages> </system.web.webPages.razor>
- UserLogin.cshtml(/Areas/Default/Views/Home/UserLogin.cshtml)およびIndex.cshtml((/Areas/Default/Views/Home/Index.cshtml)で使用します:
@model LessonProject.Model.User @if (Model != null) { <li>@Model.Email</li> <li>@Html.ActionLink("", "Logout", "Login")</li> } else { <li><span class="btn btn-link" id="LoginPopup">@GlobalRes.Enter</span></li> <li>@Html.ActionLink(GlobalRes.Register, "Register", "User")</li> } … @{ ViewBag.Title = "LessonProject"; Layout = "~/Areas/Default/Views/Shared/_Layout.cshtml"; } <h2>LessonProject </h2> <p> @DateTime.Now.ToString("D") <div class="menu"> <a href="@Url.Action("Index", "Role", new { id = "1" })">@GlobalRes.Roles</a> @Html.ActionLink(GlobalRes.Users, "Index", "User") </div> </p>
実行、確認:

LoginViewの例を使用して、検証メッセージの設定に移りましょう。
- リソースファイル(/App_LocalResources/GlobalRes.resx)のフィールドにErrorMessageを選択します。
EnterEmail | メールアドレスを入力してください |
EnterPassword | パスワードを入力してください |
- LoginView.cs(/Models/ViewModel/LoginView.cs)で検証ルールを設定します。
public class LoginView { [Required(ErrorMessageResourceType=typeof(GlobalRes), ErrorMessageResourceName="EnterEmail")] public string Email { get; set; } [Required(ErrorMessageResourceType = typeof(GlobalRes), ErrorMessageResourceName = "EnterPassword")] public string Password { get; set; } public bool IsPersistent { get; set; } }
localhost / en / Loginページのバージョンをチェックインします。

ただし、ポップアップログインの場合、デフォルトのURLを使用してポップアップブロックを呼び出すため、これらの警告はロシア語のままです。 したがって、langパラメーターを設定することにより、これを変更できます。
- リソースに追加(/App_LocalResources/GlobalRes(.en).resx)CurrentLang = ru and CurrentLang = en
- _Layout.cshtml(/Areas/Default/Views/Shared/_Layout.cshtml)の非表示フィールドにこれをリストします。
<body> @Html.Hidden("CurrentLang", GlobalRes.CurrentLang) <div class="navbar navbar-fixed-top"> • ajax- (/Scripts/common.js): _this = this; this.loginAjax = "/Login/Ajax"; this.init = function () { _this.loginAjax = "/" + $("#CurrentLang").val() + _this.loginAjax; $("#LoginPopup").click(function () { _this.showPopup(_this.loginAjax, initLoginPopup); }); } function initLoginPopup(modal) { $("#LoginButton").click(function () { $.ajax({ type: "POST", url: _this.loginAjax, data : $("#LoginForm").serialize(),
私たちはチェックします:

データベース
データベースを操作する最も重要なセクションに進みます。 たとえば、Post型(ブログ投稿)のオブジェクトがありますが、もちろん2つの言語である必要があります。
ID | 一意のレコード番号 | |
ユーザーID | 投稿者 | |
ヘッダー | 見出し | 翻訳が必要 |
URL | URLレコード | |
内容 | 投稿内容 | 翻訳が必要 |
追加日 | 追加日 | |
それで、それはどのように整理されますか:
- 言語が定義される言語テーブルを作成しましょう
- 変換を必要としないすべてのフィールドが配置される投稿テーブルを作成します
- PostおよびLanguageに関連付けられたPostLangテーブルを作成します。ここで、Postテーブルに必要なフィールドを翻訳し、Languageテーブルに関連付けます。

OK、今度はこれをLessonProject.Model(LessonProject.Model / IRepository.cs)に追加します。
#region Language IQueryable<Language> Languages { get; } bool CreateLanguage(Language instance); bool UpdateLanguage(Language instance); bool RemoveLanguage(int idLanguage); #endregion #region Post IQueryable<Post> Posts { get; } bool CreatePost(Post instance); bool UpdatePost(Post instance); bool RemovePost(int idPost); #endregion
作成済みのスニペット/Proxy/Language.csを使用してモデルを作成します。
namespace LessonProject.Model { public partial class Language { } }
/Proxy/Post.cs:
namespace LessonProject.Model { public partial class Post { } }
/SqlRepository/Language.cs:
public partial class SqlRepository { public IQueryable<Language> Languages { get { return Db.Languages; } } public bool CreateLanguage(Language instance) { if (instance.ID == 0) { Db.Languages.InsertOnSubmit(instance); Db.Languages.Context.SubmitChanges(); return true; } return false; } public bool UpdateLanguage(Language instance) { Language cache = Db.Languages.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Code = instance.Code; cache.Name = instance.Name; Db.Languages.Context.SubmitChanges(); return true; } return false; } public bool RemoveLanguage(int idLanguage) { Language instance = Db.Languages.Where(p => p.ID == idLanguage).FirstOrDefault(); if (instance != null) { Db.Languages.DeleteOnSubmit(instance); Db.Languages.Context.SubmitChanges(); return true; } return false; } }
/SqlRepository/Post.cs:
public partial class SqlRepository { public IQueryable<Post> Posts { get { return Db.Posts; } } public bool CreatePost(Post instance) { if (instance.ID == 0) { Db.Posts.InsertOnSubmit(instance); Db.Posts.Context.SubmitChanges(); return true; } return false; } public bool UpdatePost(Post instance) { Post cache = Db.Posts.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) {
したがって、Postクラスのオブジェクトには、さまざまな翻訳が保存されているPostLangのセットがあります。 さらに、英語またはロシア語への翻訳は、そうである場合とそうでない場合があります。 しかし、少なくとも1つの言語が必要です。 これのために何をする必要があります:
- 言語フィールドを投稿に追加(ヘッダー、コンテンツ)
- CurrentLangプロパティを作成してみましょう。変更すると、言語フィールドが初期化されます。
- Postデータベースにエントリを作成すると、PostLangデータベースにエントリが自動的に作成されます。
- データベースのレコードを変更すると、どの言語が変更されているかがチェックされ、そのような言語(翻訳)がまだない場合は、新しいPostLangレコードがデータベースに作成されます。
実装(/Proxy/Post.cs)に進みましょう。
public partial class Post { private int _currentLang; public int CurrentLang { get { return _currentLang; } set { _currentLang = value; var currentLang = PostLangs.FirstOrDefault(p => p.LanguageID == value); if (currentLang == null) { IsCorrectLang = false; var anyLang = PostLangs.FirstOrDefault(); if (anyLang != null) { SetLang(anyLang); } } else { IsCorrectLang = true; SetLang(currentLang); } } } private void SetLang(PostLang postLang) { Header = postLang.Header; Content = postLang.Content; } public bool IsCorrectLang { get; protected set; } public string Header { get; set; } public string Content { get; set; } }
ここで重要なのは、必要な翻訳がない場合、最初の翻訳が取得され、IsCorrectLang = falseが設定されることです。 これは、何も表示しないよりも、少なくともいくつかの情報をユーザーに表示する方がよいようにするためです。
投稿オブジェクト(/SqlRepository/Post.cs)の作成/変更:
public bool CreatePost(Post instance) { if (instance.ID == 0) { instance.AddedDate = DateTime.Now; Db.Posts.InsertOnSubmit(instance); Db.Posts.Context.SubmitChanges(); var lang = Db.Languages.FirstOrDefault(p => p.ID == instance.CurrentLang); if (lang != null) { CreateOrChangePostLang(instance, null, lang); return true; } } return false; } public bool UpdatePost(Post instance) { Post cache = Db.Posts.Where(p => p.ID == instance.ID).FirstOrDefault(); if (cache != null) { cache.Url = instance.Url; Db.Posts.Context.SubmitChanges(); var lang = Db.Languages.FirstOrDefault(p => p.ID == instance.CurrentLang); if (lang != null) { CreateOrChangePostLang(instance, cache, lang); return true; } return true; } return false; } private void CreateOrChangePostLang(Post instance, Post cache, Language lang) { PostLang postLang = null; if (cache != null) { postLang = Db.PostLangs.FirstOrDefault(p => p.PostID == cache.ID && p.LanguageID == lang.ID); } if (postLang == null) { var newPostLang = new PostLang() { PostID = instance.ID, LanguageID = lang.ID, Header = instance.Header, Content = instance.Content, }; Db.PostLangs.InsertOnSubmit(newPostLang); } else { postLang.Header = instance.Header; postLang.Content = instance.Content; } Db.PostLangs.Context.SubmitChanges(); }
CreateOrChangePostLang関数の動作を検討してください。
- この関数を呼び出すとき、必要な言語を言語で検索します。 言語が見つからない場合、呼び出しは発生せず、PostLangオブジェクトを作成しません(つまり、翻訳)
- 必要な言語が見つかったら、CreateOrChangePostLangを呼び出します。
- キャッシュがゼロの場合(PostLangオブジェクトがまだ作成されていない場合)または
- キャッシュがヌルではないが、翻訳が見つからない場合、
- 翻訳を作成します(PostLangデータベースに書き込みます)
- それ以外の場合は、見つかった翻訳を変更します。
投稿エントリを削除すると、すべてのPostLangsがOnDelete =カスケードリンクによって削除されます(これに従ってください)
必要な言語のエントリは、すでにデータベースに追加されている必要があります。
管理者
これをすべて実証するために、管理パネルを作成します。 アクションプランは次のとおりです(後で改良して表明します)。
- モデルを作成する
- 入力言語とユーザーを関連付けます(管理者または編集者が機能する言語を明確にするため)
- 言語切り替えを作成する
- 管理者ホームページを作成
- ポストコントローラーを作成する
- デフォルト/ postControllerパーツの投稿を一覧表示する
テーブルUser LanguageIDに追加します。

IRepository.csに追加します。
bool ChangeLanguage(User instance, string LangCode);
/SqlRepository/User.csに実装します。
public bool ChangeLanguage(User instance, string LangCode) { var cache = Db.Users.FirstOrDefault(p => p.ID == instance.ID); var newLang = Db.Languages.FirstOrDefault(p => p.Code == LangCode); if (cache != null && newLang != null) { cache.Language = newLang; Db.Users.Context.SubmitChanges(); return true; } return false; }
モデル/Models/ViewModel/PostView.csを作成します。
public class PostView { public int ID { get; set; } public int UserID { get; set; } public bool IsCorrectLang { get; set; } public int CurrentLang { get; set; } [Required(ErrorMessage = " ")] public string Header { get; set; } [Required] public string Url { get; set; } [Required(ErrorMessage = " ")] public string Content { get; set; } }
GlobalResに検証行を挿入する必要はありません。ここでは、管理パネルでのみ作業し、これは役に立たないためです(管理者は控えめな人であるため)。 しかし、他の要件がある場合は、何をすべきかを知っています。
/Areas/Admin/Controller/AdminController.csを作成します。
public abstract class AdminController : BaseController { public Language CurrentLang { get { return CurrentUser != null ? CurrentUser.Language : null; } } protected override void Initialize(RequestContext requestContext) { CultureInfo ci = new CultureInfo("ru"); Thread.CurrentThread.CurrentCulture = ci; base.Initialize(requestContext); } }
/Areas/Admin/Controller/HomeController.cs:
[Authorize(Roles="admin")] public class HomeController : AdminController { public ActionResult Index() { return View(); } public ActionResult AdminMenu() { return View(); } public ActionResult LangMenu() { if (CurrentLang == null) { var lang = repository.Languages.FirstOrDefault(); repository.ChangeLanguage(currentUser, lang.Code); } var langProxy = new LangAdminView(repository, CurrentLang.Code); return View(langProxy); } [HttpPost] public ActionResult ChangeLanguage(string SelectedLang) { repository.ChangeLanguage(currentUser, SelectedLang); return Redirect("~/admin"); } }
そのため、AdminControllerは現在使用している言語を選択および設定します。 この言語がインストールされていない場合は、最初の言語が選択され、HomeController.cs:LangMenuがユーザーにインストールされます。 LangAdminView.cs(/Models/ViewModel/LangAdminView.cs)を作成します。
public class LangAdminView { private IRepository Repository { get { return DependencyResolver.Current.GetService<IRepository>(); } } public string SelectedLang {get; set; } public List<SelectListItem> Langs { get; set; } public LangAdminView(string currentLang) { currentLang = currentLang ?? ""; Langs = new List<SelectListItem>(); foreach (var lang in Repository.Languages) { Langs.Add(new SelectListItem() { Selected = (string.Compare(currentLang, lang.Code, true) == 0), Value = lang.Code, Text = lang.Name }); } } }
すべてのビュー(+ jsファイル)を説明しましょう:
/Areas/Admin/Views/Shared/_Layout.cshtml:
@{ var currentUser = ((LessonProject.Controllers.BaseController)ViewContext.Controller).CurrentUser; } <!DOCTYPE html> <html> <head> <title>@ViewBag.Title</title> <meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /> @Styles.Render("~/Content/css/jqueryui") @Styles.Render("~/Content/css") @RenderSection("styles", required: false) @Scripts.Render("~/bundles/modernizr") </head> <body> <div class="navbar navbar-fixed-top"> <div class="navbar-inner"> <div class="container-fluid"> <div class="btn-group pull-right"> <a class="btn dropdown-toggle" data-toggle="dropdown" href="#"><i class="icon-user"> </i> @currentUser.Email<span class="caret"></span> </a> <ul class="dropdown-menu"> <li><a href="/"> </a></li> <li class="divider"></li> <li><a href="@Url.Action("Logout", "Login", new { area = "Default" })"></a> </li> </ul> </div> <a class="brand" href="@Url.Action("Index", "Home")">LessonProject</a> </div> </div> </div> <div class="container-fluid"> <div class="row-fluid"> <div class="span3"> <div class="well sidebar-nav"> <ul class="nav nav-list"> @Html.Action("LangMenu", "Home") @Html.Action("AdminMenu", "Home") </ul> </div> </div> <div class="span9"> @RenderBody() </div> </div> </div> @Scripts.Render("~/bundles/jquery") @Scripts.Render("~/bundles/jqueryui") @Scripts.Render("~/bundles/bootstrap") @Scripts.Render("~/bundles/common") @Scripts.Render("/Scripts/admin/common.js") @RenderSection("scripts", required: false) </body> </html>
Index.cshtml(/Areas/Admin/Views/Home/Index.cshtml):
@{ ViewBag.Title = "Index"; Layout = "~/Areas/Admin/Views/Shared/_Layout.cshtml"; } <h2></h2> AdminMenu.cshtml (/Areas/Admin/Views/Home/AdminMenu.cshtml): <li> @Html.ActionLink("", "Index", "Home") </li> <li> @Html.ActionLink("", "Index", "Post") </li>
LangMenu.cshtml(/Areas/Admin/Views/Home/LangMenu.cshtml):
@model LessonProject.Models.ViewModels.LangAdminView <li> @using (Html.BeginForm("ChangeLanguage", "Home", FormMethod.Post, new { id = "SelectLangForm" })) { @Html.DropDownList("SelectedLang", Model.Langs) } </li>
また、SelectedLangハンドラー(/Scripts/admin/common.js):
function AdminCommon() { _this = this; this.init = function () { $("#SelectedLang").change(function () { $("#SelectLangForm").submit(); }); } } var adminCommon = null; $().ready(function () { adminCommon = new AdminCommon(); adminCommon.init(); });
管理者(chernikov@gmail.comがあります)の下に移動し、
localhost / adminページに移動します。
ログインしてログインできない場合は、データベース内のUserRole接続を確認して、現在のユーザーが「admin」コードを持つロールを持つようにします。言語のドロップダウンリストを開きます。 現在使用している言語を示しています。
PostController.csコントローラーを追加します(/Areas/Admin/Controllers/PostController.cs):
public class PostController : AdminController { public ActionResult Index(int page = 1) { var list = Repository.Posts.OrderByDescending(p => p.AddedDate); var data = new PageableData<Post>(list, page); data.List.ForEach(p => p.CurrentLang = CurrentLang.ID); return View(data); } [HttpGet] public ActionResult Create() { var postView = new PostView { CurrentLang = CurrentLang.ID }; return View("Edit", postView); } [HttpGet] public ActionResult Edit(int id) { var post = Repository.Posts.FirstOrDefault(p => p.ID == id); if (post != null) { post.CurrentLang = CurrentLang.ID; var postView = (PostView)ModelMapper.Map(post, typeof(Post), typeof(PostView)); return View(postView); } return RedirectToNotFoundPage; } [HttpPost] [ValidateInput(false)] public ActionResult Edit(PostView postView) { if (ModelState.IsValid) { var post = (Post)ModelMapper.Map(postView, typeof(PostView), typeof(Post)); post.CurrentLang = CurrentLang.ID; if (post.ID == 0) { post.UserID = CurrentUser.ID; Repository.CreatePost(post); } else { Repository.UpdatePost(post); } TempData["Message"] = "!"; return RedirectToAction("Index"); } return View(postView); } public ActionResult Delete(int id) { Repository.RemovePost(id); TempData["Message"] = " "; return RedirectToAction("Index"); } }
Foreach(/Models/Info/PageableData.cs)を作成できるようにPageableDataを変更します。
public class PageableData<T> where T : class { protected static int ItemPerPageDefault = 20; public List<T> List { get; set; } … public PageableData(IQueryable<T> queryableSet, int page, int itemPerPage = 0) { … List = queryableSet.Skip((PageNo - 1) * itemPerPage).Take(itemPerPage).ToList(); } }
Index.cshtml(/Areas/Admin/Views/Post/Index.cshtml):
@model LessonProject.Models.Info.PageableData<LessonProject.Model.Post> @{ ViewBag.Title = ""; Layout = "~/Areas/Admin/Views/Shared/_Layout.cshtml"; } <h2> </h2> @Html.ActionLink("", "Create", "Post", null, new { @class = "btn" }) <table class="table"> <thead> <tr> <th> # </th> <th> </th> <th> </th> <th> </th> </tr> </thead> @foreach (var item in Model.List) { <tr> <td> @item.ID </td> <td> @(item.IsCorrectLang ? "" : " ") </td> <td> @item.Header </td> <td> @Html.ActionLink("", "Edit", "Post", new { id = item.ID }, new { @class = "btn btn-mini" }) @Html.ActionLink("", "Delete", "Post", new { id = item.ID }, new { @class = "btn btn-mini btn-danger" }) </td> </tr> } </table>
ForEachで初期化するとき、言語フィールドは各オブジェクトで既に初期化されています。 言語-現在管理パネルで作業している言語。
編集用のビューは、コントローラーですべての作業を行い、PostViewはすでに言語設定を使用しているため、簡単です。 (/Areas/Admin/Views/Post/Edit.cshtml):
@model LessonProject.Models.ViewModels.PostView @{ ViewBag.Title = Model.ID == 0 ? " " : " "; Layout = "~/Areas/Admin/Views/Shared/_Layout.cshtml"; } <h2>@(Model.ID == 0 ? " " : " ")</h2> <p> </p> @using (Html.BeginForm("Edit", "Post", FormMethod.Post)) { @Html.Hidden("ID", Model.ID) <fieldset> <div class="control-group"> <label class="control-label"> @(!Model.IsCorrectLang && Model.ID != 0 ? " " : "") </label> </div> <div class="control-group"> <label class="control-label"> </label> <div class="controls"> @Html.TextBox("Header", Model.Header, new { @class = "input-xlarge" }) @Html.ValidationMessage("Header") </div> </div> <div class="control-group"> <label class="control-label"> Url</label> <div class="controls"> @Html.TextBox("Url", Model.Url, new { @class = "input-xlarge" }) @Html.ValidationMessage("Url") </div> </div> <div class="control-group"> <label class="control-label"> </label> <div class="controls"> @Html.TextArea("Content", Model.Content, new { @class = "input-xlarge" }) @Html.ValidationMessage("Content") </div> </div> <div class="form-actions"> <button type="submit" class="btn btn-primary"> </button> @Html.ActionLink("", "Index", null, null, new { @class = "btn" }) </div> </fieldset> }
翻訳の必要性に関するプロンプトに注意してください。 この場合、フィールドはすでに入力されているため、翻訳して保存する必要があります。 したがって、翻訳が追加されます。
投稿をいくつか追加して翻訳します。

OK、投稿が作成されました。
デフォルトエリアにPostControllerを作成し、投稿を表示します(/Areas/Default/Controller/PostController.cs):
public class PostController : DefaultController { public ActionResult Index(int page = 1) { var list = Repository.Posts.OrderByDescending(p => p.AddedDate); var data = new PageableData<Post>(list, page); data.List.ForEach(p => p.CurrentLang = CurrentLang.ID); return View(data); } }
Index.cshtml(/Areas/Default/Views/Post/Index.cshtml):
@model LessonProject.Models.Info.PageableData<LessonProject.Model.Post> @{ ViewBag.Title = "Index"; Layout = "~/Areas/Default/Views/Shared/_Layout.cshtml"; } <div class="item"> @foreach (var post in Model.List) { <h3>@post.Header</h3> <p> @post.Content.NlToBr() </p> <span>@post.AddedDate.ToString("d")</span> } </div> <div class="pagination"> @Html.PageLinks(Model.PageNo, Model.CountPage, x => Url.Action("Index", new {page = x})) </div>
そしてチェック:

いいね!
言語を切り替える
クライアント部分にru / enスイッチを作成しましょう。 LangHelper.csクラス(/Helper/LangHelper.cs)を追加します。
public static class LangHelper { public static MvcHtmlString LangSwitcher(this UrlHelper url, string Name, RouteData routeData, string lang) { var liTagBuilder = new TagBuilder("li"); var aTagBuilder = new TagBuilder("a"); var routeValueDictionary = new RouteValueDictionary(routeData.Values); if (routeValueDictionary.ContainsKey("lang")) { if (routeData.Values["lang"] as string == lang) { liTagBuilder.AddCssClass("active"); } else { routeValueDictionary["lang"] = lang; } } aTagBuilder.MergeAttribute("href", url.RouteUrl(routeValueDictionary)); aTagBuilder.SetInnerText(Name); liTagBuilder.InnerHtml = aTagBuilder.ToString(); return new MvcHtmlString(liTagBuilder.ToString()); } }
_Layout.cshtmlにPartialを追加(/Areas/Default/Views/Shared/_Layout.cshtml):
<
div class="container"> <ul class="nav nav-pills pull-right"> @Html.Partial("LangMenu") </ul>
+ LangMenu.cshtml:
@Url.LangSwitcher("en", ViewContext.RouteData, "en") @Url.LangSwitcher("ru", ViewContext.RouteData, "ru")
始めます。 出来上がり! 美人

不正な形式、ロシア語への翻訳
予想される数値フィールドにテキスト値を入力すると、次のメッセージが表示される場合があります。
The value 'one hundred dollars' is not valid for Price.
しかし、このメッセージをロシア語で表示する方法。 これを行うには、次の手順が役立ちます。
- App_GlobalResourcesフォルダーを追加する
- Messages.resxリソースを追加する
- 「PropertyValueInvalid: 値{0}はフィールド{1}に対して無効です 」という行を追加します
- App_Startで、Application_Start()(/Global.asax.cs)に行を追加します
- DefaultModelBinder.ResourceClassKey = "Messages";
- Display [Name =” Price”]属性を使用して、フィールド名を指定できます。
- 結果が得られます。

まとめ
多言語サイトでの作業は次のとおりです。
- 翻訳文字列をリソースに分離する
- データベーステーブルで言語フィールドを定義し、言語テーブルを介してリンクします
- 言語サポートに基づいてajaxリクエストを使用する
結論として、多言語サイトを開始する価値はありません。顧客が明示的にそうしなければ、そのような機会が近い将来に使用される場合は、少なくともデータベースレベルで多言語を使用してサイトの構築を開始する必要があります。
すべてのソースは
https://bitbucket.org/chernikov/lessonsにあります