JSF 2.0应用程序中的本地化映像

时间:2011-08-12 07:12:33

标签: image jsf localization jsf-2

我有一个JSF 2.0应用程序,允许用户更改应影响文本和图像的网站语言。

目前,语言环境是在会话bean中设置的,每个页面都具有从此会话bean设置的语言环境。它适用于文本。但我的图像有问题。目前我们正在使用这样的图像:

<h:graphicImage name="flag.gif" library="img">

这会导致生成返回给用户代理的以下HTML代码:

<img src="/AppRoot/faces/javax.faces.resource/flag.gif?ln=img" .... />

我们假设用户用英语请求页面。上面图像的GET请求由ResourceHandler.handleResourceRequest()处理。它使用ViewHandler.calculateLocale()来标识正确的区域设置前缀。我用calculateLocale()实现了我自己的ViewHandler,它从用户的会话中检索语言环境。因此,它正确地创建了一个指向“/ resources / english / img / flag.gif”的资源实例。然后用户将他/她的语言环境更改为法语。重新加载页面时,将呈现并请求相同的图像URL。这次ViewHandler.calculateLocale()将Locale.FRENCH返回给ResourceHandler,导致创建路径为“/ resources / french / img / flag.gif”的资源。

在流式传输图像之前,根据规范,ResourceHandler.handleResourceRequest()必须执行以下操作:

  

•调用Resource.userAgentNeedsUpdate(javax.faces.context.FacesContext)。如果此方法返回false,则必须将HttpServletRequest.SC_NOT_MODIFIED传递给HttpServletResponse.setStatus(),然后handleResourceRequest必须立即返回。

它检测到自上次浏览器请求以来资源未更新 - 未考虑先前对此“逻辑”URL的请求导致服务器上的不同“物理”资源。并返回HTTP 304,这将导致先前的英文图像再次显示给用户。

如果使用Shift + F5刷新页面,则会正确下载法语图像,因为用户代理不会发送“If-Modified-Since”。

总是可以在库名中手动添加区域设置前缀,如下所示:

<h:graphicImage library="#{userContext.locale}/img" name="flag.gif" />

但我仍然认为前一种方法应该有效并且更清洁。

我想知道:

  1. 为什么JSF不生成“src”,这是我们使用“name”和“library”属性的实际路径? JSF拥有构建初始页面请求的完整路径的所有信息 - 包括UIViewRoot的区域设置(无需实现我自己的ViewHandler)。我的假设是因为根据规范资源也可以放在类路径中的JAR中。仍然可以呈现servlet的url,仅用于检索没有直接url的类资源的路径。

  2. 为什么规范声明生成的图像“src”属性应该包含库但是没有说明语言环境前缀(请参阅Resource.getReqestPath())? Image src由Resource.getRequestPath()检索。如果前缀包含在URL中,则英语图像不会被浏览器解释为单个“已修改”资源。

  3. 欢迎任何想法!

1 个答案:

答案 0 :(得分:2)

实际上,您也可以使用常规HTML <img>标记并构建自己的路径 似乎最好创建自己的Controller来解析路径:

<img alt="#{i18n['some.image.title']}" src="#{localizationController.someImage}" />

Localization Controller可以读取上下文路径(当前应用程序的基本URL),如下所示:

String basePath = FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath();

ExternalContext还提供真实路径名(即磁盘上的名称,如果您使用分解格式) - 如果需要,请参阅getRealPath()方法。

为什么我更喜欢这种方法?它非常简单且非常强大:可以使用Localization Controller来提供到CSS文件(或至少主要样式表覆盖),客户端脚本和当然图像等本地化对象的路径,还可以实际提供动态可本地化上下文(即JavaScript中可翻译字符串的数组)。

回答您的具体问题:

  1. 简短的回答是我不知道。我很乐意考虑设计这个API的人仔细权衡所有优缺点并选择最佳解决方案(尽管不满足所有可能的用例)。

  2. 为此,我可以给你准确的答案。基本上,正确的国际化应用程序不应包含任何可能依赖于区域设置的图像,即特定于文化的图像。这是一个非常理想化的世界观,但说实话,实际上依赖于Locale的形象应该是罕见的情况 如果我了解您的具体问题,您希望根据当前的区域设置切换某个特定的国家/地区标记。实际上,你也可以在这里使用条件渲染(render="#{someController.someBooleanMethod}")并实际写入所有图像引用。我知道这很糟糕,但这是一个可行的解决方案。