要支持国际化,需要在容器初始化的时候配置一个处理国际化的全局拦截器。比如可以使用 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 展现: