我有一个 JSF 2.0 应用程序,它允许用户更改网站的语言,这会影响文本和图像。
当前区域设置是在 session bean 中设置的,每个页面都具有从此 session 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,它从用户 session 中检索区域设置。结果,它正确地创建了一个指向“/resources/english/img/flag.gif”的资源实例。然后用户将他/她的区域设置更改为法语。重新加载页面时,将呈现并请求相同的图像 URL。这次 ViewHandler.calculateLocale() 将 Locale.FRENCH 返回给 ResourceHandler,这会导致创建路径为 "/resources/french/img/flag.gif" 的资源。
在流式传输图像之前,根据规范,ResourceHandler.handleResourceRequest() 必须执行以下操作:
•Call Resource.userAgentNeedsUpdate(javax.faces.context.FacesContext). If this method returns false, HttpServletRequest.SC_NOT_MODIFIED must be passed to HttpServletResponse.setStatus(), then handleResourceRequest must immediately return.
它检测到自上次浏览器请求以来资源未更新 - 没有考虑到对该“逻辑”URL 的先前请求导致服务器上不同的“物理”资源。并返回 HTTP 304,这会导致之前的英文图像再次显示给用户。
如果使用 Shift+F5 刷新页面,则可以正确下载法语图像,因为用户代理没有发送“If-Modified-Since”。
始终可以在库名称中使用 EL 手动添加区域设置前缀,如下所示:
<h:graphicImage library="#{userContext.locale}/img" name="flag.gif" />
但我仍然认为前一种方法应该有效并且更干净。
我想知道:
如果我们使用“name”和“library”属性,为什么 JSF 不生成图像的实际路径“src”? JSF 拥有在初始页面请求上构建完整路径的所有信息 - 包括 UIViewRoot 中的区域设置(无需实现我自己的 ViewHandler)。我的假设是,这是因为根据规范资源也可以放在类路径中的 JAR 中。不过,servlet 的 url 只能用于检索类路径定位的资源,而无法为其提供直接 url。
为什么规范规定生成的图像“src”属性应包含库,但没有提及区域设置前缀(请参阅 Resource.getReqestPath())?图像 src 通过 Resource.getRequestPath() 检索。如果前缀包含在 URL 中,法语和英语图像将不会被浏览器解释为单个“已修改”资源。
欢迎任何想法!
最佳答案
实际上,您也可以使用常规 HTML <img>
标记并构建您自己的路径。
看来最好创建自己的 Controller 来解析路径:
<img alt="#{i18n['some.image.title']}" src="#{localizationController.someImage}" />
本地化 Controller 可以像这样读取上下文路径(当前应用程序的基本 URL):
String basePath = FacesContext.getCurrentInstance().getExternalContext().getRequestContextPath();
ExternalContext还提供真实路径名(即磁盘上的路径名,如果您使用分解格式) - 请参阅getRealPath()
方法,如果您需要的话。
为什么我更喜欢这种方法?它非常简单且非常强大:人们不仅可以使用本地化 Controller 来提供本地化对象的路径,例如 CSS 文件(或至少主样式表覆盖)、客户端脚本,当然还有图像,而且还可以实际提供动态本地化上下文(即 JavaScript 中的可翻译字符串数组)。
回答您的具体问题:
简短的回答是我不知道。我很乐意考虑设计此 API 的人仔细权衡所有优点和缺点并选择最佳解决方案(尽管不能满足所有可能的用例)。
对此我可以给你准确的答案。基本上,正确的国际化应用程序不应包含任何可能依赖于区域设置的图像,即特定于文化的图像。这是相当理想主义的世界观,但说实话,具有实际上取决于语言环境的图像应该是罕见的情况。
如果我理解您的具体问题,您想根据当前的区域设置切换一些特定的国家/地区标志。事实上,您也可以在此处使用条件渲染 (render="#{someController.someBooleanMethod}"
),并实际上一次写入所有图像引用。我知道这很糟糕,但这是一种可行的解决方案。
关于image - JSF 2.0 应用程序中的本地化图像,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7036741/