我的 JSF 应用程序中的 i18n 枚举存在问题。当我开始时,我有枚举,里面定义了文本。但是现在,我有与枚举中的消息包绑定(bind)的键。
我的枚举示例之一:
public enum OrderStatus implements CustomEnum {
PENDING("enum.orderstatus.pending"),
CANCELED("enum.orderstatus.canceled");
/**
* key in message bundle
*/
private String name;
OrderStatus(String name) {
this.name = name;
}
@Override
public String getName() {
return name;
}
}
在 View 层,我使用类似的东西:
<!-- input -->
<h:selectOneMenu value="#{order.status}">
<f:selectItems value="#{flowUtils.orderStatuses}"/>
</h:selectOneMenu>
<!-- output -->
<h:outputText value="#{order.status}"/>
在 Java 中:
public class FlowUtils {
public List<SelectItem> getOrderStatuses() {
ArrayList<SelectItem> l = new ArrayList<SelectItem>();
for(OrderStatus c: OrderStatus.values()) {
// before i18n
// l.add(new SelectItem(c, c.getName()));
// after i18n
l.add(new SelectItem(c, FacesUtil.getMessageValue(c.getName())));
}
return l;
}
}
public class FacesUtil {
public static String getMessageValue(String name) {
FacesContext context = FacesContext.getCurrentInstance();
return context.getApplication().getResourceBundle(context, "m").getString(name);
}
}
它工作得很好,但是当我需要输出
#{order.status}
,我需要转换它。所以我实现了一个转换器,但在转换
String
时遇到了麻烦至Object
在 getAsObject()
方法。网页.xml:
<converter>
<converter-for-class>model.helpers.OrderStatus</converter-for-class>
<converter-class>model.helpers.EnumTypeConverter</converter-class>
</converter>
java :
public class EnumTypeConverter implements Converter {
@Override
public Object getAsObject(FacesContext context, UIComponent comp,
String value) throws ConverterException {
// value = localized value :(
Class enumType = comp.getValueBinding("value").getType(context);
return Enum.valueOf(enumType, value);
}
@Override
public String getAsString(FacesContext context, UIComponent component,
Object object) throws ConverterException {
if (object == null) {
return null;
}
CustomEnum type = (CustomEnum) object;
ResourceBundle messages = context.getApplication().getResourceBundle(context, "m");
String text = messages.getString(type.getName());
return text;
}
}
我现在很纠结。有人知道如何有效地国际化多个枚举吗?
最佳答案
通过转换器传递的值不是您似乎期望的选项标签,而是选项值。最佳实践是不要在模型端执行此操作,而是在 View 端执行此操作,因为模型不需要知道 i18n。
至于方法,您基本上是在不必要地使事情复杂化。从 JSF 1.2 开始,有一个内置的 EnumConverter
它将自动启动,从 JSF 2.0 开始,您可以遍历通用数组或 List
在 f:selectItems
由新 var
属性而不需要在 List<SelectItem>
上复制值在模型中。
这是 bean 的样子:
public class Bean {
private OrderStatus orderStatus;
private OrderStatus[] orderStatuses = OrderStatus.values();
// ...
}
以下是 View 的外观(假设
msg
指的是 <var>
,正如您在 <resource-bundle>
中定义的 faces-config.xml
):<h:selectOneMenu value="#{bean.orderStatus}">
<f:selectItems value="#{bean.orderStatuses}" var="orderStatus"
itemValue="#{orderStatus}" itemLabel="#{msg[orderStatus.name]}" />
</h:selectOneMenu>
就这样。
与问题无关,您在枚举名称和消息键中有拼写错误,应该是:
PENDING("enum.orderstatus.pending"),
CANCELLED("enum.orderstatus.cancelled");
而且,更干净的方法是将捆绑 key 保留在枚举之外,并将枚举本身用作捆绑 key 的一部分。例如。
PENDING,
CANCELLED;
<h:selectOneMenu value="#{bean.orderStatus}">
<f:selectItems value="#{bean.orderStatuses}" var="orderStatus"
itemValue="#{orderStatus}" itemLabel="#{msg['enum.orderstatus.' += orderStatus]}" />
</h:selectOneMenu>
enum.orderstatus.PENDING = Pending
enum.orderstatus.CANCELLED = Cancelled
关于jsf-2 - 本地化资源包中的枚举值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4375578/