Wicket有flexible internationalisation system支持以多种方式对UI消息进行参数化。有一些例子,例如在StringResourceModel javadocs中,例如:
WeatherStation ws = new WeatherStation();
add(new Label("weatherMessage", new StringResourceModel(
"weather.${currentStatus}", this, new Model<String>(ws)));
但我想要一些非常简单的东西,并且找不到一个很好的例子。
在.properties文件中考虑这种UI消息:
msg=Value is {0}
具体来说,我不想为此目的创建一个模型对象(使用要替换的值的getter;如上例中的WeatherStation)。如果我已经拥有局部变量中的值,那就太过分了,否则就不需要这样的对象了。
这是用正确的值替换{0}的一种愚蠢的“蛮力”方式:
String value = ... // contains the dynamic value to use
add(new Label("message", getString("msg").replaceAll("\\{0\\}", value)));
是否有一种干净,更多Wicket-y方式来做到这一点(这不比上面那么长)?
答案 0 :(得分:12)
看一下StringResourceModel javadoc中的例4 - 你可以传递一个空模型和显式参数:
add(new Label("message",
new StringResourceModel(
"msg", this, null, value)));
msg=Value is {0}
答案 1 :(得分:5)
有一种方法,虽然仍然涉及创建模型,但不需要带有吸气剂的bean。
在属性文件中给出此消息:
msg=${} persons
以下是如何使用值替换占位符,无论是局部变量,字段还是文字:
add(new Label("label", new StringResourceModel("msg", new Model<Serializable>(5))));
答案 2 :(得分:4)
我认为通过Jonik's answer改进MessageFormat
可以实现最一致的 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));
为什么我喜欢它:
StringResourceModel
一起使用。注意:
如果你想使用模型,你只需要创建一个覆盖模型toString
函数的简单模型,如下所示:
abstract class MyModel extends AbstractReadOnlyModel{
@Override
public String toString()
{
if(getObject()==null)return "";
return getObject().toString();
}
}
并将其作为MessageFormat
参数传递。
我不知道为什么Wicket在反馈消息中不支持Model
。但如果它得到支持,则没有理由使用这些解决方案,您可以在任何地方使用StringResourceModel
。
答案 3 :(得分:2)
当面对问题中描述的内容时,我现在会使用:
的.properties:
msg=Saving record %s with value %d
爪哇:
add(new Label("label", String.format(getString("msg"), record, value)));
为什么我喜欢它:
${}
trick不同)。 修改:好吧,如果您确实需要支持多种语言,替换后的值可能会有不同的顺序,String.format()
就不行了。相反,using MessageFormat is a similar approach正确支持此功能。免责声明:这是“太明显”,但它比其他解决方案更简单(并且肯定比我原来的replaceAll()
黑客更好)。我最初寻求的是“Wicket-y”方式,而这种方式绕过了Wicket,然后又关注了谁? : - )
答案 4 :(得分:0)
为您的标签创建模型确实是 Wicket Way 。也就是说,您可以通过偶尔的实用功能轻松实现自己。这是我使用的一个:
/**
* 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<Serializable>[] models = new ConvertingModel[args.length];
for ( int i = 0; i < args.length; i++ ) {
models[i] = new ConvertingModel<Serializable>( new Model<Serializable>( args[i] ), component );
}
return new CustomLabel( id, new StringResourceModel( resourceKey, component, null, models ) );
}
详情我在这里说道:
ConvertingModel
,它会根据给定组件可用的IConverters自动将对象转换为String表示CustomLabel
应用自定义标签文字后处理(详见this answer)使用自定义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:
<span wicket:id='temperature'>The current temperature is 5 degrees Celsius.</span>
这种方法的缺点是你不再能直接访问Label类,你不能将它子类化为覆盖isVisible()
或类似的东西。但就我的目的而言,99%的时间都有效。
答案 5 :(得分:0)
如果您的组件中有一个模型,其中包含一个对象,该对象具有您要从占位符访问的值作为替换对象,则可以编写:
new StringResourceModel("salutation.text", getModel());
让我们假设getModel()
的返回类型为IModel<User>
,而User
包含firstName
和lastName
之类的字段。在这种情况下,您可以轻松访问属性字符串中的firstName
和lastName
字段:
salutation.text=Hej ${firstName} ${lastName}, have a nice day!