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

时间:2010-10-20 10:35:27

标签: java internationalization properties wicket

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方式来做到这一点(这不比上面那么长)

6 个答案:

答案 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));

为什么我喜欢它:

  • 清洁,简单的解决方案
  • 使用普通Java而不使用其他内容
  • 您可以根据需要更换任意数量的值
  • 使用标签,信息(),验证等
  • 这不是完全摇摇晃晃,但它与检票口一致,因此您可以将这些属性与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)));

为什么我喜欢它:

  • 清洁,简单的解决方案
  • 使用plain Java而不使用其他
  • 您可以根据需要替换任意数量的值(与${} 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 ) );
}

详情我在这里说道:

  1. 我创建了自己的ConvertingModel,它会根据给定组件可用的IConverters自动将对象转换为String表示
  2. 我创建了自己的CustomLabel应用自定义标签文字后处理(详见this answer
  3. 使用自定义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包含firstNamelastName之类的字段。在这种情况下,您可以轻松访问属性字符串中的firstNamelastName字段:

salutation.text=Hej ${firstName} ${lastName}, have a nice day!

您可以在这里找到更多信息:https://ci.apache.org/projects/wicket/apidocs/8.x/org/apache/wicket/model/StringResourceModel.html#StringResourceModel-java.lang.String-org.apache.wicket.model.IModel-