Home of: [工房 "藤車"] > [SourceForge.net における PageMixer]

locale に応じたページ描画

本節では、 PageMixer フレームワークにおいて、 ロケールに応じた HTML ページ描画の実現について説明します。 言い換えるなら、 多言語化のためのロケール対応ユーティリティの使い方の説明です。

注意: 本節で説明されている内容に関しては、 PageMixer 2.x から大きく設計が変更されています。

概要

クラス図

本節におけるクラス図を以下に示します。

クラス図
クラス図 (クリックで拡大表示)

クラス名

本チュートリアルでは、 クラスは全てクラス名のみで表記されています。 完全な名称は以下の通りです。

PageMixer フレームワークのクラス

表記完全名
ClassLoaderLocator jp.ne.dti.lares.foozy.pagemixer.page.ClassLoaderLocator
DefaultPage jp.ne.dti.lares.foozy.pagemixer.page.DefaultPage
LocalFSLocator jp.ne.dti.lares.foozy.pagemixer.page.LocalFSLocator
LocalePage jp.ne.dti.lares.foozy.pagemixer.page.LocalePage
Locator jp.ne.dti.lares.foozy.pagemixer.page.Locator
MonoPage jp.ne.dti.lares.foozy.pagemixer.page.MonoPage
Page jp.ne.dti.lares.foozy.pagemixer.page.Page
PageEntry jp.ne.dti.lares.foozy.pagemixer.page.PageEntry
PageEntryFactory jp.ne.dti.lares.foozy.pagemixer.page.PageEntryFactory
PageParser jp.ne.dti.lares.foozy.pagemixer.mixer.PageParser
PersistentProducer jp.ne.dti.lares.foozy.pagemixer.page.PersistentProducer
Producer jp.ne.dti.lares.foozy.pagemixer.mixer.Producer

チュートリアルの固有クラス

表記完全名
Bootstrap pagemixer.filter.Bootstrap
LocalePageSample pagemixer.filter.LocalePageSample
NopFilter pagemixer.filter.NopFilter

概念

初期の PageMixer は、 「ロケールに応じた描画」の目的を、 「多言語化アプリケーションの容易な構築」としていました。 そのため、ユーティリティクラス群は、 「ロケールへの配慮」のみに着目していたのです。 しかし PageMixer 3.0 からは、 「ページ」がより体系的に抽象化されています。

はじめに、 以下に示す新たに導入された概念を説明します。

「リソース(resource)」
Producer インスタンスを生成するための InputStream の元となるもの。 例えば、 HTML ファイルや事前解析で生成された Producerなどは 「リソース」に成り得ます。 一つの「リソース」は一つの Producer に対応します。
「リソースロケーション(resource location)」
「リソース」を識別するためのシンボリックな名前。 複数の「リソースロケーション」が同一の「リソース」を指し示すことも有り得ます。
「ページエントリ(page entry)」
描画のための情報の集合。 この集合は、 Producer インスタンス、 コンテントタイプ(例: "text/html; charset=Windows-31J")、 エンコーディング(e.g.: "Windows-31J")などから構成されます。
「ページ(page)」
複数の「ページエントリ」を論理的な一つの単位として扱うための 「ページエントリ」の集合。 この集合は同時に「ページエントリ」と 「リソースロケーション」の間の関連性も管理します。
「エントリ名(entry name)」
「ページ」において「ページエントリ」を識別するためのシンボリックな名前。 複数の「エントリ名」が同一の「ページエントリ」を指し示すことも有り得ます。

ここで、 描画手続きは以下の3つの部位に分割されます。

「リソース」管理:
この部位は、 指定された「リソースロケーション」に対応する「リソース」の InputSream 取得方法および、 「リソース」の最終更新タイムスタンプの取得/比較の方法をカプセル化します。
Producer インスタンス取得:
この部位は、 「リソース」の(取得された) InputStream から、 Producer を生成する方法をカプセル化します。
「ページエントリ」管理:
この部位は、 指定された「エントリ名」とロケールから、 「リソースロケーション」/コンテントタイプ/ エンコーディングといったものを確定する方法をカプセル化します。 言い換えるなら、 この部位はまさに「ページ」そのものに相当します。

「リソース」管理

PageMixer は「リソース」管理のために "Locator" を提供しています。

また、PageMixer は ClassLoader 経由での「リソース」読み込み (これは例えば JAR ファイルから「リソース」を読み込む際に有用です) のための "ClassLoaderLocator" や、 ローカルのファイルシステムからの「リソース」読み込みのための "LocalFSLocator" も提供しています。

備考: 他にも Servlet 環境用にいくつかのクラスが提供されていますが、 それらの説明は Servlet 用チュートリアルにて説明します。

あなた自身の固有「リソース」管理 (例: RDBMS における管理)を実装する場合、 Locator に関する詳細は API ドキュメント(および実装クラス群のソースコード)を参照してください。

Producer インスタンス取得

PageMixer は Producer インスタンス取得のために "Producer.Factory" を提供しています。 また、実のところ、 PageParser および PersistentProducer の両方ともが Producer.Factory 実装クラスです。

「ページエントリ」管理

PageMixer は 「ページエントリ」管理のために "Page" および以下に示すいくつかの実装クラスを提供しています。

あなた自身の固有「ページエントリ」管理 (例: RDBMS における管理)を実装する場合、 Page に関する詳細は API ドキュメント(および実装クラス群のソースコード)を参照してください。

MonoPage

