简体   繁体   English

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

[英]Localized images in JSF 2.0 application

I have a JSF 2.0 application which allows the user to change the site's language which should affect both texts and images.我有一个 JSF 2.0 应用程序,它允许用户更改应该影响文本和图像的站点语言。

Currently the locale is set in a session bean and each page has with locale set from this session bean.当前区域设置在 session bean 中设置,并且每个页面都具有从该 session bean 设置的区域设置。 It works great for texts.它适用于文本。 But I have trouble with images.但是我对图像有问题。 Currently we are using images like this:目前我们正在使用这样的图像:

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

This leads to generation of the following HTML code returned to the user agent:这导致生成以下 HTML 代码返回给用户代理:

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

Let's assume that the user requests the page in English.假设用户请求英文页面。 The GET request for the image above is processed by ResourceHandler.handleResourceRequest().上图的 GET 请求由 ResourceHandler.handleResourceRequest() 处理。 It uses ViewHandler.calculateLocale() to identify the correct locale prefix.它使用 ViewHandler.calculateLocale() 来识别正确的语言环境前缀。 I have implemented my own ViewHandler with calculateLocale() that retrieves the locale from the user's session.我已经使用 calculateLocale() 实现了我自己的 ViewHandler,它从用户的 session 中检索语言环境。 As a result it correctly creates a resource instance which points to "/resources/english/img/flag.gif" .结果,它正确地创建了一个指向"/resources/english/img/flag.gif"的资源实例。 Then the user changes his/her locale to french.然后用户将他/她的语言环境更改为法语。 When the page is reloaded, the same image URL is rendered and requested.重新加载页面时,会渲染并请求相同的图像 URL。 This time ViewHandler.calculateLocale() returns Locale.FRENCH to the ResourceHandler which results in the creation of resource with path "/resources/french/img/flag.gif" .这一次 ViewHandler.calculateLocale() 将 Locale.FRENCH 返回给 ResourceHandler,从而创建路径为"/resources/french/img/flag.gif"的资源。

Before streaming the image, according to the specification, the ResourceHandler.handleResourceRequest() must do the following:在流式传输图像之前,根据规范,ResourceHandler.handleResourceRequest() 必须执行以下操作:

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

It detects that the resource is not updated since the previous browser request - not taking into account that the previous request to this "logical" URL lead to different "physical" resource on the server.它检测到资源自上次浏览器请求以来未更新 - 不考虑到此“逻辑” URL 的先前请求导致服务器上的不同“物理”资源。 And returns HTTP 304 which leads to the previous English image displayed again to the user.并返回 HTTP 304 导致之前的英文图像再次显示给用户。

If the page is refreshed with Shift+F5, the french image is correctly downloaded since no "If-Modified-Since" is sent by the user agent.如果使用 Shift+F5 刷新页面,则由于用户代理未发送“If-Modified-Since”,因此正确下载了法语图像。

There is always the possibility to add the locale prefix manually with EL in the library name like this:总是可以在库名称中手动添加带有 EL 的语言环境前缀,如下所示:

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

But I still think that the former approach should work and is cleaner.但我仍然认为前一种方法应该有效并且更清洁。

I am wondering:我想知道:

  1. Why doesn't JSF produce a "src" that is the actual path to the image in case we use "name" and "library" attributes for?如果我们使用“名称”和“库”属性,为什么 JSF 不生成作为图像实际路径的“src”? JSF has all the information to build the full path on the initial page request - including the locale form the UIViewRoot (no need to implement my own ViewHandler). JSF 具有在初始页面请求上构建完整路径的所有信息 - 包括 UIViewRoot 的语言环境(无需实现我自己的 ViewHandler)。 My assumption is that it is because according to the specification resources can also be put in a JAR in the class path.我的假设是,这是因为根据规范,资源也可以放在 class 路径中的 JAR 中。 Still the url to the servlet could be rendered only for retrieving the class path located resources for which no direct url can be given.仍然可以将 url 呈现给 servlet,仅用于检索 class 路径定位的资源,不能直接给出 url。

  2. Why does the specification state that the generated image "src" attribute should include the library but says nothing about the locale prefix (see Resource.getReqestPath())?为什么规范 state 生成的图像“src”属性应该包含库,但没有说明语言环境前缀(参见 Resource.getReqestPath())? The Image src is retrieved by Resource.getRequestPath(). Image src 由 Resource.getRequestPath() 检索。 If the prefix was included in the URL french and english images would not be interpreted by the browser as a single "modified" resource.如果前缀包含在 URL 中,则浏览器不会将法语和英语图像解释为单个“修改”资源。

Any ideas are welcome!欢迎任何想法!

Actually, you can just as well use regular HTML <img> tag and build your own path.实际上,您也可以使用常规的 HTML <img>标签并构建自己的路径。
It seems that it is best to create your own Controller for resolving paths:似乎最好创建自己的 Controller 来解析路径:

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

Localization Controller could read the context path (the base URL of the current application) like this:本地化 Controller 可以像这样读取上下文路径(当前应用程序的基础 URL):

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

ExternalContext also provides real path name (ie the one on disk, if you use exploded format) – see getRealPath() method, should you ever needed. ExternalContext还提供真实的路径名(即磁盘上的路径名,如果您使用分解格式)——如果您需要,请参阅getRealPath()方法。

Why I prefer this method?为什么我更喜欢这种方法? It is extremely simple and pretty powerful: one can use Localization Controller not just to provide paths to localized objects like CSS files (or at least main style sheet overrides), client-side scripts and of course images, but also to actually provide dynamic localizable context (ie arrays of translatable strings in JavaScript).它非常简单且非常强大:可以使用本地化 Controller 不仅提供本地化对象的路径,例如 CSS 文件(或至少主要样式表覆盖)、客户端脚本和当然图像,还可以实际提供动态可本地化上下文(即 JavaScript 中可翻译字符串的 arrays)。

To answer your specific questions:要回答您的具体问题:

  1. The short answer is I don't know.简短的回答是我不知道。 I'd love to think about it that somebody who designed this API carefully weighted all pros and cons and chose optimal solution (although not satisfying every possible Use Case).我想考虑一下,设计此 API 的人仔细权衡了所有优缺点并选择了最佳解决方案(尽管不能满足所有可能的用例)。

  2. For that I can give you precise answer.为此,我可以给你准确的答案。 Basically, correctly Internationalized application should not contain any image that might depend on Locale, ie be culture-specific.基本上,正确的国际化应用程序不应包含任何可能依赖于区域设置的图像,即特定于文化的图像。 This is quite idealistic view of the world but to be honest having image that actually depends on Locale should be rare case.这是一种非常理想化的世界观,但说实话,拥有实际上依赖于 Locale 的图像应该很少见。
    If I understood your specific problem, you want to switch some specific country flag based on current Locale.如果我了解您的具体问题,您想根据当前的语言环境切换一些特定的国家标志。 In fact, you can just as well use conditional rendering here ( render="#{someController.someBooleanMethod}" ) and actually write all image references at once.事实上,您也可以在这里使用条件渲染 ( render="#{someController.someBooleanMethod}" ) 并实际一次编写所有图像引用。 I know it sucks but this is one viable solution.我知道这很糟糕,但这是一种可行的解决方案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM