JSF 2 本地化(托管 bean)

标签 jsf jsf-2 cdi managed-bean

我有一个用于本地化的属性文件:

foo=Bar
title=Widget Application

这在 faces-config 中作为 resource-bundle 绑定(bind):

<resource-bundle>
    <base-name>com.example.messages.messages</base-name>
    <var>msgs</var>
</resource-bundle>

我可以使用 EL 在 Facelets View 中很好地访问它:

<title>#{msgs.title}</title>

但是,如果存在 SQLException 之类的情况,我需要能够从托管 bean 写入消息。这一切也都有效:

FacesMessage message = new FacesMessage(FacesMessage.SEVERITY_ERROR, "There was an error saving this widget.", null);
FacesContext.getCurrentInstance().addMessage(null, message);

问题是:我希望这些消息来自属性文件,以便它们也可以根据区域设置进行更改。有没有一种简单的方法可以使用注入(inject)来访问属性文件?

最佳答案

我问了一个非常相关的问题: How to inject a non-serializable class (like java.util.ResourceBundle) with Weld

在 Seam 论坛内部: http://seamframework.org/Community/HowToCreateAnInjectableResourcebundleWithWeld

总结一下: 我实现了一个带有 3 个 Producer 的可注入(inject) ResourceBundle。 首先您需要一个 FacesContextProducer。我从 Seam 3 Alpha 源中获取了一个。

public class FacesContextProducer {
   @Produces @RequestScoped
   public FacesContext getFacesContext() {
      FacesContext ctx = FacesContext.getCurrentInstance();
      if (ctx == null)
         throw new ContextNotActiveException("FacesContext is not active");
      return ctx;
   }
}

然后你需要一个 LocaleProducer,它使用 FacesContextProducer。我还从 Seam 3 Alpha 中获取了它。

public class FacesLocaleResolver {
   @Inject
   FacesContext facesContext;

   public boolean isActive() {
      return (facesContext != null) && (facesContext.getCurrentPhaseId() != null);
   }

   @Produces @Faces
   public Locale getLocale() {
      if (facesContext.getViewRoot() != null) 
         return facesContext.getViewRoot().getLocale();
      else
         return facesContext.getApplication().getViewHandler().calculateLocale(facesContext);
   }
}

现在您已具备创建 ResourceBundleProducer 的一切条件,如下所示:

public class ResourceBundleProducer {
  @Inject       
  public Locale locale;

  @Inject       
  public FacesContext facesContext;

  @Produces
  public ResourceBundle getResourceBundle() {
   return ResourceBundle.getBundle("/messages", facesContext.getViewRoot().getLocale() );
  }
}

现在您可以将 ResourceBundle @Inject 到您的 bean 中。请注意,它必须被注入(inject)到 transient 属性中,否则您将收到一个异常,提示 ResourceBundle 不可序列化。

@Named
public class MyBean {
  @Inject
  private transient ResourceBundle bundle;

  public void testMethod() {
    bundle.getString("SPECIFIC_BUNDLE_KEY");
  }
}

关于JSF 2 本地化(托管 bean),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3478073/

相关文章:

java - 如何使用 JSF 将文件上传到 glassfish

jsf-2 - 无法访问 bean 中的内部类

java - 自定义 validator 类不工作

java - CDI:jar 中的接口(interface)无法解析为本地 Wildfly 8.0

java - CDI 不明确的依赖

image - 如何使用 p :graphicImage with StreamedContent within p:dataTable?

java - 如何在 Primefaces 中实现保存按钮

forms - 如何创建 h :selectOneRadio with options of a java list (JSF)?

jakarta-ee - IDEA错误 "Managed bean must be a concrete class, or is annotated with @Decorator"

maven - 在 Maven 中将 Primefaces 从 6.2 升级到 7.0.14