MVC 2完党なロヌカリれヌションガむド

画像 この蚘事では、ASP.NET MVCに基づいおWebアプリケヌションをロヌカラむズするすべおの偎面を怜蚎したす。 このトピックの執筆時点では、最新のMVC 2 RC 2バヌゞョンを䜿甚しおいたす。

始める前に、MVCチヌムに感謝したいず思いたす。すばらしい仕事をしおくれた皆さん、このフレヌムワヌクを䜿甚するずきにWebアプリケヌションを䜜成するプロセスを楜しんでいたす。 Ruby on Railsで少し経隓した埌、このタむプのフレヌムワヌクを探しおいたした。

次の問題を怜蚎したす。
  1. 怜蚌を衚瀺
  2. シンプルな䜜物切り替えメカニズム
  3. モデル怜蚌メッセヌゞのロヌカラむズ
  4. DisplayName属性のロヌカラむズ
  5. キャッシュずロヌカリれヌション
䜜業するには、Visual Studio 2008 ExpressずASP.NET MVC 2 RC2が必芁です。たた、新しいMVC 2 Webプロゞェクトを䜜成する必芁がありたす。

ロヌカラむズを衚瀺


もちろん、ロヌカラむズされたテキストの堎合、リ゜ヌスファむルが䜿甚されたすが、ストレヌゞには暙準のasp.netフォルダヌは䜿甚されたせん。

次のディレクトリ構造をお勧めしたす。

画像

ビュヌ -aspxペヌゞのリ゜ヌスファむル。 モデル -ビュヌモデルをロヌカラむズするためのリ゜ヌスファむル。

Viewsディレクトリには、リ゜ヌスファむルが配眮されおいる各コントロヌラヌのサブフォルダヌが含たれおいたすファむルの数は、サポヌトされおいる蚀語のセットによっお異なりたす。

モデルには、ビュヌモデルの各グルヌプのサブディレクトリが含たれたす。 生成されたアカりントモデルLogOn、Register、ChangePasswordには、各蚀語カルチャのAccountフォルダヌずリ゜ヌスファむルがありたす。

リ゜ヌスファむル


リ゜ヌスファむルの呜名芏則に関するいく぀かの蚀葉。 リ゜ヌスファむルの名前の圢匏は次のずおりです。
[リ゜ヌス名]。[文化] .resx

リ゜ヌス名-ファむル名。 絶察に䜕でも構いたせん。 同じリ゜ヌス名を持぀耇数のリ゜ヌスファむルがある堎合にグルヌプ化するために䜿甚されたす-それらはCULTUREで指定された異なるカルチャを持぀単䞀のリ゜ヌスを構成したす。

CULTURE-リ゜ヌスファむルカルチャのむンゞケヌタ。 文化には、 䞭立ず正確の 2぀のタむプがありたす。 ニュヌトラルカルチャは、蚀語コヌド en 、 ru 、 deなどのみで構成されたす。 正確なカルチャは、蚀語コヌドず地域コヌドで構成されたす en-US 、 en-UK 

たた、カルチャが定矩されおいないリ゜ヌスファむルには特別な意味があり、「デフォルト」たたは「フォヌルバック」カルチャず呌ばれたす。 名前から掚枬できるように、特定のカルチャリ゜ヌスファむルでテキストが芋぀からなかった堎合、たたは特定のカルチャのファむルがない堎合、リ゜ヌスファむルに䜿甚されたす。 特にナヌザヌがサポヌトされおいないカルチャを䜕らかの方法でむンストヌルできる堎合は、基本的なリ゜ヌスファむルを䜿甚するこずを匷くお勧めしたす。

リ゜ヌスファむルのいく぀かの䟋

MyStrings.en-US.resx-英語アメリカ

MyStrings.en-UK.resx-むギリス英語

MyStrings.en.resx-ニュヌトラル英語英語のデフォルト

MyStrings.ru.resx-䞭立ロシア語

MyStrings.resxはベヌスリ゜ヌスファむルです。

これで、䜕かをロヌカラむズしお、それがどのように機胜するかを確認する準備ができたした。 䜜成されたWebアプリケヌションでのヘッダヌのロヌカラむズの小さな䟋を瀺したす。 この䟋では、英語デフォルトず䞭立ロシア語の2぀の蚀語を䜿甚したすが、他の蚀語も䜿甚できたす。

たず、フォルダヌ構造を䜜成したす。䞊蚘で説明したように、Site.Masterの芪ペヌゞのリ゜ヌスファむルが必芁になりたす。 Resources \ Viewsに 共有ディレクトリを䜜成し、2぀のリ゜ヌスファむルを远加したす。

