kagamihogeの日記

kagamihogeの日記です。

Flex の ResourceBundle のメモ

自分用のメモ。Adobe Flex 3 ヘルプ - Flex アプリケーションのローカライズ とか色々。

Flex 3 では非推奨になっている ResourceBundle を直接見るやり方

mx.resources.ResourceBundle そのものが非推奨になってるんじゃなくて、ResourceBundle#getString(key:String) とかの、ResourceBundle から値を取得するメソッドが非推奨になってるんだけど。

Flex Builder 前提での話になっちゃうけど。とりあえずメインの mxml をこんな感じに書く。

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" applicationComplete="init()">
    <mx:Script>
        <![CDATA[
            import mx.resources.ResourceBundle;
            [ResourceBundle("hogeResource")]
            public var rb:ResourceBundle;
            
            private function init():void {
                trace(rb.getString("fooKey"));
            }
        ]]>
    </mx:Script>
</mx:Application>


hogeResource.properties を作り、メインと同じディレクトリに置いておく。中身はよくある key=value 形式。

fooKey=fooValue

ただ、最初に書いたけどこのやり方は非推奨。実際「'getString' has been deprecated since 3.0. Please use 'ResourceManager.getInstance().getString()'.」という警告が出る。

ResourceManager を使うやり方

MXML のみのやり方は公式ドキュメントなどに譲るとして。AS のクラスから ResourceManager 経由してリソースファイル見るやり方。

<?xml version="1.0" encoding="utf-8"?>
<mx:Application xmlns:mx="http://www.adobe.com/2006/mxml" layout="absolute" applicationComplete="hoge()">
    <mx:Script>
        <![CDATA[            
            private function hoge():void {
                var h:Hoge = new Hoge();
                h.goHoge();
            }
        ]]>
    </mx:Script>
</mx:Application>

非推奨のやり方と変わらず、とりあえず mxml, hogeResource.properties, Hoge.as は同じディレクトリにおいておく。

package
{
    import mx.resources.ResourceManager;
    
    [ResourceBundle("hogeResource")]
    public class Hoge
    {
        public function Hoge()
        {
        }
        
        public function goHoge():void {
            var resourceValue:String = ResourceManager.getInstance().getString("hogeResource", "fooKey");
            
            trace("hogeResource_fooKey=" + resourceValue);
        }
    }
}

キモはクラスに付与する ResourceBundle というメタタグにあるようだ。こいつを書いておくと(何かよくわかんないけど)プロパティファイルにアクセスできるようになる。で、ResourceManager.getInstance().getString(bundleName:String, resourceName:String) をやると、プロパティファイル名(bundleName)とキー(resourceName)で値がとってこれる。

メタタグと getString するときと両方にバンドル名が必要なのがちょっとダサいなぁと思うのだけど……自分で何がしかのラッパー作って下さいね、ってことなのかな。

ResourceManager を使うやり方とローカライズ

ja_JP だとあっちのファイル、en_US だとこっちのファイル、とかをやりたい時のアレ。

まず、↓な感じにビルドパスの通ってるディレクトリ下にロケールの名前でディレクトリを掘ってやる。で、そこにプロパティファイルを置いてやる。

プロパティファイルの中身をそれぞれ判別つくよーに変える。


//en_US/hogeResource.properties
fooKey=fooValue en_US
//ja_JP/hogeResource.properties
fooKey=fooValue ja_JP

で、プロジェクトのプロパティ -> Flex コンパイラで追加コンパイラ引数をこんな感じで書く。


-locale ja_JP -source-path=./{locale}

{locale} って書いておくと -locale の値を見て自動判定してくれるっぽいですね。

コレで -locale ja_JP を -locale en_US に変えてやると違うプロパティファイルを見に行ってくれるようになる。

ビルドパス下にはプロパティファイル置くもんじゃない?

この状態だと「ソースパスエントリ '(省略)\rbtest\src\ja_JP' は、クラスパスエントリ '(省略)\rbtest\src' のサブディレクトリです。」とかいう警告が出る。Flex ではソースファイル以外をビルドパスに入れるのはあんま宜しく無いってことなのかね?

というわけで。ビルドパスからいっこ上の階層に移してみる。ついでに locale という名前のディレクトリ下に置くようにする。コンパイラ引数もちょっと変更してやる。


-locale ja_JP -source-path=../locale/{locale}


ja_JP, en_US 以外のテキトーなロケールを使いたい場合

ちなみに Flex Builder インストールしただけのデフォ状態だと -locale に ja_JP と en_US しか使えないです。ヘンなの指定すると「'(省略)\frameworks\locale\ab_CD' を開くことができません」とかって怒られます。このディレクトリ見るとわかるんですが、ロケールに対応するファイルが無いと駄目なんですな。

で、とりあえずのテキトーなロケールを作りたい場合の対応。


(省略)\bin\copylocale en_US ab_CD

