本地化资源包中的枚举值
我的 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;
}
}
在视图层中,我使用类似:
<!-- 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
时遇到了麻烦。
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 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?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
通过转换器传递的值不是您期望的选项标签,而是选项值。最佳实践是不要在模型端执行此操作,而是在视图端执行此操作,因为模型不需要了解 i18n。
至于方法,你基本上不必要地使事情变得过于复杂。从 JSF 1.2 开始,有一个内置的
EnumConverter
会自动启动,从 JSF 2.0 开始,您可以通过新的varf:selectItems
中的通用数组或List
code> 属性,无需在模型中的List
上复制值。bean 的外观如下:
视图的外观如下(假设
msg
引用您在中定义的
):faces-config.xml 中的
仅此而已。
与问题无关,您在枚举名称和消息键中输入了拼写错误,它应该是:
并且,更干净的方法是将捆绑包密钥保留在枚举之外,并使用枚举本身作为捆绑包密钥的一部分。例如
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 orList
inf:selectItems
by the newvar
attribute without the need to duplicate the values over aList<SelectItem>
in the model.Here's how the bean can look like:
And here's how the view can look like (assuming that
msg
refers to the<var>
as you've definied in<resource-bundle>
infaces-config.xml
):That's all.
Unrelated to the problem, you've typos in the enum name and message keys, it should be:
And, more clean would be to keep the bundle keys out the enum and use enum itself as part of bundle key. E.g.
我在这里发布了我的解决方案: 多个枚举的国际化(枚举值的翻译) - 但仍希望进一步增强。
编辑:在@Joop Eggen的帮助下,我们提出了一个非常酷的解决方案:
再次编辑:完整且随时可用的解决方案:
创建一个类
使其成为自定义EL函数
将taglib添加到您的web.xml
中像这样的属性文件 enum_en.properties 和 enum_yourlanguage.properties
将属性文件作为资源包添加到 faces-config.xml
将自定义标记库添加到 xhtml 文件
然后 - 瞧 - 您现在可以在 jsf 中访问翻译后的枚举值:
I have posted my solution here: Internationalization of multiple enums (translation of enum values) - but still hoping for further enhancement.
EDIT: with the help of @Joop Eggen, we have come up with a really cool solution:
EDIT again: complete and ready-to-use solution:
Make a class
Make it a custom EL function
Add the taglib to your web.xml
Have properties files enum_en.properties and enum_yourlanguage.properties like this
Add the properties files as resource bundles to your faces-config.xml
Add the custom taglib to your xhtml files
And - voilà - you can now access the translated enum values in jsf:
嗯,枚举只是另一个类。没有什么可以阻止您添加解析和字符串转换方法来解析和输出区域设置敏感的消息。
也许它违反了单一责任原则(是吗?),但我相信让枚举负责解析和返回区域设置感知值是正确的做法。
只需添加两个这样的方法:
我希望我的代码是正确的,因为我现在没有使用 IDE 检查它...这是您正在寻找的吗?
Well, enum is just another class. There is nothing stopping you from adding parsing and to-string conversion methods that will parse and output locale-sensitive messages.
Maybe it violates Single Responsible Principle (does it?), but I believe making enum responsible for parsing and returning locale-aware values is the right thing to do.
Just add two methods like this:
I hope I got the code right, as I am not checking it with IDE now... Is this what you were looking for?
我计算枚举中的消息键,如下所示;所以不需要在枚举上维护具有附加属性的键
然后我
在应用程序上下文中配置了 org.springframework.context.support.ReloadableResourceBundleMessageSource
I calculate the message key in the enum like as shown below; so no need to maintain the keys with additional attributes on the enum
Then I use it like this
with having configured a org.springframework.context.support.ReloadableResourceBundleMessageSource in the app context
如果有人正在寻找一个简单的实用程序库来处理枚举国际化,请查看 https:/ /github.com/thiagowolff/litefaces-enum-i18n
该工件也可以在 Maven Central 中找到:
基本上,您只需将工件添加到您的项目中,并按照所描述的枚举命名约定定义枚举各自的键即可。可以使用提供的 EL 函数检索翻译(以及 CSS 类名称)。
In case anyone is looking for a simple utility library to handle enum internationalization, please take a look at https://github.com/thiagowolff/litefaces-enum-i18n
The artifact is also available in Maven Central:
Basically, you just need to add the artifact to your project and define the enum respective keys following the described enum naming conventions. The translations (and also CSS class names) can be retrieved using the provided EL functions.