Интернационализированные этикетки в JSF / Facelets

Есть ли в Facelets какие-либо функции для более аккуратных или более читаемых текстовых меток интернационализированного пользовательского интерфейса, которые вы могли бы сделать с помощью JSF?

Например, в обычном JSF использование h: outputFormat - очень подробный способ интерполировать переменные в сообщениях.

Уточнение: Я знаю, что могу добавить запись файла сообщения, которая выглядит так:

label.widget.count = You have a total of {0} widgets.

и отобразите это (если я использую Seam) с помощью:

<h:outputFormat value = "#{messages['label.widget.count']}">
   <f:param value = "#{widgetCount}"/>
</h:outputFormat>

но вывод одного предложения - это много беспорядка - именно из-за этого у JSF плохая репутация.

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
5
0
4 462
7
Перейти к ответу Данный вопрос помечен как решенный

Ответы 7

Используйте ResourceBundle и файлы свойств.

Не могли бы вы объяснить еще немного? Я не понимаю, что вы имеете в виду, поскольку OP уже сказал, что использует это.

Sietse 19.09.2008 12:35

Я никогда не встречал другого способа сделать это, кроме outputFormat. К сожалению, это довольно многословно.

Единственное, что я могу предложить, - это создать сообщение в поддерживающем компоненте и затем вывести его, а не messageFormat.

В моем случае у меня есть Spring MessageSource, интегрированный с JSF (с использованием MessageSourcePropertyResolver). Затем в ваших поддерживающих bean-компонентах довольно легко получать параметризованные сообщения - вам просто нужно знать, в какой Locale находится ваш пользователь (опять же, у меня Locale привязан к свойству резервного bean-компонента, поэтому он доступен через JSF или Java).

Я думаю, что параметры - особенно в сообщениях - это то, что JSF действительно мог бы сделать лучше!

Я думал об этом больше, и мне пришло в голову, что я, вероятно, мог бы написать свою собственную функцию JSTL, которая принимает ключ сообщения и переменное количество параметров:

<h:outputText value = "#{my:message('label.widget.count', widgetCount)}"/>

и если моя функция сообщения HTML-кодирует результат перед выводом, мне даже не нужно было бы использовать h: outputText

#{my:message('label.widget.count', widgetCount)}

Если вы сделаете это и получите работу, пожалуйста, напишите мне teh codez;) Если серьезно, это был бы отличный ресурс, если бы вы могли где-нибудь выпустить его.

user7094 19.09.2008 12:42

Поскольку вы используете Seam, вы можете использовать EL в файле сообщений.

Свойство:

label.widget.count = You have a total of #{widgetCount} widgets.

XHTML:

<h:outputFormat value = "#{messages['label.widget.count']}" />

Он по-прежнему использует outputFormat, но менее подробен.

Единственным ограничением этого подхода является то, что вы привязаны к использованию этой метки с # {widgetCount} или вам нужно явно исключить "widgetCount", чтобы использовать его.

Damo 07.04.2009 16:10
Ответ принят как подходящий

Вы можете создать свою собственную библиотеку тегов лиц, чтобы сделать ее менее подробной, например:

<ph:i18n key = "label.widget.count" p0 = "#{widgetCount}"/>

Затем создайте taglib в своем представлении dir: /components/ph.taglib.xml

<?xml version = "1.0" encoding = "UTF-8"?>
<!DOCTYPE facelet-taglib PUBLIC "-//Sun Microsystems, Inc.//DTD Facelet Taglib 1.0//EN" "https://facelets.dev.java.net/source/browse/*checkout*/facelets/src/etc/facelet-taglib_1_0.dtd">

<facelet-taglib xmlns = "http://java.sun.com/JSF/Facelet">
    <namespace>http://peterhilton.com/core</namespace>

    <tag>
        <tag-name>i18n</tag-name>
        <source>i18n.xhtml</source>
    </tag>

</facelet-taglib>

создать /components/i18n.xhtml

<?xml version = "1.0" encoding = "UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<ui:composition xmlns = "http://www.w3.org/1999/xhtml"
    xmlns:ui = "http://java.sun.com/jsf/facelets"
        xmlns:h = "http://java.sun.com/jsf/html"        
    xmlns:f = "http://java.sun.com/jsf/core">

    <h:outputFormat value = "#{messages[key]}">
            <!-- crude but it works -->
        <f:param value = "#{p0}" />
        <f:param value = "#{p1}" />
        <f:param value = "#{p2}" />
        <f:param value = "#{p3}" />
    </h:outputFormat>

</ui:composition>

Вы, вероятно, сможете найти элегантный способ передачи аргументов, проведя небольшое исследование.

Теперь зарегистрируйте свою новую библиотеку тегов в web.xml

<context-param>
<param-name>facelets.LIBRARIES</param-name>
<param-value>
        /components/ph.taglib.xml
    </param-value>
</context-param>

Просто добавьте xmlns:ph = "http://peterhilton.com/core" к своим представлениям, и все готово!

Хороший ответ, близкий к тому, что мы сделали до сих пор. Основная проблема в том, что вы не можете использовать его внутри значений атрибутов.

Peter Hilton 19.03.2009 19:50

Вы можете использовать Интерполятор швов:

<h:outputText value = "#{interpolator.interpolate(messages['label.widget.count'], widgetCount)}"/>

На нем есть @BypassInterceptors, поэтому производительность должна быть в порядке.

Вы можете использовать Bean напрямую, если интерполируете сообщения.

label.widget.count = You have a total of #{widgetCount} widgets.
label.welcome.message = Welcome to #{request.contextPath}!
label.welcome.url = Your path is ${pageContext.servletContext}.

${messages['label.widget.count']} достаточно.

Этот отлично работает с Spring:

package foo;

import javax.el.ELContext;
import javax.el.ELException;
import javax.el.ExpressionFactory;
import javax.el.ResourceBundleELResolver;
import javax.faces.context.FacesContext;

import org.springframework.web.jsf.el.SpringBeanFacesELResolver;

public class ELResolver extends SpringBeanFacesELResolver {
    private static final ExpressionFactory FACTORY = FacesContext
            .getCurrentInstance().getApplication().getExpressionFactory();
    private static final ResourceBundleELResolver RESOLVER = new ResourceBundleELResolver();

    @Override
    public Object getValue(ELContext elContext, Object base, Object property)
            throws ELException {
        Object result = super.getValue(elContext, base, property);
        if (result == null) {
            result = RESOLVER.getValue(elContext, base, property);
            if (result instanceof String) {
                String el = (String) result;
                if (el.contains("${") | el.contains("#{")) {
                    result = FACTORY.createValueExpression(elContext, el,
                            String.class).getValue(elContext);
                }
            }
        }
        return result;
    }
}

И...

Вам необходимо изменить EL-Resolver в faces-config.xml с org.springframework.web.jsf.el.SpringBeanFacesELResolver на

С Уважением

<el-resolver>foo.ELResolver</el-resolver>

Будьте осторожны: может возникнуть бесконечная петля, знайте, что вы делаете.

Grim 16.02.2014 10:54

Другие вопросы по теме