Java 枚举消息包中的标签

Java 枚举消息包中的标签,java,jsf,web-applications,enums,Java,Jsf,Web Applications,Enums,我有一个enum,其中有一些条目用于selectOneMenu,这意味着enum结构如下所示:display,pdfLabel 我想从我的消息包中加载条目标签,这意味着取决于区域设置 它工作得很好,但只是在我完成项目后的第一次。这意味着,如果在我第一次加载条目时区域设置为“en”,即使在注销-会话无效之后;如果我将区域设置更改为“de”,则条目仍然来自“en”-消息。只有在我重新部署的情况下它才会起作用 有人知道这种行为吗 我的枚举: public enum Transportmittel {

我有一个
enum
,其中有一些条目用于
selectOneMenu
,这意味着enum结构如下所示:
display,pdfLabel

我想从我的消息包中加载条目标签,这意味着取决于区域设置

它工作得很好,但只是在我完成项目后的第一次。这意味着,如果在我第一次加载条目时区域设置为“en”,即使在注销-会话无效之后;如果我将区域设置更改为“de”,则条目仍然来自“en”-消息。只有在我重新部署的情况下它才会起作用

有人知道这种行为吗

我的枚举:

public enum Transportmittel {
     TRUCK(I18n.get("tv.moc.truck"), "TRUCK"), 
     AIRFREIGHT(I18n.get("tv.moc.airfreight"), "AIRFREIGHT"), 
     TRAIN(I18n.get("tv.moc.train"), "TRAIN"), 
     SEAFREIGHT(I18n.get("tv.moc.seafreight"), "SEAFREIGHT"), 
     BARGE(I18n.get("tv.moc.barge"), "BARGE");

String ausgabe;
String pdfLabel;

private Transportmittel(String ausgabe, String pdfLabel) {
    this.ausgabe = ausgabe;
    this.pdfLabel = pdfLabel;
}

public String toString() {
    return ausgabe;
}

public String getLabelForPdf() {
    return pdfLabel;
}
}

加载条目的控制器:

@PostConstruct
public void init() {
    transportMittelSelectList.add(new SelectItem(Transportmittel.TRUCK.pdfLabel, Transportmittel.TRUCK.ausgabe));
    transportMittelSelectList.add(new SelectItem(Transportmittel.TRAIN.pdfLabel, Transportmittel.TRAIN.ausgabe));
    transportMittelSelectList.add(new SelectItem(Transportmittel.AIRFREIGHT.pdfLabel, Transportmittel.AIRFREIGHT.ausgabe));
    transportMittelSelectList.add(new SelectItem(Transportmittel.SEAFREIGHT.pdfLabel, Transportmittel.SEAFREIGHT.ausgabe));
    transportMittelSelectList.add(new SelectItem(Transportmittel.BARGE.pdfLabel, Transportmittel.BARGE.ausgabe));
}
这就是我加载消息包的地方:

public class I18n {

    public static String get(String msg) {
        FacesContext context = FacesContext.getCurrentInstance();
        ResourceBundle bundle = context.getApplication().getResourceBundle(
                                context, "messages");
        return bundle.getString(msg);
    }
}

枚举值是
静态的
——因此当类加载器加载类时(=第一次使用)只调用它们的构造函数一次。因此,在连续使用时,您仍然使用同一实例,该实例包含在第一次使用期间构造时设置的相同字符串
ausgabe


因此,使用时必须设置
ausgabe
pdfLabel
的值。但是,如果有一些“外部”类知道如何为枚举值获取不同的标签,而不是让这些值以某种方式硬编码在枚举中,那可能更好。

这确实行不通。枚举属性仅在应用程序范围内初始化一次,而i18n本质上应该根据每个请求进行解析

您需要重新设计枚举,以便只保留标签键,而不保留已解析的本地化值

TRUCK("tv.moc.truck", "TRUCK"), 
AIRFREIGHT("tv.moc.airfreight", "AIRFREIGHT"), 
TRAIN("tv.moc.train", "TRAIN"), 
SEAFREIGHT("tv.moc.seafreight", "SEAFREIGHT"), 
BARGE("tv.moc.barge", "BARGE");
然后在应用程序范围的bean中提供如下枚举值:

@ManagedBean
@ApplicationScoped
public class Data {

    public Transportmittel[] getTransportmittels() {
        return Transportmittel.values();
    }

}
然后在
中引用它,如下所示(看,不需要
SelectItem
样板文件):


或者,如果您碰巧已经使用了JSF实用程序库,如您的用户配置文件中当前所示,那么您也可以绕过整个应用程序范围的
数据
bean,直接在EL范围内使用它,如下所示:


...
另见:

您能告诉我们i18n的xml配置吗?以及如何准确地切换区域设置。@没有人可以添加它,但我很确定这与我的问题无关,因为消息包中的所有其他值都会相应地加载。正如下面的答案所解释的,我认为它必须与enum做更多的工作。无论如何,谢谢你的帮助:)是的,你是对的,枚举值是静态的,很好。然而,我想到了这个解决方案:反正我只支持两种语言,所以我只是将它们添加到我的enum
ausgabe_de,ausgabe_en
,然后根据语言环境将它们加载到我的
列表中。你对此有什么看法?我认为这不是个好主意。如果有另一种语言支持(例如奥地利方言;),会发生什么情况。如前所述,我将介绍另一个类,它为您提供特定枚举值的国际化字符串。因此,您只需调用
EnumLabel.getLabel(enumValue)
,并根据当前区域设置返回正确的标签。要查找枚举值的对应标签,您可以在枚举值中存储消息键,也可以使用枚举的名称(或FQN)来完成此操作。一如既往,非常感谢您的帮助。