我一直很高兴地使用omnifaces'Faces.getLocale()
获取当前登录用户使用的区域设置(反过来又从<f:view>
定义)。我真的很喜欢从视图到客户端再到系统默认区域设置的后备方法,因为它符合我的应用程序中区域设置选择的要求:
- 如果用户已登录,请使用他的语言首选项(从后端实体获取)
- 如果找不到用户偏好,请使用排名最高的语言
Accept-Languages
HTTP 标头
- 如果目前尚未选择区域设置,则使用系统默认值。
现在我开始使用 JAX-RS(resteasy 实现),并发现编写一个为我的后端代码提供当前用户区域设置的服务非常困难。
我不能使用Faces.getLocale()
,因为这需要一个FacesContext
在 JAX-RS 请求处理期间不存在。
我无法使用@Context SecurityContext
中的注释@Provider
(这会给我用户首选的区域设置)或@Context HttpHeaders
(访问客户端区域设置)因为 JAX-RS 仅在使用提供程序本身时注入这些内容,而不是在我的后端代码实例化该类时注入。
我不想乱扔我的方法签名Locale
参数,因为实际上一切需要存在语言环境。
举一个具体的例子:我有一个 vcard 生成器,它根据用户的首选区域设置生成小注释字段。我可以通过 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
有一组仅 JSF 的方法,使用Faces.getLocale()
),但是维护起来很痛苦。所以不是通过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
}
有没有人做过类似的工作并可以分享见解?