Есть ли в 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 плохая репутация.




Используйте ResourceBundle и файлы свойств.
Я никогда не встречал другого способа сделать это, кроме 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;) Если серьезно, это был бы отличный ресурс, если бы вы могли где-нибудь выпустить его.
Поскольку вы используете Seam, вы можете использовать EL в файле сообщений.
Свойство:
label.widget.count = You have a total of #{widgetCount} widgets.
XHTML:
<h:outputFormat value = "#{messages['label.widget.count']}" />
Он по-прежнему использует outputFormat, но менее подробен.
Единственным ограничением этого подхода является то, что вы привязаны к использованию этой метки с # {widgetCount} или вам нужно явно исключить "widgetCount", чтобы использовать его.
Вы можете создать свою собственную библиотеку тегов лиц, чтобы сделать ее менее подробной, например:
<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" к своим представлениям, и все готово!
Хороший ответ, близкий к тому, что мы сделали до сих пор. Основная проблема в том, что вы не можете использовать его внутри значений атрибутов.
Вы можете использовать Интерполятор швов:
<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>
Будьте осторожны: может возникнуть бесконечная петля, знайте, что вы делаете.
Не могли бы вы объяснить еще немного? Я не понимаю, что вы имеете в виду, поскольку OP уже сказал, что использует это.