SharedStrings.resx-英語のデヌタを含む基本的なリ゜ヌスファむル。

SharedStrings.ru.resx-ロシア語のデヌタを含む基本的なリ゜ヌスファむル。

䞡方のファむルに「タむトル」プロパティを远加しお入力したす。

画像

重芁 各リ゜ヌスファむルのアクセス修食子がpublicに蚭定されおいるこずを確認したす。 たた、リ゜ヌスツヌルにPublicResXFileCodeGeneratorのカスタムツヌルプロパティ倀があるこずを確認したす。 そうしないず、リ゜ヌスファむルはコンパむルされず、利甚できたせん。

画像

画像

リ゜ヌスファむルの名前空間に぀いお少し説明したす。 この方法で䜜成されたファむルには、次の圢匏の名前空間がありたす。

[プロゞェクト名] .Resources.Views.Shared

読みやすさず呜名芏則ぞの準拠を改善するために、リ゜ヌスファむルのカスタムツヌル名前空間プロパティをViewRes ビュヌリ゜ヌスファむル甚に倉曎したした。

Site.Masterペヌゞに倉曎を加えるずきが来たした。

< div id ="title" >

< h1 > My MVC Application </ h1 >
</ div >
に眮き換える
< div id ="title" >

< h1 > <% =ViewRes.SharedStrings.Title %> </ h1 >

</ div >

アプリケヌションを実行しお、すべおが正垞に機胜し、ヘッダヌが正しい堎所に衚瀺されるこずを確認したすリ゜ヌスファむルから読み取る必芁がありたす。 すべおがうたくいったら、文化を倉える方法を瀺したしょう。

カルチャを倉曎するには、リク゚ストごずに CurrentThreadオブゞェクトのCurrentCultureおよびCurrentUICultureプロパティを倉曎する必芁がありたす!!! これを行うには、カルチャを倉曎するコヌドをApplication_AcquireRequestState Global.asaxメ゜ッドに配眮したすこのメ゜ッドはむベントハンドラヌであり、リク゚ストごずに呌び出されたす

Global.asax.csファむルに次のコヌドを远加したす。
protected void Application_AcquireRequestState( object sender, EventArgs e)
{
//Create culture info object
CultureInfo ci = new CultureInfo( "en" );

System.Threading.Thread.CurrentThread.CurrentUICulture = ci;
System.Threading.Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(ci.Name);
}


アプリケヌションを再床起動し、機胜するこずを確認したす。 次に、CulturInfoコンストラクタヌの文字列パラメヌタヌを倉曎し私の堎合は「ru」になりたす、プロゞェクトを再起動したす。 次のものが必芁です。

画像

画像

以䞊です。 Site.Masterヘッダヌをロヌカラむズしたため、任意のテキストでこれを行うこずができたす。

シンプルな䜜物切り替えメカニズム


前の章では、アプリケヌションタむトルのロヌカラむズに成功したしたが、リアルタむムでカルチャを倉曎する方法はありたせんでした。 次に、文化的環境をリアルタむムで制埡するのに圹立぀䜕らかのメカニズムを䜜成したす。

ナヌザヌが遞択したカルチャのリポゞトリ、セッションオブゞェクトを䜿甚したす。 文化を倉えるために、各蚀語のリンクをマスタヌペヌゞに配眮したす。 リンクをクリックするず、アカりントコントロヌラヌでアクションが発生し、セッション倀が適切なカルチャに倉曎されたす。

次のコヌドをAccountControllerクラスに远加したす。
public ActionResult ChangeCulture( string lang, string returnUrl)
{
Session[ "Culture" ] = new CultureInfo(lang);
return Redirect(returnUrl);
}

これで、2぀のパラメヌタヌを持぀アクションメ゜ッドが䜜成されたした。1぀目はカルチャコヌド、2぀目はナヌザヌを元のペヌゞにリダむレクトするためのアドレスです。 セッションコレクションに新しいカルチャを蚭定する必芁がありたすが、サポヌトされおいないカルチャのむンストヌルを防ぐために、受信したナヌザヌデヌタのチェックを远加するこずを忘れないでください。

次に、文化的な参照を含む単玔なナヌザヌコントロヌルを䜜成したす。 Views \ Sharedディレクトリに新しい郚分ビュヌを远加し、ファむルにCultureChooserUserControl.ascxずいう名前を付けお、次のファむルを貌り付けたす。
<% = Html.ActionLink( "English" , "ChangeCulture" , "Account" ,
new { lang = "en" , returnUrl = this .Request.RawUrl }, null ) %>
<% = Html.ActionLink( "" , "ChangeCulture" , "Account" ,
new { lang = "ru" , returnUrl = this .Request.RawUrl }, null ) %>


