Index > リソースバンドル(java.util.ResourceBundle)を使って表示文字列を管理しているが・・・
Mon, June 19, 2006

リソースバンドル(java.util.ResourceBundle)を使って表示文字列を管理しているが・・・

Javaには予め言語(というか地域というかロケールというか)別に 表示文字列リソースを管理するための仕組みが備わっている。
このリソースバンドルは非常に便利なのだが、もしリソースが存在しなかった場合に、 MissingResourceExceptionというランタイム例外を投げます。

さて、ランタイムにこの例外を決して発生させないようにしたいのですが、 どうすればいいのでしょうか。

リソースの中には、エラーメッセージなどめったに表示されないものも 含まれてますから、力業で人間がテストして、MissingResourceExceptionを 都度拾っていけばいいのさ、という方法はNGです。 (そのうえ、リソースはどんどん増えていく)

いろいろ考えたのですが、やはり、 リソースがもれなく登録されていることをランタイムにチェックする以外の 何か別の方法で管理する必要があるということだと思います。

テストを書く

プログラム中で使っているリソースキーの一覧があれば、 それと実際にリソースバンドルで管理しているキーの一覧を付き合わせればいいだけです。 簡単です。

しかし、プログラム中で使っているリソースキーの一覧はどうすれば得られるのでしょうか。 リソースキーは、いろいろなタイミングで増えたり減ったり、変更されたりするので、 ソースコードとは別に、テスト用キー一覧を作成して管理するのはあきらかに無意味です。

どうすればいいのか?

わたしのとった方法

もしかしてもっとスマートな方法があるのではないかと思うのですが、 いろいろ考えて、全ソースコードから機械的にリソースキーを拾うことにしました。
表示文字列を取り出すとき、ResourceBundle.getString("hogehoge")という 定型パターンのコードを書くため、全ソースコードをスキャンして、 この部分の記述を取り出して、この例でいえば、hogehogeを抜き出した一覧表を 作成すればOKです。

前処理として、grepで "getString" という文字列が含まれる行だけを抽出しておいた 上で、pickup.pyに渡します。

 $ grep getString `find ./ -name ".java"` > log
 $ jython pickup.py log

pickup.py

import sys

import java.lang as lang
import java.io as io
import java.util.regex as re

logfile=sys.argv[1]


rex="getString\(\"(.*?)\"\)"
patt=re.Pattern.compile(rex)

br=io.BufferedReader(io.InputStreamReader( io.FileInputStream(io.File(logfile)),"UTF-8"))
while(true):
    line=br.readLine()
    if line==None:
        break

    m=patt.matcher(lang.String(line))
    if m.find():
        print m.group(1)

br.close()

課題

実際には、ソースコード中コメントアウトされている部分に、 存在している getString も拾ってしまったり、 以下のような記述で表示文字列を取り出しているコードがあると 有効ではないのですが・・・

String key="hogehoge"
getString(key)

うーむ、もっとスマートな方法はないのか。

 Twitter
follow me on Twitter
 Categories