jsf-2 - 本地化资源包中的枚举值

标签 jsf-2 enums localization

我的 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 时遇到了麻烦至ObjectgetAsObject()方法。

网页.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 开始,您可以遍历通用数组或 Listf: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/

相关文章:

java - 如何在 Swagger 中为数组参数提供内部类型?

time - 使用time.Format时的本地化

api - 如何使用必应翻译 API?

java - 由于错误 c00ce56e,无法完成操作

jsf-2 - java.util.MissingResourceException : Can't find bundle for base name resources.应用程序,语言环境

java - 数据库中的 primefaces 图形图像未加载

css - 我如何在 JSF 中使用/创建主题?

java - 枚举和 case 语句。即使有中断也不切换

swift - 从枚举的一个子部分中选择一个随机值

ios - 本地化自定义 SiriKit 意图