Java使用enum处理国际化问题

Message.java
public enum Message {
    USER_USERNAME_EXISTENT,
    WHATEVER_YOU_WANT("whatever.You.WANT"),
    NOT_DEFINED;

    private final static ThreadLocal<ResourceBundle> lang = new ThreadLocal<ResourceBundle>();
    private final static String BASENAME = "lang";
    public final String key;

    Message() {
        key = name().toLowerCase().replace('_', '.');
    }

    Message(String key) {
        this.key = key;
    }

    public String value() {
        return text(key);
    }

    public String value(Object[] o) {
        return text(key, o);
    }

    @Override
    public String toString() {
        return value();
    }

    private static String text(String key) {
        return text(key, "");
    }

    private static String text(String key, Object[] o) {
        return new MessageFormat(text(key)).format(o);
    }

    private static String text(String key, String defaultValue) {
        return key == null || lang.get() == null || !lang.get().containsKey(key) ? defaultValue : lang.get().getString(key);
    }

    /*private static String text(String key, String defaultValue, Object[] o) {
        return new MessageFormat(text(key, defaultValue)).format(o);
    }*/

    public static void setLocale(String s) {
        try {
            String[] arr = s.split("_");
            Locale locale = null;
            switch (arr.length) {
                case 1:
                    locale = new Locale(arr[0]);
                    break;
                case 2:
                    locale = new Locale(arr[0], arr[1]);
                    break;
                case 3:
                    locale = new Locale(arr[0], arr[1], arr[2]);
                    break;
            }
            setLocale(locale);
        } catch (Exception e) {
            e.printStackTrace();
            setLocale(Locale.CHINA);
        }
    }

    public static void setLocale(Locale locale) {
        lang.set(ResourceBundle.getBundle(BASENAME, locale));
    }

    public static void main(String[] args) {
        testLocale(Locale.CHINA);
        testLocale(Locale.CANADA);
        testLocale(Locale.US);
    }

    private static void testLocale(Locale locale) {
        setLocale(locale);
        System.err.println("国际化资源完整性检查:" + BASENAME + "_" + locale + ".properties");
        for (Message message : Message.values()) {
            if (message.value().equals("")) {
                System.err.println(message.key);
            } /*else {
                System.out.println(message.key + "=" + message.value());
            }*/
        }
    }
}


在国际化资源文件lang_zh_CN.properties中定义如下:
user.username.existent=账号已存在
whatever.You.WANT=非默认格式的键


Message类中的变量说明:
String key 对应资源文件中的键, 默认将枚举名的大写转小写, 下划线转点号
ThreadLocal<ResourceBundle> lang 在多线程环境中为本地线程保存一个对国际化资源的引用
String BASENAME 资源名

方法说明
toString,value,text都是根据key去找对应的国际化消息,  如果是格式化的字符串, 还可以带参数
setLocale 线程创建时设置国际化资源
testLocale 这个方法是个亮点, 使用它可以迅速地查出国际化资源里那些国际化消息还没有实现

调用示例:
Jsp
<%@ page import="com.xxx.xxx.Message" %>
<%=Message.USER_USERNAME_EXISTENT%>


Java
String text = Message.USER_USERNAME_EXISTENT.value();


可以看出, 在Jsp页面上对国际化消息的处理比任何标签都来的简洁, 而且不会因为字符串的拼写错误而无法找到国际化资源里的键.

你可能感兴趣的:(java,enum,多线程,jsp,国际化)