SeamFramework.org Community Documentation

- 前のページ
- 次のページ

## 第16章 国際化と地域化およびテーマ

Seam では容易に国際化されたアプリケーションを作成できます。 まず、 アプリケーションの国際化および地域化に必要とされるすべての段階について見ていきます。 そのあと Seam が同梱するコンポーネントの説明をします。

## 16.1. アプリケーションを国際化する

JEE アプリケーションは数多くのコンポーネントから構成され、 それらのコンポーネントすべてがローカライズを行うアプリケーションに対して正しく設定されていなければなりません。

最初から始めることにします。 1 番目の手順としてデータベースのサーバーとクライアントが使用するロケールに対応する正しい文字エンコーディングを使用していることを確認します。 UTF-8 を使用するのが全般的には多くなります。 この方法については本チュートリアルの範囲外となります。

### 16.1.1. アプリケーションサーバーの設定

アプリケーションサーバーが要求パラメータを正しいエンコーディングでクライアントの要求から受け取るようにするには、 tomcat コネクタを設定する必要があります。 Tomcat または JBoss AS を使用する場合は `URIEncoding="UTF-8"` 属性をコネクタの設定に追加します。 JBoss AS 4.2 なら `${JBOSS_HOME}/server/(default)/deploy/jboss-web.deployer/server.xml` を変更します。

    <Connector port="8080" URIEncoding="UTF-8"/>

別の方法もあり、 こちらの方がよいでしょう。 JBoss AS に要求パラメータのエンコーディングはその要求から取得されることを指示することができます。

    <Connector port="8080" useBodyEncodingForURI="true"/>

### 16.1.2. 翻訳されたアプリケーション文字列

アプリケーションのすべての メッセージ にも翻訳された文字列が必要となります (例、 ビューのフィールドラベルなど)。 まず、 リソースバンドルが目的の文字エンコーディングを使ってコード化されることを確認する必要があります。 デフォルトでは ASCII が使用されます。 ASCII は多くの言語に十分対応しますが、 すべての言語の文字を提供しているわけではありません。

リソースバンドルは ASCII で作成されなければなりません。 あるいは Unicode 文字の表示に Unicode エスケープのコードを使用します。 バイトコードに対してプロパティファイルをコンパイルしないため使用にセットする文字を JVM に伝える方法がありません。 このため、 ASCII 文字または ASCII 文字にはないエスケープ文字を使用しなければなりません。 \uXXXX を使用するといずれの Java ファイルでも Unicode 文字を表すことができます。 XXXX はその文字を表す 16 進数です。

ネイティブエンコーディングでメッセージのリソースバンドルにラベル (<xlink>ラベル</xlink>) の翻訳を書き込みそのファイルの内容を JDK で提供される `native2ascii` ツールでエスケープ形式に変換することができます。 このツールはネイティブエンコーディングで記述されたファイルを Unicode エスケープ配列として非 ASCII 文字で表すものに変換します。

このツールの使い方は Java 5 の場合はここ または Java 6 の場合はここ に記載されています。 たとえば、 あるファイルを UTF-8 から変換するには次のようにします。

    $ native2ascii -encoding UTF-8 messages_cs.properties > messages_cs_escaped.properties

### 16.1.3. その他のエンコーディング設定

正しい文字セットを使ってローカライズされたデータとメッセージが表示されること、 そしてサブミットされるデータがすべて正しいエンコーディングを使用することを確認する必要があります。

表示文字のエンコーディングを設定するには `<f:view locale="cs_CZ"/>` タグを使用する必要があります (ここでは JSF にチェコ語を使用するよう指示している)。 xml にローカライズされた文字列を埋め込む場合は xml ドキュメント自体のエンコーディングを変更したいことがあります。 これを行うには xml 宣言の `<?xml version="1.0" encoding="UTF-8"?>` で必要に応じてエンコーディング属性を変更します。

また、 JSF や Facelet は指定文字エンコーディングを使った要求をサブミットするはずですが、 エンコーディングを指定していない場合は強制的にサーブレットフィルタを使うようにすることができます。 `components.xml` で設定します。

    <web:character-encoding-filter encoding="UTF-8"

       override-client="true"

       url-pattern="*.seam" />

## 16.2. ロケール

各ユーザーログインのセッションは、 `java.util.Locale` インスタンスと関連しています (アプリケーションでは、 `locale` という名前のコンポーネントとして扱えます)。 通常の環境では、 ロケールのための特別な設定は不要です。 Seam ではアクティブなロケールの決定は単純に JSF に委譲しています。

- HTTP 要求で指定されるロケール (ブラウザのロケール) があり、 そして、 `faces-config.xml` により対応可能なロケールの組み合わせの中にそのロケールがある場合、 その後のセッションの期間、そのロケールを使用します。

- それ以外で、デフォルトロケールが `faces-config.xml` 中に指定されていれば、 その後のセッションの期間、そのロケールを使用します。

- それ以外では、サーバのデフォルトロケールを使用します。

