2013-03-26 78 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{