SeamFramework.orgCommunity Documentation
Seam では容易に国際化されたアプリケーションを作成できます。 まず、 アプリケーションの国際化および地域化に必要とされるすべての段階について見ていきます。 そのあと Seam が同梱するコンポーネントの説明をします。
JEE アプリケーションは数多くのコンポーネントから構成され、 それらのコンポーネントすべてがローカライズを行うアプリケーションに対して正しく設定されていなければなりません。
Note that all i18n features in Seam work only in JSF context.
最初から始めることにします。 1 番目の手順としてデータベースのサーバーとクライアントが使用するロケールに対応する正しい文字エンコーディングを使用していることを確認します。 UTF-8 を使用するのが全般的には多くなります。 この方法については本チュートリアルの範囲外となります。
アプリケーションサーバーが要求パラメータを正しいエンコーディングでクライアントの要求から受け取るようにするには、 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"/>
アプリケーションのすべての メッセージ にも翻訳された文字列が必要となります (例、 ビューのフィールドラベルなど)。 まず、 リソースバンドルが目的の文字エンコーディングを使ってコード化されることを確認する必要があります。 デフォルトでは ASCII が使用されます。 ASCII は多くの言語に十分対応しますが、 すべての言語の文字を提供しているわけではありません。
リソースバンドルは ASCII で作成されなければなりません。 あるいは Unicode 文字の表示に Unicode エスケープのコードを使用します。 バイトコードに対してプロパティファイルをコンパイルしないため使用にセットする文字を JVM に伝える方法がありません。 このため、 ASCII 文字または ASCII 文字にはないエスケープ文字を使用しなければなりません。 \uXXXX を使用するといずれの Java ファイルでも Unicode 文字を表すことができます。 XXXX はその文字を表す 16 進数です。
You can write your translation of labels (項16.3. 「ラベル」) to your messages resource bundle in the native encoding and then convert the content of the file into the escaped format through the tool native2ascii
provided in the JDK. This tool will convert a file written in your native encoding to one that represents non-ASCII characters as Unicode escape sequences.
このツールの使い方は Java 5 の場合はここ または Java 6 の場合はここ に記載されています。 たとえば、 あるファイルを UTF-8 から変換するには次のようにします。
$ native2ascii -encoding UTF-8 messages_cs.properties > messages_cs_escaped.properties
正しい文字セットを使ってローカライズされたデータとメッセージが表示されること、 そしてサブミットされるデータがすべて正しいエンコーディングを使用することを確認する必要があります。
表示文字のエンコーディングを設定するには <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" />
各ユーザーログインのセッションは、 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"/>
必然的にロケールをサポートすることを宣言する場合、 一致するリソースバンドルを与えた方がよいでしょう。 次は言語固有のラベルの定義方法について説明します。
JSF は、ユーザーインタフェースのラベルや説明用テキストの国際化を、 <f:loadBundle />
を使用することによって対応しています。 Seam アプリケーションでもこのアプローチが使用可能です。 代わりに、組み込みの EL 式を利用したテンプレート化ラベルの表示に、 Seam messages
コンポーネントを利用することも可能です。
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
で使うことができます。
もし、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;
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
と表示されます。
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 also provides a default date converter to convert a string value to a date. This saves you from having to specify a converter on input fields that are simply capturing a date. The pattern is selected according the the user's locale and the time zone is selected as described above.
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"/>
ロケールセレクタ、テーマセレクタ、タイムゾーンセレクタはすべて、 ロケールとテーマ設定をクッキーに永続化することをサポートしています。 単純に 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"/>