本地化资源包中的枚举值 [英] Localizing enum values in resource bundle

查看:15
本文介绍了本地化资源包中的枚举值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的 JSF 应用程序中的 i18n 枚举有问题.当我开始时,我有一个枚举,里面定义了文本.但是现在,我有与枚举中的消息包相关联的键.

I have a problem with i18n enums in my JSF application. When I started, I had enums with the text defined inside. But now, I have keys tied to message bundles in the enum.

例如我的枚举之一:

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

}

在视图层,我使用类似的东西:

In the view layer, I use something like:

<!-- 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} 时,我需要对其进行转换.所以我实现了一个转换器,但是在 getAsObject() 方法中将 String 转换为 Object 时遇到了麻烦.

It worked well, but when I needed to output #{order.status}, I needed to convert it. So I implemented a converter, but got in trouble with conversion of String to Object in the getAsObject() method.

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

}

我现在纠结于此.有人知道如何有效地国际化多个枚举吗?

I'm entangled now with that. Anybody know how to internationalize multiple Enums efficiently?

推荐答案

通过转换器传递的值并不是您所期望的选项标签,而是选项值.最佳做法是不要在模型端执行此操作,而应在视图端执行此操作,因为模型不需要具有 i18n 感知能力.

The value which is passed through the converter is not the option label as you seem to expect, but the option value. The best practice is to not do this in the model side, but in the view side, because the model shouldn't need to be i18n aware.

至于方法,您基本上不必要地使事情变得过于复杂.由于 JSF 1.2 有一个内置的 EnumConverter 它将自动启动,并且从 JSF 2.0 开始,您可以通过新的 varf:selectItems 中迭代通用数组或 Listcode> 属性,而无需在模型中的 List 上复制值.

As to the approach, you're basically unnecessarily overcomplicating things. Since JSF 1.2 there's a builtin EnumConverter which will kick in automatically and since JSF 2.0 you can iterate over a generic array or List in f:selectItems by the new var attribute without the need to duplicate the values over a List<SelectItem> in the model.

这是豆子的样子:

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

    // ...
}

这里是视图的样子(假设 msg 指的是 正如您在 中定义的那样;faces-config.xml):

And here's how the view can look like (assuming that msg refers to the <var> as you've definied in <resource-bundle> in faces-config.xml):

<h:selectOneMenu value="#{bean.orderStatus}">
    <f:selectItems value="#{bean.orderStatuses}" var="orderStatus" 
        itemValue="#{orderStatus}" itemLabel="#{msg[orderStatus.name]}" />
</h:selectOneMenu>

仅此而已.

与问题无关,您在枚举名称和消息键中打错了字,应该是:

Unrelated to the problem, you've typos in the enum name and message keys, it should be:

PENDING("enum.orderstatus.pending"),
CANCELLED("enum.orderstatus.cancelled");

而且,更干净的是将包键保留在枚举之外,并将枚举本身用作包键的一部分.例如

And, more clean would be to keep the bundle keys out the enum and use enum itself as part of bundle key. E.g.

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

这篇关于本地化资源包中的枚举值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