2013-03-26 682 views
2

再次讨论了一些已经讨论过的问题before以及我想要共享“我的”解决方案并寻求改进,其他方法或最佳实践的地方。多个枚举的国际化(枚举值的转换)

我有几个枚举,我需要国际化(我需要将枚举值翻译成一些语言才能在jsf页面中显示它们)。 Examle枚举:

public enum TransferStatus { 
    NOT_TRANSFERRED, 
    TRANSFERRED 
} 

翻译将是例如Not yet transferred/Transferred, all good

翻译应存放在一个MessageBundle(属性文件)。我正在寻找一个简单的通用解决方案(最好不需要在所有枚举中编写额外的代码),这在jsf方面并不需要太多。仅仅提到它,当然它有可能是两个不同的枚举值相同的枚举值(例如,在不同的枚举中具有不同含义的值,如COMPLETED)。

我想出了解决办法:

(1)在属性商店翻译文件是这样的:

TransferStatus.NOT_TRANSFERRED = Not yet transferred 
TransferStatus.TRANSFERRED = Transferred, all good 

(2)请一个助手类,它需要一个枚举和生成查找关键字:

public class EnumTranslator { 
    public static String getMessageKey(Enum<?> e) { 
    return e.getClass().getSimpleName() + '.' + e.name(); 
    } 
} 

(3)该代码添加到每个枚举:

public String getKey() { 
    return EnumTranslator.getMessageKey(this); 
} 

(4)现在,我可以使用枚举的转换值是这样的:

<h:outputText value="#{enum[order.transferStatus.key]}" /> 

它是没问题,但我只是不喜欢被添加相同getKey()方法对每个枚举。应该有更好的东西!现在轮到你了,SO :-)

+0

你可能已经张贴这是一个问题的其他问题。那么你会在适当的时候收到其他用户的反馈。 – 2013-03-26 09:13:08

+0

谢谢,完成并链接到这里。 – 2013-03-26 09:23:33

回答

3

好了,现在这是完整的和随时使用的解决方案:(感谢@Joop埃根)

使类

public final class EnumTranslator { 
    public static String getMessageKey(Enum<?> e) { 
    return e.getClass().getSimpleName() + '.' + e.name(); 
    } 
} 

使它成为一个自定义EL函数

<?xml version="1.0" encoding="UTF-8"?> 
<facelet-taglib 
xmlns="http://java.sun.com/xml/ns/javaee" 
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facelettaglibrary_2_0.xsd" 
version="2.0"> 
<namespace>http://example.com/enumi18n</namespace> 
<function> 
    <function-name>xlate</function-name> 
    <function-class>your.package.EnumTranslator</function-class> 
    <function-signature>String getMessageKey(java.lang.Enum)</function-signature> 
</function> 
</facelet-taglib> 

的taglib添加到你的web.xml

<context-param> 
    <param-name>javax.faces.FACELETS_LIBRARIES</param-name> 
    <param-value>/WEB-INF/enumi18n.taglib.xml</param-value> 
</context-param> 

有属性文件enum_en.properties和enum_yourlanguage.properties这样

TransferStatus.NOT_TRANSFERRED = Not transferred 
TransferStatus.TRANSFERRED = Transferred 

属性文件作为资源包添加到您的面孔,配置。XML

<resource-bundle> 
     <base-name>kk.os.obj.jsf.i18n.enum</base-name> 
     <var>enum</var> 
    </resource-bundle> 

自定义标签库添加到您的XHTML文件

<html ... xmlns:l="http://example.com/enumi18n"> 

而且 - 瞧 - 你现在可以在JSF访问翻译枚举值:

<h:outputText value="#{enum[l:xlate(order.transferStatus)]}" /> 
+0

美丽而充满活力的“voilà”。 – 2013-04-05 06:02:03

1

我会做一个EL功能,使枚举类,因为它们是:

#{l:xlate(order.transferStatus)} 

好吧,XLATE有一个对象参数,然后(或Enum<?>)。但枚举类保持原样。

+0

这只是真棒。不得不改变,只是添加自定义函数来调用我的'EnumTranslator.getMessageKey()'(见[这里](http://stackoverflow.com/questions/7079978/how-to-create-a-custom-el-function )如何做到这一点),现在我可以像这样访问已翻译的枚举值:''。辉煌!非常感谢! – 2013-03-26 09:53:24

1

的方式我'这样做需要更多的代码(但远远少于我在这里看到的其他答案),但我觉得更可靠:

@ManagedBean 
@ApplicationScoped 
public class EnumTranslator { 

    private <E extends Enum<E>> Map<E, String> getPresentableNames(Class<E> enumClass) { 
     ResourceBundle resources = ResourceBundle.getBundle(
      "com.example.app.MyMessageBundle", 
      FacesContext.getCurrentInstance().getViewRoot().getLocale()); 

     String prefix = enumClass.getSimpleName() + "."; 

     Map<E, String> map = new EnumMap<E, String>(enumClass); 
     for (E value : enumClass.getEnumConstants()) { 
      map.put(value, resources.getString(prefix + value)); 
     } 

     return map; 
    } 

    // Bean method, accessible via EL 
    public Map<?, ?> getTransferStatuses() { 
     return getPresentableNames(TransferStatus.class); 
    } 
} 

然后你的页面可以这样做:

<h:outputText value="#{enumTranslator.transferStatuses[order.transferStatus]}" /> 
+0

我也喜欢这个 - 你认为哪种方式更可靠? – 2013-03-26 10:58:09

+0

直接基于实际的枚举值,并且代码更易于追踪。 – VGR 2013-03-26 19:28:00

1

什么:

public interface InternationalizationOfEnum { 
default String getKey() { 
     return EnumTranslator.getMessageKey(this); 
    } 
String name();} 

public enum anyEnum implements InternationalizationOfEnum{