Mensagens dinâmicas com MessageFormat

Esta é uma rápida dica sobre uma classe muito útil da API Java, a classe MessageFormat. Não vou dar muitas explicações, e mais detalhes podem ser encontrados na própria API: http://download.oracle.com/javase/1.4.2/docs/api/java/text/MessageFormat.html

Dentre as muitas coisas legais que esta classe permite fazer (formatação de valores monetários, data, hora), temos uma maneira de tratar mensagens internacionalizadas (ou não) cujo conteúdo muda de acordo com o valor específico de um parâmetro. Explico melhor:

Digamos que você precise internacionalizar, ou apenas armazenar em um properties, a seguinte frase:

“Duke, você nos visitou uma vez.”

Digamos que você precise tratar esta frase, de maneira que quando a quantidade de visitas for maior, ela mude para:

“Duke, você nos visitou (n) vezes”

Certo! O tal (n) alí pode ser qualquer número, então o que muita gente faz são concatenações para conseguir o resultado esperado, por exemplo:

“Duke, você nos visitou” + n + “vezes”;

Vamos Piorar a situação? E se o Duke nunca lhe visitou, ou seja, n é igual a zero? E é lógico que não é somente o Duke que lhe visita, então você ainda tem o seguinte:

m*, você nos visitou uma vez. (quando n = 1)

m* + você nos visitou + n + vezes. (quando n > 1)

m*, você nunca nos visitou. (quando n = 0)

*onde m pode ser o Duke ou qualquer pessoa.

Isto ainda pode ficar mais complicado quando você precisa passar a mensagem para mais de um idioma, pois a posição das partes variantes (m e n) pode ser diferente na mensagem. Este cenário é comum em sistemas internacionalizados.

Apesar de a maioria dos frameworks web com foco em componentes de apresentação apresentarem algum suporte a este tipo de situação, algumas vezes será necessário tratar mensagens assim no código Java.

Para estas situações a classe MessageFormat é ideal.

Em primeiro lugar, podemos ter apenas uma mensagem que trata todas as possibilidades, acredite. Basta colocarmos, para cada parte variável da mensagem, um placeholder, que identificará a presença de um valor dinâmico. Como no exemplo temos dois valores variáveis (n e m) teremos dois placeholders na mensagem. A sintaxe de um placeholder é um numérico entre chaves: {0} e {1}. Os valores indicam a posição dos parâmetros passados para o método que formatará a mensagem.

Nossa mensagem então ficaria assim:

{1}, você nos visitou {0} vezes.

Mas espere! Isto ainda não nos atende. Apenas uma das variações da mensagem está contemplada; precisamos do tipo de formato choice: este tipo de formato nos permite escolher dinamicamente uma parte da mensagem de acordo com o valor passado a um placeholder:

{1}, você {0,choice,0# nunca nos visitou.|1# nos visitou uma vez.|1<nos visitou {0,number,integer} vezes}.

Na mensagem acima, está em destaque a sintaxe do tipo de formatação choice; ele é colocado após o número do placeholder, depois de uma vírgula.

Em vermelho está o texto que será apresentado caso o valor passado ao placeholder seja zero. Em verde está o texto que será apresentado caso o valor passado ao placeholder seja um. Em azul está o texto que será apresentado caso o valor passado ao placeholder seja maior que um.

OK, mas como fazer a mágica da transformação? Basta passar a mensagem e os parâmetros para o método format, da classe MessageFormat. Abaixo coloco uma classe de exemplo, que mostra ainda a mesma mensagem traduzida em inglês e espanhol, para demonstrar que a localização dos placeholders pode mudar sem afetar o resultado esperado.


import java.text.MessageFormat;

public class FormatacaoMensagem{

private static String ingles = "You have {0,choice,0#never visited us|1#visited us once|1<visited us {0,number,integer} times}, {1}.";
private static String portugues = "{1}, você {0,choice,0#nunca nos visitou.|1#nos visitou uma vez.|1<nos visitou {0,number,integer} vezes}.";
private static String espanhol = "Usted {0,choice,0#nunca nos ha visitado, {1}|1#nos ha visitado una vez, {1}|1<nos ha visitado {0,number,integer} veces, {1}}.";

public static void main(String[] args){

Object[] nenhum = {
new Integer(0),
"Duke"

};

Object[] um = {
new Integer(1),
"Duke"

};

Object[] varios = {
new Integer(2),
"Duke"

};

System.out.println( MessageFormat.format(ingles, nenhum) );
System.out.println( MessageFormat.format(ingles, um) );
System.out.println( MessageFormat.format(ingles, varios) );

System.out.println( MessageFormat.format(portugues, nenhum) );
System.out.println( MessageFormat.format(portugues, um) );
System.out.println( MessageFormat.format(portugues, varios) );

System.out.println( MessageFormat.format(espanhol, nenhum) );
System.out.println( MessageFormat.format(espanhol, um) );
System.out.println( MessageFormat.format(espanhol, varios) );

}
}

Eis o resultado final:

Vale a pena conferir a API para as outras opções que a classe oferece.

Está dada a dica!

Um comentário sobre “Mensagens dinâmicas com MessageFormat

Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s