【问题标题】:enuma label from message bundle消息包中的枚举标签
【发布时间】:2013-08-30 08:38:26
【问题描述】:

我有一个enum,其中包含一些selectOneMenu 的条目,这意味着枚举结构如下所示:display, pdfLabel

我想从我的message bundle 中加载条目标签,这意味着取决于 语言环境

它工作正常,但只是在我解散项目后的第一次。这意味着,如果我第一次加载条目时语言环境是“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);
    }
}

【问题讨论】:

  • 你能告诉我们 i18n 的 xml 配置吗?以及您如何准确地切换语言环境。
  • @noone 我可以添加它,但我很确定这与我的问题无关,因为消息包中的所有其他值都会相应地加载。正如下面的答案所解释的,我认为它必须与枚举做更多的事情。无论如何感谢您的帮助:)

标签: java jsf web-applications enums


【解决方案1】:

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

所以你必须在使用时设置ausgabepdfLabel 的值。但也许最好有一些“外部”类,它知道如何为您的枚举值获取不同的标签,而不是将这些值以某种方式硬编码在枚举中。

【讨论】:

  • 是的,你是对的,枚举值是静态的,好点。然而,我对这个解决方案很坚持:无论如何我只支持 2 种语言,所以我只是将它们添加到我的枚举 ausgabe_de, ausgabe_en 中,然后根据语言环境将它们加载到我的 List<SelectItem> 中。你对此有何看法?
  • 我认为这不是一个好主意。如果有另一种语言支持(例如奥地利方言;)会发生什么。如前所述,我将介绍另一个类,它为您提供特定枚举值的国际化字符串。因此,您只需调用EnumLabel.getLabel(enumValue) 并根据当前的语言环境,将返回正确的标签。要为枚举值找到相应的标签,您可以在枚举值中存储消息键,也可以使用枚举的名称(或 FQN)来完成此操作。
【解决方案2】:

这确实行不通。枚举属性仅在应用程序范围内初始化一次,而 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();
    }

}

然后在<f:selectItems>中引用如下(看,不需要SelectItem样板):

<f:selectItems value="#{data.transportmittels}" var="transportmittel"
    itemValue="#{transportmittel}" itemLabel="#{bundle[transportmittel.ausgabe]}" />

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

<o:importConstants type="com.example.Transportmittels" /> <!-- can be declared in a master template -->
...
<f:selectItems value="#{Transportmittels}" var="transportmittel"
    itemValue="#{transportmittel}" itemLabel="#{bundle[transportmittel.ausgabe]}" />

另见:

【讨论】:

  • 一如既往,非常感谢您,非常感谢您的帮助。
猜你喜欢
  • 2013-11-18
  • 1970-01-01
  • 2022-12-28
  • 2021-03-03
  • 1970-01-01
  • 2021-04-08
  • 1970-01-01
  • 1970-01-01
  • 2013-11-15
相关资源
最近更新 更多