在资源包中本地化枚举值

mar*_*osh 12 enums localization jsf-2

我的JSF应用程序中的i18n枚举有问题.当我开始时,我有内部定义文本的枚举.但现在,我在枚举中将密钥绑定到消息包.

我的枚举示例之一:

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;
    }

}
Run Code Online (Sandbox Code Playgroud)

在视图层中,我使用如下内容:

<!-- input -->
<h:selectOneMenu value="#{order.status}">
    <f:selectItems value="#{flowUtils.orderStatuses}"/>
</h:selectOneMenu>

<!-- output -->
<h:outputText value="#{order.status}"/>
Run Code Online (Sandbox Code Playgroud)

在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);
    }
}
Run Code Online (Sandbox Code Playgroud)

它工作得很好,但是当我需要输出时#{order.status},我需要转换它.所以,我实现了一个转换器,但与转换陷入麻烦StringObjectgetAsObject()方法.

web.xml中:

<converter>
  <converter-for-class>model.helpers.OrderStatus</converter-for-class>
  <converter-class>model.helpers.EnumTypeConverter</converter-class>
</converter>
Run Code Online (Sandbox Code Playgroud)

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;
    }

}
Run Code Online (Sandbox Code Playgroud)

我现在纠结于此.有谁知道如何有效地国际化多个Enums?

Bal*_*usC 25

通过转换器传递的值不是您期望的选项标签,而是选项值.最佳做法是在模型方面不要这样做,但在视图方面,因为模型不需要知道.

至于方法,你基本上不必要地使事情过于复杂.由于JSF 1.2有一个内置的EnumConverter,它会自动踢,因为JSF 2.0,你可以遍历一个通用的阵列或Listf:selectItems通过新的var属性,而无需在重复的值List<SelectItem>在模型中.

以下是bean的外观:

public class Bean {
    private OrderStatus orderStatus;
    private OrderStatus[] orderStatuses = OrderStatus.values();

    // ...
}
Run Code Online (Sandbox Code Playgroud)

以下是视图的外观(假设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>
Run Code Online (Sandbox Code Playgroud)

就这样.


与问题无关,你在枚举名称和消息键中输入错误,它应该是:

PENDING("enum.orderstatus.pending"),
CANCELLED("enum.orderstatus.cancelled");
Run Code Online (Sandbox Code Playgroud)

并且,更干净的是将捆绑密钥保留在枚举中并使用枚举本身作为捆绑密钥的一部分.例如

PENDING,
CANCELLED;
Run Code Online (Sandbox Code Playgroud)
<h:selectOneMenu value="#{bean.orderStatus}">
    <f:selectItems value="#{bean.orderStatuses}" var="orderStatus" 
        itemValue="#{orderStatus}" itemLabel="#{msg['enum.orderstatus.' += orderStatus]}" />
</h:selectOneMenu>
Run Code Online (Sandbox Code Playgroud)
enum.orderstatus.PENDING = Pending
enum.orderstatus.CANCELLED = Cancelled
Run Code Online (Sandbox Code Playgroud)