提问人:sergionni 提问时间:1/29/2011 最后编辑:BalusCsergionni 更新时间:1/11/2022 访问量:52791
JSF 中的本地化,如何记住每个会话而不是每个请求/视图的选定语言环境
Localization in JSF, how to remember selected locale per session instead of per request/view
问:
faces-config.xml
:
<application>
<locale-config>
<default-locale>ru</default-locale>
<supported-locale>ua</supported-locale>
</locale-config>
</application>
在 Bean 操作方法中,我将更改当前视图中的语言环境,如下所示:
FacesContext.getCurrentInstance().getViewRoot().setLocale(new Locale("ua"));
问题是应用了 Locale,但仅针对每个请求/视图,而不是针对会话。同一会话中的另一个请求/视图将区域设置重置回默认值。ua
ru
如何为会话应用区域设置?
答:
您需要将选定的区域设置存储在会话作用域中,并在 viewroot 中的两个位置设置它:一次是在更改区域设置后立即通过 UIViewRoot#setLocale()
设置的(这会更改当前 viewroot 的区域设置,从而反映在回发中;之后执行重定向时不需要此部分),一次是在 <f 的属性中:view>
(在后续请求/视图中设置/保留区域设置)。locale
下面是一个示例,这样的应该是什么样子的:LocaleBean
package com.example.faces;
import java.util.Locale;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.FacesContext;
@ManagedBean
@SessionScoped
public class LocaleBean {
private Locale locale;
@PostConstruct
public void init() {
locale = FacesContext.getCurrentInstance().getExternalContext().getRequestLocale();
}
public Locale getLocale() {
return locale;
}
public String getLanguage() {
return locale.getLanguage();
}
public void setLanguage(String language) {
locale = new Locale(language);
FacesContext.getCurrentInstance().getViewRoot().setLocale(locale);
}
}
下面是视图的示例,如下所示:
<!DOCTYPE html>
<html lang="#{localeBean.language}"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:h="http://java.sun.com/jsf/html">
<f:view locale="#{localeBean.locale}">
<h:head>
<title>JSF/Facelets i18n example</title>
</h:head>
<h:body>
<h:form>
<h:selectOneMenu value="#{localeBean.language}" onchange="submit()">
<f:selectItem itemValue="en" itemLabel="English" />
<f:selectItem itemValue="nl" itemLabel="Nederlands" />
<f:selectItem itemValue="es" itemLabel="Español" />
</h:selectOneMenu>
</h:form>
<p><h:outputText value="#{text['some.text']}" /></p>
</h:body>
</f:view>
</html>
它假设已经配置如下:#{text}
faces-config.xml
<application>
<resource-bundle>
<base-name>com.example.i18n.text</base-name>
<var>text</var>
</resource-bundle>
</application>
请注意,JSF 的运行不需要,但搜索机器人如何解释您的页面是强制性的。否则,它可能会被标记为重复内容,这对SEO不利。<html lang>
另请参阅:
- Maven 和 JSF webapp 结构,确切地将 JSF 资源放在哪里
- JSF 中的国际化,何时使用 message-bundle 和 resource-bundle?
- i18n 在 JSF 2.0 应用程序中具有 UTF-8 编码的属性文件
评论
<f:view>
UIViewRoot
我看到问题也出在.properties文件名上。 Java 语言环境 us 代码(小写),例如:en_gb 但是自动创建的语言环境(由 Netbeans 创建)是lowercase_uppercase的,即:messages_en_GB.properties 将名称更改为:messages_en_gb.properties 它应该有效 - 如果你尝试了一切
如果可以在环境中使用 CDI 和 deltaspike(JSF 模块),则可以将以下内容添加到环境中,以自动重置当前视图上的语言环境:LocaleBean
@javax.enterprise.context.SessionScoped
public class LocaleBean implements Serializable {
...
public void resetLocale(@Observes @BeforePhase(JsfPhaseId.RENDER_RESPONSE) PhaseEvent event) {
event.getFacesContext().getViewRoot().setLocale(this.locale);
}
}
这个组件 f:view 不在您的 JSF 页面中,它将不起作用,它只会显示默认的英语语言。为此 f:view 组件提供 localae 值,然后它就可以正常工作了。我现在遇到了同样的问题,它工作正常。
一句小话@BalusC很好的解决方案。如果我们有,在后备 bean 中执行一些方法。从调用到该方法内部可用的区域设置是由用户浏览器或默认应用程序区域设置的区域设置,而不是由用户选择在会话 Bean 上设置的区域设置(当然,如果浏览器区域设置等于用户选择的区域设置,它们可以匹配)。<f:viewAction>
FacesContext.getCurrentInstance().getViewRoot().getLocale()
我可以纠正,因为也许我在实施@BalusC提供的解决方案时做错了什么。
编辑。在使用 JSF 生命周期之后,locale 的这种行为与 无关,因为 也有类似的行为。 在请求中(在用户选择语言环境之后)在渲染响应阶段执行。 方法在调用应用程序阶段执行。这就是在此方法中执行的逻辑无权访问用户选择的区域设置的原因。<f:viewAction>
@PostContruct
<f:view locale="#{localeBean.locale}">
<f:viewAction>
@PostContruct
当我们需要正确的语言环境时,我们使用的解决方案是将 (CDI) 注入包含 和 方法的其他后备 Bean 中,然后从这些方法的开头设置语言环境。localeBean
<f:viewAction>
@PostContruct
UIViewRoot#setLocale()
localeBean
评论
f:viewAction
评论