JSF/Facelets의 국제화된 레이블
-
01-07-2019 - |
문제
하다 페이스렛 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에 나쁜 이름을 주는 종류의 일입니다.
해결책
다음과 같이 자신만의 얼굴 태그 라이브러리를 만들어 덜 장황하게 만들 수 있습니다.
<ph:i18n key="label.widget.count" p0="#{widgetCount}"/>
그런 다음 뷰 디렉터리에 taglib를 만듭니다./구성 요소/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>
/comComponents/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에 새 taglib를 등록하십시오.
<context-param>
<param-name>facelets.LIBRARIES</param-name>
<param-value>
/components/ph.taglib.xml
</param-value>
</context-param>
그냥 추가하세요 xmlns:ph="http://peterhilton.com/core"
귀하의 견해에 따라 모든 준비가 완료되었습니다!
다른 팁
Seam을 사용하고 있으므로 EL을 사용할 수 있습니다 메시지 파일에 있습니다.
재산:
label.widget.count = You have a total of #{widgetCount} widgets.
XHTML:
<h:outputFormat value="#{messages['label.widget.count']}" />
이것은 여전히 outputFormat을 사용하지만 덜 장황합니다.
나는 OutputFormat 이외의 다른 방법을 본 적이 없습니다.불행히도 매우 장황합니다.
내가 제안할 수 있는 유일한 다른 방법은 Backing Bean에서 메시지를 생성한 다음 messageFormat 대신 이를 출력하는 것입니다.
내 경우에는 JSF와 통합된 Spring의 MessageSource를 사용합니다. MessageSourcePropertyResolver).그러면 Backing Bean에서 매개변수화된 메시지를 얻는 것이 매우 쉽습니다. 사용자가 어떤 Locale에 있는지 알기만 하면 됩니다. (역시 JSF 또는 Java를 통해 액세스할 수 있도록 Backing Bean 속성에 바인딩된 Locale이 있습니다.)
내 생각에는 매개변수(특히 메시지의 경우)가 JSF가 실제로 더 잘할 수 있는 일 중 하나라고 생각합니다!
나는 이것에 대해 더 많이 생각해 왔으며 아마도 메시지 키와 가변 개수의 매개 변수를 사용하는 내 자신의 JSTL 함수를 작성할 수 있다는 생각이 들었습니다.
<h:outputText value="#{my:message('label.widget.count', widgetCount)}"/>
내 메시지 기능이 출력 전에 결과를 HTML로 인코딩하는 경우 h:outputText를 사용할 필요조차 없습니다.
#{my:message('label.widget.count', widgetCount)}
Seam Interpolator를 사용할 수 있습니다.
<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>
ResourceBundle 및 속성 파일을 사용하십시오.