2015年1月19日月曜日

ASP.NET WebForms なアプリでの国際化対応

元々 ASP.NET は WebForms だろうと MVC だろうと、基本的には同じ方法で国際化対応ができますが、MSCC 向けアプリを作っている時に、WebForms の国際化対応がうまく行かなかったので忘れないように残しておきます。

グローバルリソースを使った方法では、アプリ単位でリソースを作成するため、一つのリソースにまとめて文言などを記載します。

image

このように、「キー」と「値」をペアに記載していくのが、文字のリソースとなります。これをロジックや UI 側で取得していくのが、国際化対応の基本となります。

image

aspx を利用している場合は Literal コントロールを利用したりして抽出する必要があります(コードから設定しない場合)。Validator の ErrorMessage などに設定する場合は直接以下のように記載します。

   1: ErrorMessage="<%$ Resources:MessageResource, ErrorAct1 %>">

Resources の後にリソースファイル名、その後にキー名を指定するだけです。

他にもアプリ全体、または国際化するページ単位で、カルチャの判定方法を追記します。ページ単位の場合は aspx 毎に culture = “auto” と uiCulture = “auto” と追記します。全体の場合は、下記の記述を web.config に追記します。


   1: <globalization culture="auto" uiCulture="auto" />

system.web エントリの要素として記述すると、アプリ全体でクライアントの言語設定を判定するようになります。

と、Web で検索していると大体ここまでで国際化対応できるようになるらしいのですが、自分の場合はこれだけではダメだったのと、どうしても一部 runat = “server” にするとうまくできなかったために、違う方法を組み合わせる必要がありました。

一つは Page の InitializeCulture メソッドをオーバーライドして、言語設定の情報を適用させることです。てっきり、Web.Config やらに記述したものがこれをやってくれるのだと思っていたのですが、何故か動かなかったので・・・。


   1: Protected Overrides Sub InitializeCulture()
   2:     Dim lang = Context.Request.UserLanguages(0)
   3:     Thread.CurrentThread.CurrentCulture = Globalization.CultureInfo.CreateSpecificCulture(lang)
   4:     Thread.CurrentThread.CurrentUICulture = Thread.CurrentThread.CurrentCulture
   5:     MyBase.InitializeCulture()
   6: End Sub

そしてもう一つが、先ほど runat = “server” ではないコントロールに対してリソースを適用しなくてはならなかったので、Reder メソッドをオーバーライドして書き換える処理でした。


   1: Protected Overrides Sub Render(writer As HtmlTextWriter)
   2:     Dim sb As StringBuilder = New StringBuilder
   3:     Dim sw As StringWriter = New StringWriter(sb)
   4:     Dim hWriter As HtmlTextWriter = New HtmlTextWriter(sw)
   5:     MyBase.Render(hWriter)
   6:     'runat≠server のリソース適用
   7:     Dim html = sb.ToString
   8:     Dim matches As MatchCollection = (New Regex("Localize\(([^\))]*)\)", (RegexOptions.Singleline Or RegexOptions.Compiled)).Matches(html))
   9:     For Each match As System.Text.RegularExpressions.Match In matches
  10:         html = html.Replace(match.Value, GetGlobalResourceObject("MessageResource", match.Groups(1).Value).ToString)
  11:     Next
  12:     writer.Write(html)
  13: End Sub

何か、他にちゃんとしたやり方がありそうな気もしますが、とりあえず自分の場合はこれらのやり方で国際化対応ができました。

0 件のコメント:

コメントを投稿