そこで、2぀のリンクを䜜成したした。1぀は英語甚で、2぀目はロシア語甚です。 Site.Materペヌゞにこのコントロヌルを配眮するずきが来たした。 ログむンフォヌムの暪に远加したす。

<div id = "logindisplay">コヌドを芋぀けお次のコヌドに眮き換えたす。
< div id ="logindisplay" >
<% Html.RenderPartial( "LogOnUserControl" ); %>
<% Html.RenderPartial( "CultureChooserUserControl" ); %>
</ div >

他に䜕をする必芁がありたすか そしお、最も重芁なこずは残っおいたす。私たちは文化に関する情報のオブゞェクトをセッションに配眮したすが、それをどこにも䜿甚したせん。 Global.asax.csファむルメ゜ッドApplication_AcquireRequestStateを再床倉曎したす。
protected void Application_AcquireRequestState( object sender, EventArgs e)
{
//
if ( HttpContext .Current.Session != null )
{
CultureInfo ci = (CultureInfo) this .Session[ "Culture" ];
// ,
//
//
if (ci == null )
{
// -
string langName = "en" ;
// HTTP
if ( HttpContext .Current.Request.UserLanguages != null && HttpContext .Current.Request.UserLanguages.Length != 0)
{
//
langName = HttpContext .Current.Request.UserLanguages[0].Substring(0, 2);
}
ci = new CultureInfo(langName);
this .Session[ "Culture" ] = ci;
}
//
Thread.CurrentThread.CurrentUICulture = ci;
Thread.CurrentThread.CurrentCulture = CultureInfo.CreateSpecificCulture(ci.Name);
}
}

アプリケヌションを起動するず、次のペヌゞが衚瀺されたす。リンクをクリックするず、遞択したカルチャでペヌゞがオヌバヌロヌドされたす。

画像

モデル怜蚌メッセヌゞのロヌカラむズ


Phil Haackが発行したこの問題に察する優れた解決策を芋぀けたしたが、この蚘事は完党なガむドであるため、この問題に觊れざるを埗ず、明確にしたい特定の曖昧さもありたす。 しかし、たず第䞀に、 Phil Haackの投皿を読むこずをお勧めしたす

アカりントモデル、特にRegistrationModelの怜蚌メッセヌゞをロヌカラむズする方法を説明したす。 たた、AccountControllerコヌドに盎接蚘述されたメンバヌシップ怜蚌メッセヌゞをロヌカラむズする方法に぀いおも説明したす。

そこで、 Resources \ Models \ AccountフォルダヌにValidationStrings.resxずValidationStrings.ru.resxを䜜成したしょうアクセス修食子がパブリックであるこずを確認しおください。 ご想像のずおり、これらのファむルに怜蚌メッセヌゞを保存したす。

䞡方のファむルに次のプロパティを䜜成したした英語の䟋

画像

モデルを次のように倉曎する必芁がありたすRegisterModelの䟋
[PropertiesMustMatch( "Password" , "ConfirmPassword" ,
ErrorMessageResourceName = "PasswordsMustMatch" ,
ErrorMessageResourceType = typeof (ValidationStrings))]
public class RegisterModel
{
[Required(ErrorMessageResourceName = "Required" , ErrorMessageResourceType = typeof (ValidationStrings))]
[DisplayName( "Username" )]
public string UserName { get ; set ; }
[Required(ErrorMessageResourceName = "Required" , ErrorMessageResourceType = typeof (ValidationStrings))]
[DataType(DataType.EmailAddress)]
[DisplayName( "Email" )]

public string Email { get ; set ; }
[Required(ErrorMessageResourceName = "Required" , ErrorMessageResourceType = typeof (ValidationStrings))]
[ValidatePasswordLength(ErrorMessageResourceName = "PasswordMinLength" ,ErrorMessageResourceType = typeof (ValidationStrings))]
[DataType(DataType.Password)]
[DisplayName( "Password" )]
public string Password { get ; set ; }

[Required(ErrorMessageResourceName = "Required" , ErrorMessageResourceType = typeof (ValidationStrings))]
[DataType(DataType.Password)]
[DisplayName( "Confirm password" )]
public string ConfirmPassword { get ; set ; }
}

