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

发布于 2024-09-28 10:19:25 字数 1016 浏览 4 评论 0原文

Wicket 有一个灵活的国际化系统,支持以多种方式参数化 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 风格的方法来执行此操作(并不比上面的方法长太多) )?

Wicket has a flexible internationalisation system that supports parameterising UI messages in many ways. There are examples e.g. in StringResourceModel javadocs, such as this:

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:

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.

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

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)?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

月棠 2024-10-05 10:19:25

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

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

msg=Value is {0}

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

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

msg=Value is {0}
小帐篷 2024-10-05 10:19:25

我认为最一致的WICKETY方式可以通过改进Jonik 的回答 MessageFormat:

.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,不使用任何其他内容
  • 您可以替换任意数量的值
  • 使用标签、info()、验证等。
  • 它并不完全是 wickety,但它与 wicket 一致,因此您可以通过 StringResourceModel 重用这些属性。

注意:

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

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

并将其作为 MessageFormat 参数传递。

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

I think the most consistent WICKETY way could be accomplished by improving Jonik's answer with MessageFormat:

.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));

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.

Notes:

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

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

and pass it as MessageFormat argument.

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

时间你老了 2024-10-05 10:19:25

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

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

msg=${} persons

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

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

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

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))));
玩套路吗 2024-10-05 10:19:25

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

.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 纯 Java 没有其他
  • 可以替换的您想要多少个值(与 ${} 技巧不同)。 编辑:好吧,如果您实际上需要支持多种语言,其中替换的值可能采用不同的顺序,String.format() 是不行的好的。相反,使用 MessageFormat 是一种类似的方法,可以正确支持这一点。

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

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 Java and nothing else
  • You can replace as many values as you want (unlike with the ${} trick). Edit: well, if you actually need to support many languages where the replaced values might be in different order, String.format() is no good. Instead, using MessageFormat is a similar approach that properly supports this.

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? :-)

深府石板幽径 2024-10-05 10:19:25

如果您的组件中有一个模型,其中包含一个对象,其中包含您想要从占位符访问的值作为替换,您可以编写:

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-

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:

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

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

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-

七度光 2024-10-05 10:19:25

为您的标签创建模型确实是The 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 ,它将根据
  2. 我创建 的给定组件可用的 IConverters 自动将对象转换为其字符串表示形式我自己的 CustomLabel 应用自定义标签文本后处理(详见 这个答案

使用自定义 IConverter(例如温度对象),您可能会得到类似的结果:

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>

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

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:

/**
 * 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 ConvertingModel which will automatically convert objects to their String representation based on the IConverters available to the given component
  2. I've created my own CustomLabel that applies custom label text post-processing (as detailed in this answer)

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

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>

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.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文