实现在JSF和JAX-RS中工作的Locale提供程序

时间:2013-09-03 14:14:18

标签: jsf localization jax-rs resteasy omnifaces

我一直很高兴使用omnifaces'Faces.getLocale()来获取当前登录用户使用的区域设置(这反过来从<f:view>定义获得)。我非常喜欢从视图到客户端到系统默认语言环境的回退方法,因为它符合我的应用程序中区域设置选择的要求:

  1. 如果用户已登录,请使用其语言首选项(从后端实体获取)
  2. 如果找不到用户首选项,请使用Accept-Languages HTTP标头
  3. 中排名最高的语言
  4. 如果现在没有选择区域设置,请使用系统默认值。
  5. 现在我已经开始使用JAX-RS(resteasy实现),并且发现编写一个能够为我的后端代码提供当前用户的语言环境的服务非常困难。

    我无法使用Faces.getLocale(),因为这需要{J} -J请求处理期间不存在的FacesContext

    我不能在@Context SecurityContext中使用@Provider注释(这会给我用户首选的区域设置)或@Context HttpHeaders(访问客户端区域设置),因为仅限JAX-RS当它使用提供者本身时注入那些,而不是在我的后端代码实例化类时。

    我不希望使用Locale参数丢弃我的方法签名,因为虚拟所有都需要一个区域设置。

    举一个具体的例子:我有一个vcard生成器,根据用户的首选语言环境生成很少的NOTE字段。我可以通过JSF / EL调用vcard生成方法:

    <h:commandLink action="#{vcfGenerator.forPerson(person)}" 
        value="Go" target="_blank" />
    

    通过REST服务:

    @GET @Path('person/{id:[1-9][0-9]*}/vcard')
    @Produces('text/vcard')
    String exportVcard(@PathParam('id') Long personId, @Context HttpHeaders headers) {
        VcfGenerator exporter = Component.getInstance(VcfGenerator) as VcfGenerator
    
        Person person = entityManager.find(Person, personId)
        if (! person)
            return Response.noContent().build()
    
        def locale = headers.acceptableLanguages[0] ?: Locale.ROOT
        return exporter.generateVCF(person, locale).toString()
    }
    

    这可行(VcfGenerator有一组仅使用Faces.getLocale()的JSF方法,但是很难维护。所以我不想传递Locale对象,而是想说:

    Vcard generateVCF(Person person) {
        Locale activeLocale = LocaleProvider.instance().getContext(VcfGenerator.class)
        ResourceBundle bundle = ResourceBundle.getBundle("messages", activeLocale, new MyControl())
        // use bundle to construct the vcard
    }
    

    有没有人做过类似的工作并可以分享见解?

1 个答案:

答案 0 :(得分:0)

我知道这篇文章已经发布了一段时间,但是因为它没有被标记为已经解决,所以我在这个具体案例中找到了解决方法:

  • 首先我得到了一个自定义ResourceBundle,正如@BalusC所述:http://balusc.blogspot.fr/2010/10/internationalization-in-jsf-with-utf-8.html
  • 然后我更新了构造函数,以便检测FacesContext当前是否正在使用,由此:

    public Text() {
        setParent(ResourceBundle.getBundle(BUNDLE_NAME, 
        FacesContext.getCurrentInstance().getViewRoot().getLocale(), UTF8_CONTROL));
    }
    
  • To This:

    public Text() {
        FacesContext ctx = FacesContext.getCurrentInstance();
        setParent(ResourceBundle.getBundle(BUNDLE_NAME, 
        ctx != null ? ctx.getViewRoot().getLocale() : Locale.ENGLISH, UTF8_CONTROL));
    }
    

现在可以在JSF和JAX-RS上下文中使用。

希望得到这个帮助,