ErrorMessageResourceNameプロパティずErrorMessageResourceTypeプロパティをRequired 、 PropertiesMustMatch、 ValidatePasswordLength属性に远加したす。ここで、 ErrorMessageResourceTypeはメッセヌゞが保存されるリ゜ヌスクラスのタむプで、 ErrorMessageResourceNameはプロパティの名前です。 残念ながら、プロパティを読み取るための厳密に型指定されたバヌゞョンはありたせん。したがっお、これらの魔法の行が正しい倀を持っおいるこずを確認しおください。

私たちはほずんどそこにいたす、詳现はただ残っおいたす。 独自の怜蚌属性PropertiesMustMatchAttributeおよびValidatePasswordLenghtAttributeが2぀あり、 FormatErrorMessageメ゜ッドのCultureInfo.CurrentUICultureをCultureInfo.CurrentCultureに倉曎する必芁がありたす。倉曎しない堎合、䜕も機胜したせん。

アプリケヌションを起動し、登録ペヌゞに移動し、カルチャを倉曎するための蚀語を遞択し、空のフォヌムを送信するずきにおよそ以䞋を取埗したす。

画像

ああ、お気づきのように、プレれンテヌションモデルのプロパティ名をロヌカラむズするのを忘れお、少し混乱したした。 これを行うには、DisplayName属性の倀をロヌカラむズする必芁がありたすが、それは䞀芋したほど簡単ではありたせん。 これに぀いおは次の章で説明したすが、残りの詳现は終了したしょう。 これは、Membership APIの怜蚌メッセヌゞのロヌカラむズです。

AccountControllerを開いおファむルの末尟に移動するず、ErrorCodeToStringメ゜ッドが存圚するはずです。このメ゜ッドは、ナヌザヌ登録が倱敗した堎合に゚ラヌメッセヌゞを䜜成したす。 すべおのメッセヌゞはコヌドにハヌドコヌディングされおいたす。 必芁なのは、既に䜜成されたValidationStringsリ゜ヌスファむル内の各メッセヌゞに適切なプロパティを䜜成し、ErrorCodeToStringメ゜ッド内のテキストの代わりにそれらを配眮するこずだけです。

怜蚌モデルはこれですべおです。 DisplayNameの時間です

DisplayName属性のロヌカラむズ


前の章で述べたように、DisplayName倀は、フォヌマットにパラメヌタヌを䜿甚する怜蚌メッセヌゞに含たれたす。 DisplayName属性に぀いお考えるもう1぀の理由は、HTMLフォヌムのテキストフィヌルドラベルです。これらはDisplayName倀の参加によっお䜜成されたす。

本圓の問題は、DisplayNameがロヌカラむズをサポヌトしおいないこずです。これは、倀を取埗する堎所からリ゜ヌスファむルに関連付ける方法がありたせん。

これは、DisplayNameAttributeを拡匵し、DisplayNameプロパティを曞き換えお、ロヌカラむズされた名前を返す必芁があるこずを意味したす。 継承クラスを䜜成し、LocalizedDisplayNameず呌びたした。
public class LocalizedDisplayNameAttribute : DisplayNameAttribute
{
private PropertyInfo _nameProperty;
private Type _resourceType;

public LocalizedDisplayNameAttribute( string displayNameKey)
: base (displayNameKey)
{

}

public Type NameResourceType
{
get
{
return _resourceType;
}
set
{
_resourceType = value ;
// nameProperty, set'
_nameProperty = _resourceType.GetProperty( base .DisplayName, BindingFlags.Static | BindingFlags.Public);
}
}

public override string DisplayName
{
get
{
//,nameProperty null
if (_nameProperty == null )
{
return base .DisplayName;
}

return ( string )_nameProperty.GetValue(_nameProperty.DeclaringType, null );
}
}
}

重芁な詳现は、芁求されるたびにプロパティの倀を読み取る必芁があるずいう理解です。したがっお、GetValueメ゜ッドは、コンストラクタヌではなくDisplayNameプロパティのget'erで呌び出されたす。

衚瀺名を保存するために、 Resources \ Models \ AccountフォルダヌにNames.resxおよびNames.ru.resxリ゜ヌスファむルを䜜成し、次のプロパティを䜜成したした。

画像

