WebSurfer's Home

トップ > Blog 1   |   Login
Filter by APML

多言語対応カスタムコンロトール

by WebSurfer 6. December 2010 21:33

リソースファイルを用いて多言語対応させた 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 と同じ名前でフランス語の文字列を設定します。

フランス語(フランス)の場合の Resource.fr-FR.resx

今回の例に用いた 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 の違いなどについては、記事「カルチャの基本とカルチャ情報」が参考になりましたので、忘れないようにリンクを張っておきます。

Tags: , ,

Web Custom Control

About this blog

2010年5月にこのブログを立ち上げました。その後 ブログ2 を追加し、ここは ASP.NET 関係のトピックス、ブログ2はそれ以外のトピックスに分けました。

Calendar

<<  November 2019  >>
MoTuWeThFrSaSu
28293031123
45678910
11121314151617
18192021222324
2526272829301
2345678

View posts in large calendar