かとじゅんの技術日誌

技術の話をするところ

言語リソースのXLS化

JavaExpert #02に紹介のあった言語リソースのXLS化の事例を少しカスタマイズしています.

Java Expert #02

Java Expert #02


書籍にサンプルでは,Properties,つまりXLSから読み込まれた言語リソースが,言語毎にひとつしか存在しません.このオブジェクトはキャッシュとして利用させる前提になっているので,日本語のブラウザでアクセスした後に,英語のブラウザでアクセスすると日本語のままのリソースになります.以下のコードでは,言語毎にキャッシュを持つように変更しています.本当は,ひとつのXLSファイルで言語毎にシートを分けるとか,同じシートで言語ごとに列でリソースを定義するとかやりたかったのですが,,,時間がなかったのでご参考までに.
ちなみに書籍にはdiconファイルにどのように記述するか書いてませんが,teedaCustomize.diconにを追加定義してください.
また,XLSファイルのほうは,WEB-INF/classesに配置される前提つまりsrc/main/resources直下にXLSファイルを配置することになります.ファイル名については日本語の場合ですとmessage_ja.xlsで,シート名はmessageで,それ以外のシートは作らないようにしてください.

public class XlsMessageResourceBundleImpl implements MessageResourceBundle {

	public static final String DEFAULT_MESSAGE_RESOURCE_NAME = "messages";

	public static final String XLS_SUFFIX = ".xls";

	public static final String DEFAULT_MESSAGE_XLS = DEFAULT_MESSAGE_RESOURCE_NAME
			+ XLS_SUFFIX;

	private String messageResourceName = DEFAULT_MESSAGE_RESOURCE_NAME;

	private MessageResourceBundle parent;

	private Map<String, Properties> propertiesMap = new HashMap<String, Properties>();

	private Properties defaultProperties;

	private String sheetName = "messages";

	public String get(String key) {
		if (key == null) {
			return null;
		}

		String currentLangCode = this.getLangCode();

		initialize(currentLangCode);

		Object value = (propertiesMap.get(currentLangCode) != null) ? propertiesMap
				.get(currentLangCode).get(key)
				: null;
		if (value == null) {
			value = this.defaultProperties.get(key);
		}
		if (value == null) {
			value = (propertiesMap.get(currentLangCode) != null) ? propertiesMap
					.get(currentLangCode).get(key)
					: null;
		}
		return (String) value;
	}

	private String getLangCode() {
		final FacesContext context = FacesContext.getCurrentInstance();
		if (context != null) {
			final UIViewRoot viewRoot = context.getViewRoot();
			if (viewRoot != null) {
				final Locale locale = viewRoot.getLocale();
				final String lang = locale.getLanguage();
				return lang.toLowerCase();
			}
		}
		return null;
	}

	private void initialize(String langCode) {
		if (defaultProperties == null) {
			final InputStream is = ResourceUtil
					.getResourceAsStreamNoException(DEFAULT_MESSAGE_XLS);
			this.defaultProperties = (is != null) ? loadProperties(is)
					: new Properties();
		}
		if (propertiesMap.containsKey(langCode)) {
			return;
		}
		String messages = messageResourceName;

		messages = messages + "_" + langCode + XLS_SUFFIX;

		if (messages.equals(DEFAULT_MESSAGE_XLS)) {
			return;
		}
		final InputStream is = ResourceUtil
				.getResourceAsStreamNoException(messages);
		if (is == null) {
			return;
		}
		Properties properties = loadProperties(is);
		propertiesMap.put(langCode, properties);
	}

	protected Properties loadProperties(final InputStream is) {
		Properties properties = new Properties();
		XlsReader xlsReader = new XlsReader(is);
		final DataSet dataset = xlsReader.read();
		final DataTable table = dataset.getTable(sheetName);
		for (int i = 0; i < table.getRowSize(); i++) {
			final DataRow row = table.getRow(i);
			final String bundleKey = (String) row.getValue(0);
			final String bundleVal = (String) row.getValue(1);
			if (bundleKey != null && bundleVal != null) {
				properties.put(bundleKey, bundleVal);
			}
		}
		return properties;
	}

	public MessageResourceBundle getParent() {
		return parent;
	}

	public void setParent(MessageResourceBundle parent) {
		this.parent = parent;
	}
}