次に、DisplayName属性をLocalizedDisplayNameに眮き換えお、リ゜ヌスクラスのタむプを指定する必芁がありたす。 倉曎されたRegisterModelコヌドは次のようになりたす。
[PropertiesMustMatch( "Password" , "ConfirmPassword" ,
ErrorMessageResourceName = "PasswordsMustMatch" ,
ErrorMessageResourceType = typeof (ValidationStrings))]
public class RegisterModel
{
[Required(ErrorMessageResourceName = "Required" , ErrorMessageResourceType = typeof (ValidationStrings))]
[LocalizedDisplayName( "RegUsername" , NameResourceType = typeof (Names))]
public string UserName { get ; set ; }

[Required(ErrorMessageResourceName = "Required" ,ErrorMessageResourceType = typeof (ValidationStrings))]
[DataType(DataType.EmailAddress)]
[LocalizedDisplayName( "RegEmail" , NameResourceType = typeof (Names))]
public string Email { get ; set ; }

[Required(ErrorMessageResourceName = "Required" , ErrorMessageResourceType = typeof (ValidationStrings))]
[ValidatePasswordLength(ErrorMessageResourceName = "PasswordMinLength" ,
ErrorMessageResourceType = typeof (ValidationStrings))]
[DataType(DataType.Password)]
[LocalizedDisplayName( "RegPassword" , NameResourceType = typeof (Names))]
public string Password { get ; set ; }

[Required(ErrorMessageResourceName = "Required" , ErrorMessageResourceType = typeof (ValidationStrings))]
[DataType(DataType.Password)]
[LocalizedDisplayName( "RegConfirmPassword" , NameResourceType = typeof (Names))]
public string ConfirmPassword { get ; set ; }

}

* This source code was highlighted with Source Code Highlighter .

アプリケヌションを実行し、動䜜しおいるこずを確認しおください。次のようになりたす。

画像

キャッシュずロヌカリれヌション


奇劙な章ですよね キャッシングずロヌカリれヌションを組み合わせる方法を考えおいたすか OK、次のシナリオを想像しおみたしょう。HomeControllerを開き、OutputCache属性をIndexアクションメ゜ッドに远加したす。
[OutputCache(Duration=3600, VaryByParam= "none" )]
public ActionResult Index()
{
ViewData[ "Message" ] = "Welcome to ASP.NET MVC!" ;

return View();
}

アプリケヌションを起動し、[むンデックス]ペヌゞで蚀語を倉曎しお、ヘッダヌがただロヌカラむズされおいるこずを確認したす。

なんおこった キャッシングずロヌカリれヌションを䞀緒に䜿甚するこずはできないずお考えですか 心配しないでください、この問題の解決策が存圚したす:)

OutputCacheに぀いお䜕を知っおいたすか、VaryByCustomプロパティに぀いお䜕を知っおいたすか それを䜿甚する時間です。

むンデックスペヌゞを初めお芁求するず、OutputCacheがペヌゞをキャッシュしたす。 2番目のリク゚スト蚀語遞択リンクをクリックしたずきで、OutputCacheは䜕も倉曎されおいないず刀断し、キャッシュから結果を返すため、ペヌゞは再䜜成されたせん。 そのため、蚀語の遞択が機胜したせんでした。 この問題を解決するには、ペヌゞのバヌゞョンが倉曎されたこずを䜕らかの方法でOutputCacheに䌝える必芁がありたすアクションが特定のパラメヌタヌを受け取り、VaryByParamプロパティに枡す堎合など。

VaryByCustomはこの問題の解決策の理想的な候補であり、Global.asax.csファむルのSystem.Web.HttpApplicationクラスに特別なメ゜ッドがありたす。 このメ゜ッドの暙準実装を曞き盎したす。
public override string GetVaryByCustomString( HttpContext context, string value )
{
if ( value .Equals( "lang" ))
{
return Thread.CurrentThread.CurrentUICulture.Name;
}
return base .GetVaryByCustomString(context, value );
}

たず、このメ゜ッドはパラメヌタヌ倀が「lang」特別な倀なし、VaryByCustomの倀ずしお䜿甚される単玔な文字列に䞀臎するかどうかを確認し、䞀臎する堎合は珟圚のカルチャの名前を返したす。 それ以倖の堎合は、暙準実装の倀を返したす。

次に、ロヌカラむズを䜿甚する各OutputCache属性に倀「lang」を持぀VaryByCustomプロパティを远加したす。これがすべおです。 曎新されたむンデックスアクションメ゜ッドは次のずおりです。

[OutputCache(Duration=3600,VaryByParam= "none" , VaryByCustom= "lang" )]
public ActionResult Index()
{
ViewData[ "Message" ] = "Welcome to ASP.NET MVC!" ;
return View();
}

もう䞀床アプリケヌションを実行しおみお、䜜業の切り替えを楜しんでください。

最埌の章は終わりたしたが、䜕も芋逃しおいないこずを願っおいたす。

Source: https://habr.com/ru/post/J86331/


All Articles