在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 ) ); }
我在这里看到的细节是:
- 我已经创建了自己的
ConvertingModel
,它将根据给定组件可用的IConverters自动将对象转换为String表示forms - 我创建了自己的
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%的时间都有效。