在资源束中本地枚举枚举值 [英] Localizing enum values in resource bundle

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

问题描述

我的JSF应用程序中的i18n枚举有问题。当我启动时,我已经枚举了内部定义的文本。但是现在,我把钥匙与枚举中的邮件捆绑捆绑在一起。



我的一个枚举示例:

  public enum OrderStatus实现CustomEnum {
PENDING(enum.orderstatus.pending),
CANCELED(enum.orderstatus.canceled);

/ **
*邮件束中的密钥
* /
private String name;

OrderStatus(String name){
this.name = name;
}

@Override
public String getName(){
return name;
}

}

在视图层中,我使用像:

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

<! - 输出 - >
< 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()方法。



web.xml:

 <变换器> 
< converter-for-class> model.helpers.OrderStatus< / converter-for-class>
< converter-class> model.helpers.EnumTypeConverter< / converter-class>
< / converter>

Java:

 code> public class EnumTypeConverter implements Converter {

@Override
public Object getAsObject(FacesContext context,UIComponent comp,
String value)throws ConverterException {
/ / 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());
返回文本;
}

}



我现在纠缠在一起。任何人都知道如何有效地使多个枚举国际化?

解决方案

通过转换器传递的值不是你看起来的选项标签期望,但期权价值。最好的做法是在模型方面不要这样做,但在视图方面,因为模型不应该是i18n的意识。



关于方法你基本上是不必要的过度复杂的事情。由于JSF 1.2有一个内置的 EnumConverter ,这将自动启动,自JSF 2.0以来,您可以遍历通用数组或列表 f :selectItems 通过新的 var 属性,而不需要通过列表< SelectItem>
< c $ c> public class Bean {
private OrderStatus orderStatus;
private OrderStatus [] orderStatuses = OrderStatus.values();

// ...
}

这里是如何视图可以看起来像(假设 msg 指的是< var> ,如您在<$ faces-config.xml 中的c $ c>< resource-bundle> ):

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

这就是全部。






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

  PENDING(enum.orderstatus.pending),
CANCELED(enum.orderstatus.cancelled);

而且,更干净的是将捆绑密钥保存在枚举中,并将枚举本身作为捆绑键。例如

  PENDING,
取消;



 < h:selectOneMenu值= #{bean.orderStatus} > 
< f:selectItems value =#{bean.orderStatuses}var =orderStatus
itemValue =#{orderStatus}itemLabel =#{msg ['enum.orderstatus。 = orderStatus]}/>
< / h:selectOneMenu>



  enum.orderstatus.PENDING =待定
enum.orderstatus.CANCELLED =已取消


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.

Example one of my enums:

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}"/>

and in 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);
    }
}

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?

解决方案

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.

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.

Here's how the bean can look like:

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

    // ...
}

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>

That's all.


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天全站免登陆