Seam 設定プロパティの `org.jboss.seam.international.localeSelector.language`、 `org.jboss.seam.international.localeSelector.country` そして `org.jboss.seam.international.localeSelector.variant` によりマニュアルでのロケール設定が 可能 ですが、 これを行う妥当な理由は考え付きません。

しかし、アプリケーションユーザーインタフェースを通じて、 ユーザーにマニュアルでロケール設定を可能とさせることは有用です。 Seam は上記のアルゴリズムによって決定されるロケールをオーバライドする組み込み機能も提供しています。 すべきことは、JSP または、Facelet ページのフォームに以下の断片を追加するだけです。

    <h:selectOneMenu value="#{localeSelector.language}">

        <f:selectItem itemLabel="English" itemValue="en"/>

        <f:selectItem itemLabel="Deutsch" itemValue="de"/>

        <f:selectItem itemLabel="Francais" itemValue="fr"/>

    </h:selectOneMenu>

    <h:commandButton action="#{localeSelector.select}"

        value="#{messages['ChangeLanguage']}"/>

あるいは、`faces-config.xml` に対応されたすべてのロケールの組み合わせが欲しければ、 以下を使ってください。

    <h:selectOneMenu value="#{localeSelector.localeString}">

        <f:selectItems value="#{localeSelector.supportedLocales}"/>

    </h:selectOneMenu>

    <h:commandButton action="#{localeSelector.select}"

        value="#{messages['ChangeLanguage']}"/>

ユーザーがドロップダウンからアイテムを選択してコマンドボタンをクリックすると、 その後のセッションに対して Seam と JSF のロケールはオーバライドされます。

これにより対応ロケールはどこで定義するのだろうかという疑問が湧いてきます。 一般的には JSF 設定ファイル (/META-INF/faces-config.xml) の `<locale-config>` 要素でリソースバンドルに一致するロケール一覧を与えます。 ただし、 Seam のコンポーネント設定のメカニズムは Java EE 提供のそれよりずっとパワフルであることを学んできました。 こうした理由から `org.jboss.seam.international.localeConfig` という名前の組み込みコンポーネントを使用して対応ロケールおよびサーバーのデフォルトロケールを設定することができます。 これを使うにはまず Seam コンポーネント記述子で Seam の国際パッケージ用の XML 名前空間を宣言します。 次にデフォルトのロケールと対応ロケールを次のように定義します。

    <international:locale-config default-locale="fr_CA" supported-locales="en fr_CA fr_FR"/>

必然的にロケールをサポートすることを宣言する場合、 一致するリソースバンドルを与えた方がよいでしょう。 次は言語固有のラベルの定義方法について説明します。

## 16.3. ラベル

JSF は、ユーザーインタフェースのラベルや説明用テキストの国際化を、 `<f:loadBundle />` を使用することによって対応しています。 Seam アプリケーションでもこのアプローチが使用可能です。 代わりに、組み込みの EL 式を利用したテンプレート化ラベルの表示に、 Seam `messages` コンポーネントを利用することも可能です。

### 16.3.1. ラベルを定義する

Seam は `java.util.ResourceBundle` を提供しています (アプリケーションでは `org.jboss.seam.core.resourceBundle` として利用可能)。 この特殊リソースバンドルを通じて国際化されたラベルを使用可能にする必要があります。 デフォルトでは、 Seam で使用されるリソースバンドルは `messages` の名称なので `messages.properties`、 `messages_en.properties`、 `messages_en_AU.properties` などの名称のファイルにラベルを定義する必要があります。 これらのファイルは通常 `WEB-INF/classes` ディレクトリに属します。

従って、`messages_en.properties` では、

    Hello=Hello

そして、`messages_en_AU.properties` では、

    Hello=G'day

`org.jboss.seam.core.resourceLoader.bundleNames` と呼ばれる Seam 設定プロパティによって、 リソースバンドルとして異なる名前を選択することが可能です。 リソースバンドル名の一覧を指定してメッセージの検索をさせる (深さ優先) こともできます。

    <core:resource-loader>

        <core:bundle-names>

            <value>mycompany_messages</value>

            <value>standard_messages</value>

        </core:bundle-names>

    </core:resource-loader>

特定のページだけにメッセージを定義したいのであれば、 そのJSFビューIDと同じ名前でリソースバンドルに指定します。 このときIDの最初の `/` と最後の拡張子を除去します。 つまり `/welcome/hello.jsp` にのみメッセージを表示したいのであれば、 表示させるメッセージを `welcome/hello_en.properties` に配置します。

`pages.xml` に明示的なバンドル名を指定することもできます。

    <page view-id="/welcome/hello.jsp" bundle="HelloMessages"/>

これで `HelloMessages.properties` に定義されたメッセージを `/welcome/hello.jsp` で使うことができます。

### 16.3.2. ラベルを表示する

もし、Seamのリソースバンドルを使ってラベルを定義する場合、 各ページそれぞれに `<f:loadBundle ... />` を入力しなくてもこれを使用することができます。 代わりに単に以下のように入力します。

    <h:outputText value="#{messages['Hello']}"/>

