ResourceBundle, MessageSourceでproperties内に日本語でメッセージを書く

<移行分>
ResourceBundle, MessageSourceでproperties内に日本語でメッセージを書く
Java6のJavaDocを眺めていると、ResourceBundle を拡張する ResourceBundle.Control というものがあるらしいことに気づいた。

つまりUTF-8指定した Properties を使う ResourceBundle.Control を書けば、UTF-8で書いたメッセージ定義プロパティファイルを ResourceBundle で扱える。
さようなら、native2ascii !!

文字コード指定できる ResourceBundle.Control

public class PropertyResourceBundleControl extends ResourceBundle.Control {

    private String charsetName;

    // ...

    public PropertyResourceBundleControl(String charsetName) {
        this.charsetName = charsetName;
    }

    // ...

    @Override
    public ResourceBundle newBundle(String baseName,
            Locale locale, String format, ClassLoader loader, boolean reload)
    throws IllegalAccessException, InstantiationException, IOException {

        // ... 

            if (stream != null) {
                BufferedReader br = new BufferedReader(
                        new InputStreamReader(stream, charsetName));
                bundle = new PropertyResourceBundle(br);
                br.close();
            }
        }
        return bundle;
    }
}

つまり、Springの MessageResource でも日本語が使える。
UTF-8を読める ResourceBundle でメッセージ定義を読む MessageResource

public class PropertyResourceBundleMessageSource extends
        ResourceBundleMessageSource {

    @Override
    protected ResourceBundle doGetBundle(String basename, Locale locale) 
    throws MissingResourceException {
        return ResourceBundle.getBundle(basename, locale, 
                getBundleClassLoader(), 
                new PropertyResourceBundleControl());
    }
 
}

bean定義(ここではcontext.xml)で PropertyResourceBundleMessageSource を messageSource に指定。

    <bean id="messageSource"
          class="examples.applicationcontext.PropertyResourceBundleMessageSource">
        <property name="basenames">
            <list>
                <value>messages/format</value>
                <value>messages/exceptions</value>
                <value>messages/nihongo</value>
            </list>
        </property>
    </bean>
    
    <bean id="foo" class="examples.applicationcontext.Foo">
        <property name="messageSource" ref="messageSource" />
    </bean>

メッセージはUTF-8で記述。message/nihongo.properties

キー=キーに対する値
key1=value for the key
引数.必須=引数 ''{0}'' は必須です。

テストコード

    private ApplicationContext context;
    
    @Before
    public void before() {
        context = new ClassPathXmlApplicationContext("context.xml");
    }

   @Test
   public void testMessageSourceInjection() {
       Foo foo = (Foo)context.getBean("foo");
       assertEquals("the argument 'foo' is required", foo.getMessage("argument.required", "foo"));
       assertEquals("引数 'var' は必須です。", foo.getMessage("引数.必須", "var"));
   }