リソースファイルを用いて多言語対応させた Web カスタムコントロールの話です。
Culture, UICulture の値として "auto" を設定した場合には、ASP.NET がリクエスト情報に含まれる Accept-Language ヘッダの内容から判断して、自動的にカルチャを特定してくれます。
上の画像は、IE8 で言語をフランス語(フランス) fr-FR に設定してページを要求した結果、サーバー側でカルチャが fr-FR と判断され、カスタムコントロールのリソースファイル Resource.fr-FR.resx に定義されたフランス語のリソース(今回の例では、文字列 Adresse e-mail, Enregister)が表示されたものです。
この例に使ったカスタムコントロールの構成は以下の通りです。リソースの基になるのが Resource.resx で、これはソリューションエクスプローラ上で手動で追加します。その下の Resource.Designer.cs は「厳密に型指定されたリソースクラス」というもので、Resource.resx を追加すると自動生成されます。
Resource.resx にはデフォルトのリソースを定義します。今回の例では、下の画像に示すように LabelText, ButtonText という名前の 2 つの文字列です。要求されたカルチャのリソースファイルがない場合(この例では en-US, fr-FR, ja-JP 以外が指定された場合)、Resource.resx に定義されたリソースが使われます。
Resource.Designer.cs には Resource という名前のクラスが定義され、その中にカルチャを設定する Culture 静的プロパティ、ローカライズされたリソースを取得する静的プロパティ(この例では Resource.resx で設定した LabelText, ButtonText と同じ名前のプロパティ)が定義されます。
ローカライズされたリソースは個別のリソースファイルを追加して定義します。例えば、フランス語(フランス)の場合は Resource.fr-FR.resx という名前のリソースファイルを追加し、以下の画像のように Resource.resx で設定した LabelText, ButtonText と同じ名前でフランス語の文字列を設定します。
今回の例に用いた MyServerControl.cs の内容は以下の通りです。以下のコードで、Resource というのが Resource.Designer.cs で定義される「厳密に型指定されたリソースクラス」です。
Resource.Culture 静的プロパティで現在のカルチャを設定し、設定されたカルチャのリソースファイルからローカライズされた文字列を、Resource.LabelText, Resource.ButtonText 静的プロパティを用いて取得しています。
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Threading;
using System.Globalization;
namespace MultiLanguageServerControl
{
public class MyServerControl : WebControl
{
public virtual string LabelText
{
get
{
string s = (string)ViewState["LabelText"];
if (s == null)
{
Resource.Culture = Thread.CurrentThread.CurrentUICulture;
s = Resource.LabelText;
}
return s;
}
set
{
ViewState["LabelText"] = value;
}
}
public virtual string ButtonText
{
get
{
string s = (string)ViewState["ButtonText"];
if (s == null)
{
Resource.Culture =
Thread.CurrentThread.CurrentUICulture;
s = Resource.ButtonText;
}
return s;
}
set
{
ViewState["ButtonText"] = value;
}
}
protected override HtmlTextWriterTag TagKey
{
get
{
return HtmlTextWriterTag.Table;
}
}
protected override void RenderContents(HtmlTextWriter writer)
{
StringBuilder sb = new StringBuilder();
sb.AppendLine("<tr>");
sb.AppendFormat("<td><span id=\"Label1\">{0}</span></td>",
LabelText);
sb.Append("<td><input type=\"text\" id=\"TextBox1\" /></td>");
sb.AppendFormat(
"<td><input type=\"submit\" value=\"{0}\" id=\"Button1\" /></td>",
ButtonText);
sb.AppendLine("</tr>");
writer.Write(sb.ToString());
}
}
}
このソリューションをビルドすると、以下のような dll が生成されます。この MultiLanguageServerControl.dll と en-US, fr-FR, ja-JP フォルダを中身ごと Web アプリケーションの Bin フォルダにコピーします。
aspx ページでは以下のように Culture, UICulture を "auto" に設定し、ブラウザの言語を希望の言語(今回の例では、ja-JP または en-US または fr-FR)に設定してページを要求すれば、当該リソースファイルからローカライズされた文字列が取得されます。例えば fr-FR とすれば、一番上の画像のように表示されます。(設定を忘れるとどうなるかは、この記事の下の方の「2016/6/17 追記」を見てください)
<%@ Page Language="C#" Culture="auto" UICulture="auto" %>
<%@ Import Namespace="System.Globalization" %>
<%@ Import Namespace="System.Threading" %>
<%@ Register Assembly="MultiLanguageServerControl"
Namespace="MultiLanguageServerControl"
TagPrefix="cc2" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<script runat="server">
protected void Page_Load(object sender, EventArgs e)
{
CultureInfo ci = Thread.CurrentThread.CurrentUICulture;
Label1.Text = "現在の CultureInfo: " + ci.ToString();
}
</script>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Label ID="Label1" runat="server" />
<br /><br />
<cc2:MyServerControl runat="server" />
</div>
</form>
</body>
</html>
aspx ページ本体の多言語化の話は別途・・・というより、@IT の記事 リソース・ファイル活用で国際化対応ページを構築するには? を見たほうが早いかも。
-------- 2016/6/17 追記 --------
Culture, UICulture を "auto" に設定すると、ASP.NET は、ブラウザから送信されてくる要求ヘッダに含まれる Accept-Language の設定を調べて、その要求を処理するスレッドのカルチャを Accept-Language に設定されているカルチャに書き換えるようです。
そして、実行時に、リソースマネージャが要求を処理しているスレッドのカルチャ情報を参照してローカライズされたリソースを検索し、UI に表示されるテキストを取得するという仕組みになっています。
Culture, UICulture を "auto" に設定するのを忘れるとブラウザの言語設定は無視されます。デフォルトではシステムのロケールに該当するカルチャがスレッドに設定されますので、例えば日本語 OS で xxx.ja-JP.resx というリソースがあれば、常にそれから UI に表示されるテキストを取得します。
Web サイトが日本語専用でサーバーも日本にあれば忘れても問題ないかもしれませんが、ホスティングサービス(Azure も含む)でサーバーが外国にある場合は Culture, UICulture を "auto" に設定するのを忘れると問題が出ると思います。
ロケール、カルチャ、Culture と UICulture の違いなどについては、記事「カルチャの基本とカルチャ情報」が参考になりましたので、忘れないようにリンクを張っておきます。