因爲JFinal的國際化(I18N)支持在JSP中支持很差,所以,萌生了解決這一短板的念頭。php
實現時也考慮了幾種方式,最終決定採用JSP中最原始的標籤。由於自定義標籤在JSP中容易實現,內容靈活且功能比較強大,可擴展性好。html
自定義的I18N標籤須要針對I18N的各個接口作最好的支持,使用<jf:i18n />做爲標籤名,下面是JFinal中I18N類的幾個接口:前端
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(「p2」, 「I18N標籤」);標籤中的paras取值爲「p1,p2」,尋麼最終結果仍是「早上好!小白們,如今正實驗I18N標籤。」 |
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; }
文件與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>
myi18n_en_US.properties
greeting=Today is %2$s/%3$s/%1$s
myi18n_zh_CN.properties
greeting=今天是%1$s年%2$s月%3$s日
在JFinalConfig.configConstant(Constants me)中加入以下代碼:
// 載入I18N文件 me.setI18n("myi18n", Locale.SIMPLIFIED_CHINESE, Integer.MAX_VALUE);
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));
<%@ 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",它也是目標位置。
細心的讀者可能已經發現了,paras參數是爲替換{0},{1}這類型參數,結果卻替換了%1$s年%2$s這樣的參數。這是由於代碼使用String.format()格式化,殊不知爲何不能支持{0},{1}。做者沒時間去探究,哪位讀者有時間幫我找出答案吧。