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

Iri*_*ina 9 jsf localization image jsf-2

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

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

<h:graphicImage name="flag.gif" library="img">
Run Code Online (Sandbox Code Playgroud)

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

<img src="/AppRoot/faces/javax.faces.resource/flag.gif?ln=img" .... />
Run Code Online (Sandbox Code Playgroud)

假设用户用英语请求页面.上面图像的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" />
Run Code Online (Sandbox Code Playgroud)

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

我想知道:

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

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

欢迎任何想法!

Paw*_*yda 2

实际上,您也可以使用常规 HTML<img>标签并构建自己的路径。
\n看来最好创建自己的控制器来解析路径:

\n\n
<img alt="#{i18n[\'some.image.title\']}" src="#{localizationController.someImage}" />\n
Run Code Online (Sandbox Code Playgroud)\n\n

本地化控制器可以像这样读取上下文路径(当前应用程序的基本 URL):

\n\n
String basePath = FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath();\n
Run Code Online (Sandbox Code Playgroud)\n\n

getRealPath()如果您需要,ExternalContext还提供真实路径名(即磁盘上的路径名,如果您使用展开格式) \xe2\x80\x93 see方法。

\n\n

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

\n\n

回答您的具体问题:

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

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

  4. \n
\n