Локализованные изображения в приложении JSF 2.0 - PullRequest
8 голосов
/ 12 августа 2011

У меня есть приложение JSF 2.0, которое позволяет пользователю изменять язык сайта, который должен влиять как на текст, так и на изображения.

В настоящее время языковой стандарт задается в сессионном компоненте, и каждая страница имеет языковой стандарт, установленный из этого сессионного компонента.Это прекрасно работает для текстов.Но у меня проблемы с изображениями.В настоящее время мы используем такие изображения:

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

Это приводит к генерации следующего HTML-кода, возвращаемого пользовательскому агенту:

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

Предположим, что пользователь запрашивает страницу вАнглийский.Запрос GET для изображения выше обрабатывается ResourceHandler.handleResourceRequest ().Он использует ViewHandler.calculateLocale () для определения правильного префикса локали.Я реализовал свой собственный ViewHandler с помощью CalculayLocale (), который получает локаль из сеанса пользователя.В результате он правильно создает экземпляр ресурса, который указывает на "/ 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» не отправляетсяпользовательским агентом.

Всегда есть возможность добавить префикс локали вручную с EL в имени библиотеки следующим образом:

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

Но я все еще думаю, что прежний подход должен работатьи это чище.

Мне интересно:

  1. Почему JSF не создает "src", который является реальным путем к изображению, если мы используем "name"атрибуты "и" библиотека "для?JSF имеет всю информацию для построения полного пути на начальном запросе страницы, включая локаль из UIViewRoot (нет необходимости реализовывать мой собственный ViewHandler).Я предполагаю, что это потому, что согласно спецификации ресурсы также могут быть помещены в JAR в пути к классам.Тем не менее, URL-адрес сервлета может быть обработан только для получения ресурсов, расположенных на пути к классам, для которых не может быть указан прямой URL-адрес.

  2. Почему в спецификации указано, что сгенерированное изображение "src"атрибут должен включать библиотеку, но ничего не говорит о префиксе локали (см. Resource.getReqestPath ())?Изображение src извлекается Resource.getRequestPath ().Если префикс включен в URL, французские и английские изображения не будут интерпретироваться браузером как единый «модифицированный» ресурс.

Любые идеи приветствуются!

1 Ответ

2 голосов
/ 13 августа 2011

На самом деле, вы также можете использовать обычный тег HTML <img> и создать свой собственный путь.
Кажется, что лучше всего создать свой собственный контроллер для разрешения путей:

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

Контроллер локализации может прочитать контекстный путь (базовый URL текущего приложения) следующим образом:

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

ExternalContext также предоставляет реальное имя пути (т. Е. На диске, если вы используете разнесенный формат) - см. Метод getRealPath(), если вам когда-либо понадобится.

Почему я предпочитаю этот метод? Это чрезвычайно просто и довольно мощно: можно использовать Localization Controller не только для предоставления путей к локализованным объектам, таким как файлы CSS (или, по крайней мере, переопределения основных таблиц стилей), клиентские сценарии и, конечно, изображения, но также для обеспечения динамической локализации контекст (т.е. массивы переводимых строк в JavaScript).

Чтобы ответить на ваши конкретные вопросы:

  1. Краткий ответ: я не знаю. Мне бы хотелось подумать, что кто-то, кто разработал этот API, тщательно взвесил все за и против и выбрал оптимальное решение (хотя и не удовлетворяющее все возможные варианты использования).

  2. За это я могу дать вам точный ответ. По сути, правильно интернационализированное приложение не должно содержать изображения, которое может зависеть от локали, то есть быть специфичным для конкретной культуры. Это довольно идеалистический взгляд на мир, но, честно говоря, наличие образа, который на самом деле зависит от локали, должно быть редким случаем.
    Если я понял вашу конкретную проблему, вы хотите изменить флаг определенной страны в зависимости от текущей локали. На самом деле, вы можете использовать условный рендеринг здесь (render="#{someController.someBooleanMethod}") и записывать все ссылки на изображения одновременно. Я знаю, что это отстой, но это одно из жизнеспособных решений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...