JFinal中使用JSP的自定義Tag解決I18N

1. 設計起因

因爲JFinal的國際化(I18N)支持在JSP中支持很差,所以,萌生了解決這一短板的念頭。php

實現時也考慮了幾種方式,最終決定採用JSP中最原始的標籤。由於自定義標籤在JSP中容易實現,內容靈活且功能比較強大,可擴展性好。html

 

2. I18N標籤

自定義的I18N標籤須要針對I18N的各個接口作最好的支持,使用<jf:i18n />做爲標籤名,下面是JFinalI18N類的幾個接口:前端

public static String getText(String key)
public static String getText(String key, String defaultValue)
public static String getText(String key, Locale locale)
public static String getText(String key, String defaultValue, Locale locale)


完整的標籤被設計成:java

<jf:i18n key="" defaultValue="" locale="" paras="" />

        參數說明:web

參數名jsp

做用ide

說明ui

keythis

對應接口中的keyspa

 

defaultValue

對應接口中的defaultValue

 

locale

對應接口中的locale

數據類型有差異,這裏只能使用字串,如:zh_CN, en_US

paras

全新的屬性,爲了支持參替換而設計

1.假如key對應字串爲「早上好!{0}們,如今正實驗{1}。」;paras取值爲「小白,I18N標籤」(參數間用逗號隔開);那麼獲得的最終結果是「早上好!小白們,如今正實驗I18N標籤。」

2.另外,參數能夠從Controller的attr中取值,例如:Controller中setAttr(p1小白).setAttr(p2I18N標籤);標籤中的paras取值爲「p1,p2」,尋麼最終結果仍是「早上好!小白們,如今正實驗I18N標籤。」

3. 代碼實現

3.1 I18nTag.java

package com.jfinal.tag;

import java.io.IOException;

import javax.servlet.jsp.JspException;
import javax.servlet.jsp.JspWriter;
import javax.servlet.jsp.tagext.Tag;
import javax.servlet.jsp.tagext.TagSupport;

import com.jfinal.i18n.I18N;
import com.jfinal.kit.LocaleKit;
import com.jfinal.kit.StringKit;

/**
 * JSP頁面中用於支持I18N的標籤。
 */
public class I18nTag extends TagSupport {

	private static final long serialVersionUID = -8073376431317433802L;

	
	/**
	 * I18N中的key值
	 */
	private String key;

	/**
	 * 當key值不存在時使用的默認值
	 */
	private String defaultValue;

	/**
	 * 地區屬性,如:zh_CN, en_US
	 */
	private String locale;

	/**
	 * 做爲value格式化值使用的參數,多個用逗號隔開,若是參數值在Request中有對應的attribute,則取attribute值
	 */
	private String paras;

	@SuppressWarnings("deprecation")
	@Override
	public int doStartTag() throws JspException {
//		if (StringKit.isBlank(this.getKey())) {
//			throw new JspException("The tag attribute of key is not exists.");
//		}

		// 定義輸出給頁面的text
		String text = null;

		try {
			if (StringKit.isBlank(locale)) {
				// 經過I18N接口拿到值
				text = I18N.getText(key, this.defaultValue);
			} else {
				// locale定義了值,說明指定了前端要顯示的語言類型,語言類型交由LocaleKit處理
				text = I18N.getText(key, this.defaultValue, I18N.localeFromString(locale));
			}
		} catch (Exception e) {
			text = defaultValue;
		}

		if (StringKit.notBlank(paras)) {
			// 若是tag中指定了paras,則將paras解析爲array
			String[] attrs = paras.split(",");
			Object[] values = new Object[attrs.length];

			// 循環將參數到Request中取值,若是有值,則替換
			for (int i = 0; i < attrs.length; i++) {
				String a = attrs[i];
				values[i] = pageContext.getRequest().getAttribute(a) == null ? attrs[i] : pageContext
						.getRequest().getAttribute(a);
			}

			pageContext.getAttribute("");

			text = String.format(text, values);
		}

		try {
			// 將結果輸出到頁面
			pageContext.getOut().write(text);
		} catch (IOException e) {
			return Tag.SKIP_BODY;
		}

		return Tag.EVAL_BODY_INCLUDE;
	}