ロケールに応じたコンテンツ向けではありませんが、 はじめに "MonoPage" の説明をします。 このクラスは、 実のところ非 ASCII 文字集合を使用したコンテンツの描画の際に重要です。

MonoPage は、 「エントリ名」と「リソースロケーション」との間の関連性を唯一つだけ管理します。 更に、それらの全ては、 以下に示すようにコンストラクタ引数として指定されます。

コンストラクタ起動例を以下に示します。


new MonoPage("text/html; charset=Windows-31J",
             "Windows-31J",
             "page/index.ja.html");

MonoPage

コンストラクタ引数のいくつかは省略が可能ですが、 詳細は API ドキュメントを参照してください。

LocalePage

"LocalePage" は、 ロケールに応じた描画のために、 「エントリ名」と「リソースロケーション」の間の "1 対 N" 関係を管理します。

このクラスは、 指定されたロケールごとに異なる 「リソースロケーション」および描画情報を返却し、 これは ResourceBundle により実装されています。

本クラスのコンストラクタパラメータは、 ResourceBundle 取得のためのベース名のみですが、 取得された ResourceBundle は以下に示す情報の取得に利用されます。

ResourceBundle ベース名として "page.demosite.index" を指定して LocalePage を生成する場合、 例えば "page/demosite/index_ja.properties" は以下のように記述されます。


contentType:text/html; charset=Windows-31J
encoding:Windows-31J
location:/WEB-INF/page/demosite/index.ja.html

"ja" ロケール向け *.properties ファイルの記述例

この設定により以下のような結果が得られます。

注意: ResourceBundle による読み込み順では 「空」ロケールよりもシステムデフォルトロケールが先であるため、 実行環境のシステムデフォルトロケールが、 ウェブアプリケーションのデフォルトロケールと異なる場合、 ウェブアプリケーションのデフォルトロケール用の "*.properties" ファイルを明示的に作成する必要があります。

例えば、 "ja" ロケール環境において "en" をデフォルトロケールとするウェブアプリケーションを提供する場合、 "page/demosite/index.properties" と同一内容の "page/demosite/index_en.properties" ファイルが必要です。

DefaultPage

"DefaultPage" は 同一のコンテントタイプやエンコーディングを 「ページエントリ」間で共有するための Page 実装クラスです。 本クラスは、 生成時に指定されたコンテントタイプやエンコーディング値をそのまま返却し、 同じく生成時に指定された「エントリ名」を 「リソースロケーション」値として返却します。

本クラスは、 例えば DefaultPage を使用する Servlet を "*.ja.html" URL パターンでマッピングしている場合、 全ての「*.ja.html」要求に対して、 固有のコンテントタイプやエンコーディングを指定することができることから、 スタンドアロンなアプリケーション環境よりも、 Servlet 環境において有用と思われます。 本クラスはマッピング外のファイルを読み込んでそれらを用いて応答を生成する "DefaultServlet" のようなものです。

まとめ

Page 実装クラス間の比較を以下に示しますので、 選択の一助としてください。

--- MonoPage LocalePage DefaultPage
ロケールに応じた描画 不可 不可
受理可能な URI 数 1 1 N
URI ごとの設定 不可

構築

ロケールに応じた描画を簡単に行うには、 LocatorProducer.Factory および Page の実装クラスを選択する必要があります。 更に付け加えるなら、 選択した実装クラス群を連携させるべくこれらを組み合わせる必要があります。

もちろん自前のクラスでこれらを組み合わせても構いませんが、 PageMixer は簡単に組み合わを行うために "PageEntryFactory" を提供しています。

例えば ClassLoaderLocatorPageParser および LocalePage を組み合わせるためのコードは以下のようになります。


String baseName = "page.demosite.index";

new PageEntryFactory(new LocalePage(baseName),
                     new ClassLoaderLocator(),
                     new PageParser());

構築

これにより、 生成された PageEntryFactory を通して、 指定された「エントリ名」およびロケールに応じた コンテントタイプ/エンコーディング/Producer 及びその他を保持する "PageEntry" を取得することができます。

繋いで混ぜる

以上で必要なものが全て揃いました。 実行コードは以下のようになります (詳細は pagemixer.filter.LocalePageSample を参照してください)。


final PageEntryFactory factory =
new PageEntryFactory(new LocalePage(baseName),
                     new ClassLoaderLocator(),
                     new PageParser());

try{
    Bootstrap bootstrap = new Bootstrap()
    {
        protected Producer createProducer()
            throws IOException, //
                   ClassNotFoundException //
        {
            PageEntry entry =
            factory.create(null, locale);
            return entry.getProducer();
        }
    };
    bootstrap.execute(new NopFilter());
}
catch(Exception e){
    e.printStackTrace(System.err);
}

繋いで混ぜる

上記例では、 PageEntryFactory 生成において使用されている baseName 変数は ResourceBundle のベース名が格納されており、 locale 引数は結果を描画する際のロケールが格納されています。

LocalePage 向けの *.properties ファイルのサンプルは、 src/bin 配布版の "src/demo/servlet/war/WEB-INF/classes/page" ディレクトリ配下に格納されており、 その記述は "src/demo/servlet/war" 配下の HTML ファイルを必要としています。 そのため、 サンプルをスタンドアロンアプリケーションとして実行する場合は、 src/bin 配布版の "src/demo/servlet/war/WEB-INF/classes" および "src/demo/servlet/war" へのパスを CLASSPATH の一部として指定する必要があります。