在Wicket中使用参数化UI消息的简单方法?

Wicket拥有灵活的国际化系统 ,支持以多种方式对UI消息进行参数化。 例如在StringResourceModel javadocs中有例如:

WeatherStation ws = new WeatherStation(); add(new Label("weatherMessage", new StringResourceModel( "weather.${currentStatus}", this, new Model(ws))); 

但我想要一些非常简单的东西,并且找不到一个很好的例子。

在.properties文件中考虑这种UI消息:

 msg=Value is {0} 

具体来说,我不想为此目的创建一个模型对象(使用要替换的值的getter;如上例中的WeatherStation)。 如果我已经拥有局部变量中的值,那就太过分了,否则就不需要这样的对象了。

这是用正确的值替换{0}的一种愚蠢的“powershell”方式:

 String value = ... // contains the dynamic value to use add(new Label("message", getString("msg").replaceAll("\\{0\\}", value))); 

是否有一种干净的,更多的Wicket-y方式来做到这一点 (这不比上面的长得多)

我认为可以通过使用MessageFormat改进Jonik的答案来实现最一致的WICKETY方式:

的.properties:

 msg=Saving record {0} with value {1} 

的.java:

 add(new Label("label", MessageFormat.format(getString("msg"),obj1,obj2))); //or info(MessageFormat.format(getString("msg"),obj1,obj2)); 

为什么我喜欢它:

  • 干净,简单的解决方案
  • 使用普通的Java而不是别的
  • 您可以根据需要替换任意数量的值
  • 使用标签,信息(),validation等。
  • 它不是完全摇摇晃晃,但它与wicket一致,因此您可以使用StringResourceModel重用这些属性。

笔记:

如果你想使用模型,你只需要创建一个简单的模型来覆盖模型的toString函数,如下所示:

 abstract class MyModel extends AbstractReadOnlyModel{ @Override public String toString() { if(getObject()==null)return ""; return getObject().toString(); } } 

并将其作为MessageFormat参数传递。

我不知道为什么Wicket在反馈消息中不支持Model 。 但如果它被支持,则没有理由使用这些解决方案,您可以在任何地方使用StringResourceModel

看看StringResourceModel javadoc中的示例4 – 您可以传递空模型和显式参数:

 add(new Label("message", new StringResourceModel( "msg", this, null, value))); msg=Value is {0} 

有一种方法,虽然仍然涉及创建模型,但不需要带有吸气剂的bean。

在属性文件中给出此消息:

 msg=${} persons 

以下是如何使用值替换占位符,无论是局部变量,字段还是文字:

 add(new Label("label", new StringResourceModel("msg", new Model(5)))); 

当面对问题中描述的内容时,我现在将使用:

的.properties:

 msg=Saving record %s with value %d 

Java的:

 add(new Label("label", String.format(getString("msg"), record, value))); 

为什么我喜欢它:

  • 干净,简单的解决方案
  • 使用普通的Java而不是别的
  • 您可以根据需要替换任意数量的值(与${}技巧不同 )。 编辑 :好吧,如果你真的需要支持许多语言 ,其中被替换的值可能是不同的顺序, String.format()是不好的。 相反, 使用MessageFormat是一种类似的方法 ,可以正确地支持它。

免责声明:这是“太明显”,但它比其他解决方案更简单(并且肯定比我原来的replaceAll() hack更好)。 我最初寻求的是“Wicket-y”方式,而这种方式绕过了Wicket,然后又关注了谁? 🙂

为您的标签创建模型确实是Wicket方式 。 也就是说,您可以通过偶尔的实用function轻松实现自己。 这是我使用的一个:

 /** * Creates a resource-based label with fixed arguments that will never change. Arguments are wrapped inside of a * ConvertingModel to provide for automatic conversion and translation, if applicable. * * @param The component id * @param resourceKey The StringResourceModel resource key to use * @param component The component from which the resourceKey should be resolved * @param args The values to use for StringResourceModel property substitutions ({0}, {1}, ...). * @return the new static label */ public static Label staticResourceLabel(String id, String resourceKey, Component component, Serializable... args) { @SuppressWarnings("unchecked") ConvertingModel[] models = new ConvertingModel[args.length]; for ( int i = 0; i < args.length; i++ ) { models[i] = new ConvertingModel( new Model( args[i] ), component ); } return new CustomLabel( id, new StringResourceModel( resourceKey, component, null, models ) ); } 

我在这里看到的细节是:

  1. 我已经创建了自己的ConvertingModel ,它将根据给定组件可用的IConverters自动将对象转换为String表示forms
  2. 我创建了自己的CustomLabel ,它应用自定义标签文本后处理(详见本答复 )

使用自定义IConverter,例如,一个Temperature对象,你可以有类似的东西:

 Properties key: temperature=The current temperature is ${0}. Page.java code: // Simpler version of method where wicket:id and resourceKey are the same add( staticResourceLabel( "temperature", new Temperature(5, CELSIUS) ) ); Page.html: The current temperature is 5 degrees Celsius. 

这种方法的缺点是你不再能直接访问Label类,你不能将它子类isVisible()覆盖isVisible()或类似的东西。 但就我的目的而言,99%的时间都有效。