コレでテキトーなロケールが frameworks\locale 下に作られます。モチロン本番用にはちゃんとしたファイル作ってあげなきゃいけないんだろうけど。作り方は、えー、Adobe の公式ドキュメントを……(調べてないとも言う

ResourceManager と動的な表示言語切り替え

mx.resources.IResourceManager とかを見ていると「localeChain の値変えればいいよ」とか書いてある。localeChain が何モンかについては省略。

なので、こんな感じのコードを書いてみる。

public function goHoge():void {
    var resourceValue:String = "";
    
    resourceValue = ResourceManager.getInstance().getString("hogeResource", "fooKey");
    trace("hogeResource_fooKey=" + resourceValue);
    
    ResourceManager.getInstance().localeChain = ["en_US"];
    
    resourceValue = ResourceManager.getInstance().getString("hogeResource", "fooKey");
    trace("hogeResource_fooKey=" + resourceValue);
}

で、コンパイル引数は locale に ja_JP だけを指定してみる。


-locale=ja_JP -source-path=../locale/{locale}

しかし en_US は表示されない……以下実行結果。


hogeResource_fooKey=foo ja_JP
hogeResource_fooKey=null

どうやら使用するロケールはぜんぶ -locale で指定してやんないといけないらしい。


-locale=ja_JP,en_US -source-path=../locale/{locale}

こうすると期待通りの表示がされた。

Flex ライブラリプロジェクトを使う場合

ロケール切り替えして何か表示するような処理がある Flex ライブラリプロジェクトをこ作って、それを別プロジェクトから使うような場合。

パッケージ構成はとりあえずこんな感じで。

HogeSwc はこんな感じにただメッセージ表示するだけ。

package hogepackage
{
    import mx.resources.ResourceManager;
    
    [ResourceBundle("hogeSwcResource")]
    public class HogeSwc
    {
        public function HogeSwc()
        {
        }
        
        public function doResourcePrint():void {
            var resourceValue:String = "";
            
            resourceValue = ResourceManager.getInstance().getString("hogeSwcResource", "fooKey");
            trace("hogeResource_fooKey=" + resourceValue);
        }
    }
}

んで追加コンパイル引数に↓を追加。


-source-path=../locale/{locale}

で、別の Flex プロジェクトからこんな感じのコードでライブラリを使ってみる。

import hogepackage.HogeSwc;
private function hoge():void {
    var h:HogeSwc = new HogeSwc();
    h.doResourcePrint();
}

が、コレでは「ロケール "ja_JP" のリソースバンドル "hogeSwcResource" を解決できません」となる。どーやらコレは Flex ライブラリプロジェクト側で、Flex ライブラリビルドパス -> アセット -> ライブラリに含める非埋め込みファイルを設定してないことに起因してるっぽい。

なのでアセットに入れてやればいいのだなーと思ったら……

ソースパスに入ってないと、ここの一覧に出てきてくれないようだ。なのでソースパスに locale を入れて、アセットでライブラリに含める非埋め込みファイルに locale 以下を指定してみると……これもダメ。うーん……

で。うまくいったやり方のプロジェクト構成とアセットの設定。追加コンパイラの引数はブランク。

src 下になぜプロパティファイルがあるかっていうと、ここにダミーのファイルがないとコンパイルが通らないから。なので、このダミーファイルの中身は空っぽです。

……うーん……なんか、すごい変なことやってる気がするんだけど、どうなんだろう。

ちなみに、なんでコレが気になったかというと yui-frameworks のソース覗いてみたらパッケージ構成がこうなってたから。

なんで locale 下にも src 下にも *.properties あるんだろ……? と思った次第で御座います。それで色々実験していたら、あぁ、まぁ……なるほどと。

実行時のリソースモジュールのロード

今まで書いたやり方だとちょっと不便なとこがあります。ひとつは、再コンパイルしないと別言語用の swf を作れないこと。コンパイルオプションで -locale を指定してるアレのことです。ただ、一応これは動的な表示言語切り替えで書いた方法で解決できる。がしかし、もうひとつの問題が起きる。それは、多言語対応のプロパティファイルをひとつの swf に組み込んでしまうこと。言語の数が少なければ別にいいかもしれないけど、肥大化は気になるし、後から言語の追加がしにくいってのはやはりイマイチ。何にせよ、多言語対応に再コンパイルが必要、ってのは場合によってはあまり歓迎されないことがあるんですよね。技術的というより政治的な意味で。

とはいえ……ここまで疲れたのでとりあえず一旦終了。下のリンクとか読めばいいらしい。

リソースモジュールの使用 - 実行時のリソースモジュールのロード

とかなんとかグダグダ考えてたら S2Flex - メッセージの多言語対応 なんてのが。そっか……多言語対応は Java 側でやって、Flex はそっから引っ張ってくるだけ、ってのもアリ、か……? 言われてみれば、確かに……という感じなんだけど。