2010-10-20 12 views
10

Wicket tiene un flexible internationalisation system que admite la parametrización de mensajes de IU de muchas maneras. Hay ejemplos, p. en StringResourceModel javadocs, como este:¿Manera simple de usar mensajes de IU parametrizados en Wicket?

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

Pero quiero algo realmente sencillo , y no podía encontrar un buen ejemplo de ello.

Considere este tipo de mensaje de interfaz de usuario en un archivo .properties:

msg=Value is {0} 

En concreto, no me gustaría crear un objeto del modelo (con captadores para los valores que ser reemplazado, al igual que en el anterior WeatherStation ejemplo) solo para este propósito. Eso es demasiado exagerado si ya tengo los valores en las variables locales, y de lo contrario no hay necesidad de tal objeto.

Aquí está una manera estúpida "fuerza bruta" para reemplazar el {0} con el valor correcto:

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

¿Hay una forma más limpia, Wicket-y para hacer esto (que no es terriblemente mucho más tiempo que el anterior) ?

Respuesta

4

creo que el más consistente WICKETY manera podría lograrse mediante la mejora de Jonik's answer con 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)); 

por eso me gusta:

  • Limpio, solución simple
  • Usos de Java convencionales y nada más
  • Puede reemplazar tantos valores como desee
  • Trabaja con etiquetas, info(), validación, etc.
  • No es completamente impresionante, pero es consistente con wicket por lo que puede reutilizar estas propiedades con StringResourceModel.

Notas:

si desea utilizar modelos sólo hay que crear un modelo simple que anula toString función del modelo así:

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

y pasarlo como MessageFormat argumento.

No sé por qué Wicket no es compatible con Model en el mensaje de respuesta. pero si era compatible no había ninguna razón para usar estas soluciones y podría usar StringResourceModel en todas partes.

+1

Sí, de hecho, esta es básicamente una versión mejorada de 'String.format()' [que sugerí] (http://stackoverflow.com/a/10249630/56285), con la diferencia clave de que 'MessageFormat' verdaderamente admite muchos idiomas ya que el orden de los parámetros reemplazados está explícitamente especificado. – Jonik

+0

@Jonik sí tienen razón:) –

5

Hay una manera, que aunque todavía implica la creación de un modelo, no requiere un frijol con un captador.

dado este mensaje en un archivo de propiedades:

msg=${} persons 

Así es como para reemplazar el marcador de posición con un valor, ya sea una variable local, un campo o un literal:

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

Gracias!Por cierto, ¿conoces algún nombre para esta notación '$ {}', y está documentado en alguna parte? ¿Sería posible reemplazar más de un marcador de posición (algo como '$ {0}' y '$ {1}'?) En un mensaje usando este enfoque? – Jonik

+2

$ {} es simplemente una abreviatura de llamadas de método contra el objeto modelo en sí. No sé el nombre. $ {} creo que solo hace model.toString(), pero para cosas como convención-sobre-configuración de nombres de teclas de recursos para títulos de página puede hacer algo como "agregar (nueva etiqueta (" título ", nuevo StringResourceModel (" $ { class.simpleName} .title ", this, currentPageModel))" –

0

Creación de una El modelo para su etiqueta es realmente The Wicket Way. Dicho esto, puede hacer que sea fácil para usted con la función de utilidad ocasional. Aquí hay una que utilice:

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

Detalles estoy pasando por alto aquí son:

  1. He creado mi propia ConvertingModel que convertirá automáticamente los objetos a su representación de cadena basado en los IConverters disponibles para el determinado componente
  2. he creado mi propia CustomLabel que se aplica la etiqueta de encargo del texto de post-procesamiento (como se detalla en this answer)

Con un Iconverter personalizada para, por ejemplo, un objeto de la temperatura, que podría tener algo como:

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> 

La desventaja de este enfoque es que ya no tiene acceso directo a la clase de etiqueta, no se puede subclase para anular isVisible() o cosas por el estilo. Pero para mi propósito, funciona el 99% del tiempo.

2

Cuando se enfrentan con algo como se describe en la pregunta, ahora me gustaría utilizar:

.propiedades:

msg=Saving record %s with value %d 

Java:

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

Por qué me gusta:

  • Limpio, solución simple
  • Usos plain Java y nada más
  • Puede reemplazar tantos valores como quieras (a diferencia del ${} trick). Editar: bueno, si realmente necesita admitir muchos idiomas donde los valores reemplazados pueden estar en orden diferente, String.format() no es bueno. En cambio, using MessageFormat is a similar approach que lo admite correctamente.

responsabilidad: esto es "demasiado obvio", pero es más simple que las otras soluciones (y sin duda mejor que mi replaceAll() truco original). Originalmente busqué una forma de "Wicket-y", mientras que este tipo pasa por alto Wicket —, de nuevo, ¿a quién le importa? :-)

+0

Una ventaja más: puede utilizar exactamente el mismo enfoque para los mensajes de retroalimentación (métodos como info(), error() en Componente y Sesión), dando consistencia a su código Por ejemplo: 'info (String.format (getString (" events.created "), events.size()));' – Jonik

+0

PUEDE tener orden diferente con la solución% s: msg =% 2 $ s% 1 $ s – Raigedas

11

Tome un vistazo a Ejemplo 4 en el javadoc StringResourceModel - se puede pasar de un modelo nulo y los parámetros explícitos:

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

msg=Value is {0} 
Cuestiones relacionadas