または、

    <h:outputText value="#{messages.Hello}"/>

さらに良いことに、メッセージそのものには EL 式を含むことも可能です。

    Hello=Hello, #{user.firstName} #{user.lastName}

    Hello=G'day, #{user.firstName}

コードの中にメッセージを使用することも可能です。

    @In private Map<String, String> messages;

    @In("#{messages['Hello']}") private String helloMessage;

### 16.3.3. Faces メッセージ

`facesMessages` コンポーネントはユーザーに成功か失敗かを表示するとても便利な方法です。 上述した機能は、faces messages にも有効です。

    @Name("hello")

    @Stateless

    public class HelloBean implements Hello {

        @In FacesMessages facesMessages;

        public String sayIt() {

            facesMessages.addFromResourceBundle("Hello");

        }

    }

これは、ユーザーのロケールに応じて、`Hello, Gavin King` あるいは、 `G'day, Gavin` と表示されます。

## 16.4. タイムゾーン

`java.util.Timezone` のセッションスコープのインスタンス、 名称は`org.jboss.seam.international.timezone` とタイムゾーンを変更する Seam コンポーネント、 名称は `org.jboss.seam.international.timezoneSelector` もあります。 デフォルトでは、タイムゾーンはサーバのデフォルトタイムゾーンです。 タイムゾーンが `<f:convertDateTime>` を使用して明示的に指定されない限り、 残念ながら JSF 仕様ではすべての日付と時間は UTC を前提としており、UTC として表示されます。 非常に不便なデフォルト動作となります。

Seamはこの動作をオーバーライドし、すべての日付と時刻をデフォルトでSeamタイムゾーンにします。 さらにSeamは、Seamタイムゾーンでの変換を常に行う `<s:convertDateTime>` タグを提供します。

Seam は文字列値を日付に変換するためのデフォルト date コンバータも提供します。これは単に日付入力する input フィールド上にコンバータを設定する手間を節約します。このパターンは上述のようにユーザーのロケールとタイムゾーンの選択結果にしたがって選択されます。

## 16.5. テーマ

Seamアプリケーションはまた、とても簡単にスキン変更ができます。 テーマAPIはローカライゼーションAPIにとても似ていますが、 もちろんこれら二つの関心事は直交しており、 ローカライゼーションとテーマの両方をサポートするアプリケーションもあります。

まず、サポートされるテーマのセットを設定します:

    <theme:theme-selector cookie-enabled="true">

        <theme:available-themes>

            <value>default</value>

            <value>accessible</value>

            <value>printable</value>

        </theme:available-themes>

    </theme:theme-selector>

最初にリストされたテーマがデフォルトテーマであることに注意してください。

テーマは、そのテーマと同じ名前でプロパティファイルに定義されます。 例えば、 `default` テーマは `default.properties` に一連のエントリとして定義されます。 例えば、`default.properties` は以下のように定義します。

    css ../screen.css
    template /template.xhtml

通常、 テーマリソースバンドルのエントリは CSS スタイルや画像へのパスや facelet テンプレートの名前になるでしょう (通常はテキストであるローカライゼーションリソースバンドルとは違って)。

これでJSPやfaceletページにおいてこれらのエントリを使えます。 例えば、faceletページでスタイルシートを適用するには:

    <link href="#{theme.css}" rel="stylesheet" type="text/css" />

あるいは、サブディレクトリにページ定義が存在している場合は次のようになります。

    <link href="#{facesContext.externalContext.requestContextPath}#{theme.css}"

        rel="stylesheet" type="text/css" />

最も強力な使い方として、 faceletでは `<ui:composition>` によってテンプレートを適用できます。

    <ui:composition xmlns="http://www.w3.org/1999/xhtml"

        xmlns:ui="http://java.sun.com/jsf/facelets"

        xmlns:h="http://java.sun.com/jsf/html"

        xmlns:f="http://java.sun.com/jsf/core"

        template="#{theme.template}">

ちょうどロケールセレクタのように、 ユーザーが自由にテーマを変更できるよう、組み込みのテーマセレクタがあります。

    <h:selectOneMenu value="#{themeSelector.theme}">

        <f:selectItems value="#{themeSelector.themes}"/>

    </h:selectOneMenu>

    <h:commandButton action="#{themeSelector.select}" value="Select Theme"/>

## 16.6. ロケールとテーマ設定のクッキーによる永続化

ロケールセレクタ、テーマセレクタ、タイムゾーンセレクタはすべて、 ロケールとテーマ設定をクッキーに永続化することをサポートしています。 単純に `components.xml` で `cookie-enabled` プロパティを設定します。

    <theme:theme-selector cookie-enabled="true">

        <theme:available-themes>

            <value>default</value>

            <value>accessible</value>

            <value>printable</value>

        </theme:available-themes>

    </theme:theme-selector>

    <international:locale-selector cookie-enabled="true"/>

- 前のページ第15章 セキュリティ
- 上に戻る
- ホーム
- 次のページ第17章 Seam Text