	public String getKey() {
		return this.key;
	}

	public void setKey(String key) {
		this.key = key;
	}

	public String getDefaultValue() {
		return this.defaultValue;
	}

	public void setDefaultValue(String defaultValue) {
		this.defaultValue = defaultValue;
	}

	public String getLocale() {
		return this.locale;
	}

	public void setLocale(String locale) {
		this.locale = locale;
	}

	public String getParas() {
		return this.paras;
	}

	public void setParas(String paras) {
		this.paras = paras;
	}


3.2 Jfinal.tld

    文件與I18nTag.java放在同一目錄下:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE taglib PUBLIC "-//Sun Microsystems, Inc.//DTD JSP Tag Library 1.1//EN" "http://java.sun.com/j2ee/dtds/web-jsptaglibrary_1_1.dtd">
<taglib>
    <tlibversion>1.0</tlibversion>
    <jspversion>1.1</jspversion>
    <shortname>bean</shortname>
    <uri>http://www.jfinal.com/tag</uri>
    <tag>
        <name>i18n</name>
        <tagclass>com.jfinal.tag.I18nTag</tagclass>
        <bodycontent>JSP</bodycontent>
        <attribute>
            <name>key</name>
            <required>true</required>
            <rtexprvalue></rtexprvalue>
        </attribute>
        <attribute>
            <name>defaultValue</name>
            <required>false</required>
            <rtexprvalue></rtexprvalue>
        </attribute>
        <attribute>
            <name>paras</name>
            <required>false</required>
            <rtexprvalue></rtexprvalue>
        </attribute>
        <attribute>
            <name>locale</name>
            <required>false</required>
            <rtexprvalue></rtexprvalue>
        </attribute>
    </tag>
</taglib>


4. Tag的使用

4.1 定義多國語言屬性文件

  •         myi18n_en_US.properties

greeting=Today is %2$s/%3$s/%1$s


  •         myi18n_zh_CN.properties

greeting=今天是%1$s年%2$s月%3$s日


4.2 啓動時加載I18

在JFinalConfig.configConstant(Constants me)中加入以下代碼:

// 載入I18N文件
me.setI18n("myi18n", Locale.SIMPLIFIED_CHINESE, Integer.MAX_VALUE);

4.3 在Controller中設置屬性

Calendar c = Calendar.getInstance();
c.setTime(new Date());

this.setAttr("yyyy", c.get(Calendar.YEAR));
this.setAttr("MM", c.get(Calendar.MONTH) + 1);
this.setAttr("dd", c.get(Calendar.DAY_OF_MONTH));

4.4 JSP頁面中定義標籤

<%@ taglib prefix="jf" uri="/WEB-INF/classes/com/jfinal/tag/jfinal.tld"%>

<h5><jf:i18n key="non_key" defaultValue="沒有key值顯示我" paras="2014,7,8" /></h5>
<h5><jf:i18n key="greeting" defaultValue="沒有key值顯示我" paras="2014,7,8"  locale="zh_CN"/></h5>
<h5><jf:i18n key="greeting" defaultValue="沒有key值顯示我" paras="2014,7,8"  locale="en_US" /></h5>
<h5><jf:i18n key="greeting" defaultValue="沒有key值顯示我" paras="yyyy,MM,dd"  locale="en_US" /></h5>

    首先引入標籤,引入的是標籤訂義文件tld的位置,編譯後,tld的位置爲"/WEB-INF/classes/com/jfinal/tag/jfinal.tld",它也是目標位置。


4.5 執行結果


5. 問題

細心的讀者可能已經發現了,paras參數是爲替換{0},{1}這類型參數,結果卻替換了%1$s年%2$s這樣的參數。這是由於代碼使用String.format()格式化,殊不知爲何不能支持{0},{1}。做者沒時間去探究,哪位讀者有時間幫我找出答案吧。

相關文章
相關標籤/搜索