要支持國際化,需要在容器初始化的時候配置一個處理國際化的全局攔截器。比如可以使用 com.jfinal.i18n.I18nInterceptor
配置攔截器:
public class MppConfig extends JFinalConfig {
/**
* 配置全局攔截器 GlobalInterceptor
*/
public void configInterceptor(Interceptors me) {
me.add(new I18nInterceptor());
}
}
action 請求被攔截,進入 intercept 處理:
public class I18nInterceptor implements Interceptor {
private String localeParaName = "_locale";
private String resName = "_res";
private boolean isSwitchView = false;
public I18nInterceptor() {
}
public I18nInterceptor(String localeParaName, String resName) {
if (StrKit.isBlank(localeParaName))
throw new IllegalArgumentException("localeParaName can not be blank.");
if (StrKit.isBlank(resName))
throw new IllegalArgumentException("resName can not be blank.");
this.localeParaName = localeParaName;
this.resName = resName;
}
public I18nInterceptor(String localeParaName, String resName, boolean isSwitchView) {
this(localeParaName, resName);
this.isSwitchView = isSwitchView;
}
// ...
/**
* Return the baseName, which is used as base name of the i18n resource file.
*/
protected String getBaseName() {
return I18n.defaultBaseName;
}
/**
* 1: use the locale from request para if exists. change the locale write to the cookie
* 2: use the locale from cookie para if exists.
* 3: use the default locale
* 4: use setAttr(resName, resObject) pass Res object to the view.
*/
public void intercept(Invocation inv) {
Controller c= inv.getController();
String localeParaName= getLocaleParaName();
String locale= c.getPara(localeParaName);
if (StrKit.notBlank(locale)) { // change locale, write cookie
c.setCookie(localeParaName, locale, Const.DEFAULT_I18N_MAX_AGE_OF_COOKIE);
}
else { // get locale from cookie and use the default locale if it is null
locale = c.getCookie(localeParaName);
if (StrKit.isBlank(locale))
locale= I18n.defaultLocale;
}
if (isSwitchView) {
switchView(locale, c);
}
else {
Res res= I18n.use(getBaseName(), locale);
c.setAttr(getResName(), res);
}
inv.invoke();
}
/**
* 在有些 web 系統中,頁面需要國際化的文本過多,並且 css 以及 html 也因為際化而大不相同,
* 對於這種應用場景先直接制做多套同名稱的國際化視圖,並將這些視圖以 locale 為子目錄分類存放,
* 最後使用本攔截器根據 locale 動態切換視圖,而不必對視圖中的文本逐個進行國際化切換,省時省力。
*/
public void switchView(String locale, Controller c) {
Render render= c.getRender();
if (render != null) {
String view= render.getView();
if (view != null) {
if (view.startsWith("/"))
view= "/" + locale + view;
else
view= locale + "/" + view;
render.setView(view);
}
}
}
}
View Code
根據地區不同得到 local 是不同的(比如中國大陸是 zh_CN,香港是 zh_HK,美國是 en-US),而 getBaseName() 是不變的即 i18n,將 local 和 baseName 進行拼接就能得到資源文件的名字,並對 Res 進行實例化。
controller.setAttr("_res" , res);
國際化資源文件
i18n_zh_CN.properties
msg=\u4F60\u597D{0}, \u4ECA\u5929\u662F{1}
i18n_en_US.properties
msg=Hello {0}, today is{1}.
Freemarker 展現:
${_res.msg!}
----- End -----