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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/3976888/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 04:14:24  来源:igfitidea点击:

Simple way to use parameterised UI messages in Wicket?

javainternationalizationpropertieswicket

提问by Jonik

Wicket has a flexible internationalisation systemthat supports parameterising UI messages in many ways. There are examples e.g. in StringResourceModeljavadocs, such as this:

Wicket 有一个灵活的国际化系统,支持以多种方式参数化 UI 消息。StringResourceModeljavadocs 中有一些示例,例如:

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

But I want something really simple, and couldn't find a good example of that.

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

Consider this kind of UI message in a .properties file:

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

msg=Value is {0}

Specifically, I wouldn't want to create a model object (with getters for the values to be replaced; like WeatherStation in the above example) only for this purpose. That's just overkill if I already have the values in local variables, and there is otherwise no need for such object.

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

Here's a stupid "brute force" way to replace the {0} with the right value:

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

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

Is there a clean, more Wicket-y way to do this(that isn't awfully much longer than the above)?

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

采纳答案by Hossein Nasr

I think the most consistent WICKETYway could be accomplished by improving Jonik's answerwith MessageFormat:

我认为最稳定的WICKETY方式可以通过改进来完成Jonik的回答MessageFormat

.properties:

。特性:

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

.java:

.java:

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

Why I like it:

为什么我喜欢它:

  • Clean, simple solution
  • Uses plain Java and nothing else
  • You can replace as many values as you want
  • Work with labels, info(), validation, etc.
  • It's not completely wickety but it is consistent with wicket so you may reuse these properties with StringResourceModel.
  • 干净、简单的解决方案
  • 使用纯 Java 而没有别的
  • 您可以根据需要替换任意数量的值
  • 使用标签、info()、验证等。
  • 它不是完全 wickety 但它与 wicket 一致,因此您可以将这些属性与StringResourceModel.

Notes:

笔记:

if you want to use Models you simply need to create a simple model that override toStringfunction of the model like this:

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

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

and pass it as MessageFormatargument.

并将其作为MessageFormat参数传递。

I don't know why Wicket does not support Modelin feedback message. but if it was supported there was no reason to use these solutions and you could use StringResourceModeleverywhere.

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

回答by svenmeier

Take a look at Example 4 in the StringResourceModel javadoc - you can pass a null model and explicit parameters:

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

add(new Label("message",
         new StringResourceModel(
             "msg", this, null, value)));

msg=Value is {0}

回答by Jawher

There's a way, which although still involves creating a model, doesn't requires a bean with a getter.

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

given this message in a properties file:

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

msg=${} persons

Here's how to replace the placeholder with a value, be it a local variable, a field or a literal:

以下是用值替换占位符的方法,无论是局部变量、字段还是文字:

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

回答by Jonik

When faced with something like described in the question, I would now use:

当遇到问题中描述的类似问题时,我现在会使用:

.properties:

。特性:

msg=Saving record %s with value %d

Java:

爪哇:

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

Why I like it:

为什么我喜欢它:

  • Clean, simple solution
  • Uses plain Javaand nothing else
  • You can replace as many values as you want (unlike with the ${}trick). Edit: well, if you actually need to support many languageswhere the replaced values might be in different order, String.format()is no good. Instead, using MessageFormat is a similar approachthat properly supports this.
  • 干净、简单的解决方案
  • 使用纯 Java而没有别的
  • 您可以根据需要替换任意数量的值(与${}技巧不同)。编辑:好吧,如果您确实需要支持多种语言,其中替换值的顺序可能不同,那就String.format()不好了。相反,使用 MessageFormat 是一种类似的方法,可以正确支持这一点。

Disclaimer: this is "too obvious", but it's simpler than the other solutions (and definitely nicer than my original replaceAll()hack). I originally sought for a "Wicket-y" way, while this kinda bypasses Wicket—then again, who cares? :-)

免责声明:这“太明显了”,但它比其他解决方案更简单(并且绝对比我原来的replaceAll()黑客更好)。我最初寻求的是“Wicket-y”方式,而这种方式绕过了 Wicket——话说回来,谁在乎呢?:-)

回答by Philipp Wirth

In case you have a Model in your Component which holds an object with values you want to access from your placeholders as substitutions, you can write:

如果您的 Component 中有一个 Model ,它包含一个对象,其中包含您希望从占位符访问的值作为替换,您可以编写:

new StringResourceModel("salutation.text", getModel());

Let's imagine getModel()'s return type is IModel<User>and Usercontains fields like firstNameand lastName. In this case you can easily access firstNameand lastNamefields inside your property string:

让我们想象一下getModel()的返回类型是IModel<User>并且User包含像firstName和这样的字段lastName。在这种情况下,您可以轻松访问属性字符串中的firstNamelastName字段:

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

Further information you can find here: https://ci.apache.org/projects/wicket/apidocs/8.x/org/apache/wicket/model/StringResourceModel.html#StringResourceModel-java.lang.String-org.apache.wicket.model.IModel-

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

回答by Brian Laframboise

Creating a Model for your Label really is The Wicket Way. That said, you can make it easy on yourself with the occasional utility function. Here's one I use:

为您的标签创建模型确实是Wicket 方式。也就是说,您可以使用偶尔的实用程序功能让自己变得轻松。这是我使用的一个:

/**
 * 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 ) );
}

Details I'm glossing over here are:

我在这里掩盖的细节是:

  1. I've created my own ConvertingModelwhich will automatically convert objects to their String representation based on the IConverters available to the given component
  2. I've created my own CustomLabelthat applies custom label text post-processing (as detailed in this answer)
  1. 我已经创建了自己的ConvertingModel,它会根据给定组件可用的 IConverters 自动将对象转换为它们的字符串表示
  2. 我已经创建了自己的CustomLabel应用自定义标签文本后处理(如本答案中所述

With a custom IConverter for, say, a Temperature object, you could have something like:

使用自定义 IConverter 用于,比如说,一个温度对象,你可以有这样的东西:

Properties key:
temperature=The current temperature is ##代码##.

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>

The downside to this approach is that you no longer have direct access to the Label class, you can't subclass it to override isVisible()or things like that. But for my purposes it works 99% of the time.

这种方法的缺点是您不再可以直接访问 Label 类,您不能将其子类化以覆盖isVisible()或类似的东西。但就我的目的而言,它在 99% 的情况下都有效。