プログラムソースコード中に日本語が書かれているとどうも落ち着きません。また多言語化の可能性を考えると、メッセージなどの印字文字列はプログラム中には持たず外部リソースに置くことがオススメです。
Javaでは従来java.util.Propertiesを使って環境設定情報や文字列リソースを持つことになっていました。
Properties p = new Properties();
InputStream is = new BufferedInputStream(FileInputStream("setting_ja.properties"));
p.load(is);
is.close();
System.out.println( p.getProperty("user.name") );
このようにしておけば実行時のパラメータを設定ファイルを変更するだけで切り替えることが可能になります。また言語環境に依存する表示文字列なども環境がわかれば簡単に切り替え可能です。
propertiesファイルの書き方は以下になります。
user.name=Steve Jobs
しかしここに一つ問題があります。PropertiesファイルではISO 8859-1で記述する必要があります。簡単に言えばASCII文字のみ。日本語などの文字列を使いたい場合にはUnicodeエスケープする必要があります。上記例でユーザー名に「織田信長」としたい場合には以下のようにしなければなりません。
user.name=\u7e54\u7530\u4fe1\u9577
人間にはこのような記述をするのは無理です。ですから
user.name=織田信長
書かれたファイルを用意しておいて、native2asciiコマンドで変換します。
$ native2ascii setting.txt > setting_ja.properties
ちなみに、Unicodeエスケープされたファイルを人間が識別できる文字列に変換するにはnative2asciiを-reverseオプション付きで実行すればよい。この他にも様々なエンコーディングに変換するオプションがある。
しかしこのような変換は手間だし、設定ファイルだけで内容を識別することが難しいのでできれば日本語そのまま記述したファイルを使いたい。
Java SE 1.5からXMLファイルを使えばこのような要求に応えられるようになっています。
Properties p = new Properties();
InputStream is = new BufferedInputStream(FileInputStream("setting_ja.xml"));
p.loadFromXML(is);
is.close();
System.out.println( p.getProperty("user.name") );
ファイルの記述は以下
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE properties SYSTEM "http://java.sun.com/dtd/properties.dtd">
<properties>
<comment></comment>
<entry key="hello">こんにちは</entry>
</properties>
例外の管理もいれると面倒なので、以下のようなユーティリティクラスにして利用しています。
package utility;
import java.io.BufferedInputStream;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.InvalidPropertiesFormatException;
import java.util.Properties;
public class LocalizedString {
private Properties properties;
public LocalizedString(String fileName) {
Properties aProperties = new Properties();
try {
InputStream is;
is = new BufferedInputStream(
new FileInputStream(fileName));
aProperties.loadFromXML(is);
this.properties = aProperties;
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (InvalidPropertiesFormatException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
public LocalizedString() {
this("Message_ja.xml");
}
public boolean isAvailable() {
return (this.properties!=null);
}
public Object getProperty(String aKey) {
if ( this.isAvailable() ) {
return this.properties.getProperty(aKey);
}
return null;
}
public static void main(String[] args) {
LocalizedString aProperties = new LocalizedString();
String aKey;
aKey = "hello";
System.out.println(aKey+" = "+aProperties.getProperty(aKey));
aKey = "name";
System.out.println(aKey+" = "+aProperties.getProperty(aKey));
}
}
ちなみに、Java SE 1.6からはProperties#load(InputStream)ではなくProperties#load(Reader)を使えば、ISO 8859-1以外の文字列入力ストリームにも対応可能になっているそうです。
public static void main(String[] args) {
Properties p = new Properties();
try {
InputStreamReader in =
new InputStreamReader(
new FileInputStream("ja.properties"),"UTF-8");
p.load(in);
in.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
String aKey = "name";
System.out.println(aKey + " = "+p.getProperty(aKey));
}