Ola pessoal,
Depois de um "longo e tenebroso inverno", consegui um tempinho para voltar a escrever algumas coisas que acho interessante sobre o desenvolvimento de aplicativos para dispositivos móveis, e principalmente utilizando Java ME! :)
E já que o espirito desse blog é passar para vocês algumas das minhas experiências e também soluções que encontro para algumas situações, vou mostrar hoje como resolvi um "problema" de internacionalização para aplicativos em Java ME.
O problema:
Queria fazer um aplicativo que chegasse no maior número de usuários, mas antes da aplicação em si eu tinha uma barreira: Idioma!
Não gostaria de ter uma versão diferente para cada idioma que eu fosse distribuir minha aplicação. Então, minha primeira idéia foi utilizar a JSR 238 (Mobile Internationalization API), porém ao consultar a matriz de dispositivos que implementam essa API, adivinhem só ? Poucos aparelhos e somente da Sony Ericsson.
Nesse caso, a saída então era utilizar algum "walk around" que permitisse o usuário ter a opção de escolher entre diversos idiomas, dentro de uma única distribuição do aplicativo, o que com certeza, iria facilitar a minha vida.
Solução "caseira":
Sei que a JSR 238 trata a internacionalização como um todo, e não somente a questão do idioma, mas como no meu caso o problema era SOMENTE o idioma da aplicação, minha solução caseira é com foco no suporte a diversos idiomas.
Então, criei uma classe LanguageManager que possui dois métodos estáticos para o uso dos idiomas, a interface MessagesKey que contém todas as chaves para as mensagens utilizadas no aplicativo e, claro, arquivos properties para cada idioma que se deseja disponibilizar.
Arquivos de properties:
Esse arquivo não tem nenhum mistério. Trata-se do clássico formato "CHAVE=VALOR", de forma que cada par deve estar em uma linha própria. Para facilitar a leitura desse arquivo, ele pode ter comentários em linhas iniciadas com "#".
Além da regra de "composição" do conteúdo do arquivo, o nome do arquivo também deve seguir uma regra: Ele deve estar em um diretório separado chamado "properties" e seu nome deve ser composto do código do idioma com a extensão ".properties", como por exemplo "pt-br.properties". Abaixo, exemplo de um trecho de um propertie que utilizo:
pt-br.properties
#COMMANDS
CMD_CONTINUE=Continuar
CMD_EXIT=Sair
CMD_SEARCH=Pesquisar
A interface MessagesKey
Para que o seja possível encontrar a mensagem desejada, essa classe deve conter a chave desejada, pois é através de uma referência para uma constante dessa classe que será buscada a mensagem desejada. Cada chave existente no arquivo de properties deve ter o seu correspondente nessa classe. Abaixo, exemplo da classe contendo as chaves indicadas no trecho acima do properties:
public interface MessagesKey {
/**
* Command Label
*/
public static final String CMD_CONTINUE = "CMD_CONTINUE";
public static final String CMD_EXIT = "CMD_EXIT";
public static final String CMD_SEARCH = "CMD_SEARCH";
}
A classe LanguageManager
Essa classe é a responsável pela carga do idioma desejado e também é a classe que deverá ser utilizada pelo desenvolvedor para obter o texto desejado de acordo com a chave informada. Para fazer esse "trabalho", ela tem dois métodos:
- public static boolean loadLanguage(String language) throws LanguageNotFoundException
Esse método é o responsável for fazer a "carga" do idioma desejado. O parâmetro que ele recebe é o prefixo do idioma (no caso do português do Brasil, seria pt-br), que é utilizado para carregar o propertie correspondente (pt-br.properties, no nosso exemplo). Essa carga é feita percorrendo cada linha do arquivo texto e então atribuindo o par chave/valor a um Hashtable stático (privado) da classe.
Atenção: Esse método deve ser executado ao menos uma vez antes de você tentar usar as mensagens internacionalizadas, pois ele é o responsável por carregar o Hashtable com as mensagens, senão, você com certeza terá uma exceptions de NullPointer !!! =)
Atenção: Esse método deve ser executado ao menos uma vez antes de você tentar usar as mensagens internacionalizadas, pois ele é o responsável por carregar o Hashtable com as mensagens, senão, você com certeza terá uma exceptions de NullPointer !!! =)
- public static String getMessageText (String messageKey)
Para acessar o Hashtable que possui as mensagens que devem ser exibidas, o acesso é feito por esse método que irá simplesmente devolver a String que tiver associada a chave fornecida no parâmetro. Para evitar erros de execução e simplesmente facilitar o tratamento, esse método não possui nenhum excessão, apenas retorna null caso não haja valor nenhum para a chave indicada.
Exemplo de como usar:Abaixo, vai exemplo de como utilizar a solução indicada acima:
- Carregando o idioma: Esse passo deve ser feito de preferência quando você carrega a aplicação pela primeira vez. Para facilitar meu trabalho, eu criei um parâmetro no meu JAD que indica o idioma padrão, e lá coloquei pt-br. Exemplo:
LanguageManager.loadLanguage(this.getAppProperty("DefaultLanguage"));
ou usando o idioma "explicitamente":
LanguageManager.loadLanguage("pt-br");
ou usando o idioma "explicitamente":
LanguageManager.loadLanguage("pt-br");
- Criando um novo Command, onde o label dele é "internacionalizado":
Command continueCmd = new Command(LanguageManager.getMessageText(MessagesKey.CMD_CONTINUE), Command.OK, 1);
Bom pessoal, espero que tenha ficado fácil e que isso possa ajudar a alguém!! :)Código fonte exemplo do que utilizo na minha aplicação (apenas o pacote internationalization): internationalization.zip
Abraços a todos!
Neto Marin
Um comentário:
Boa tarde Neto, muito boa sua solução era exatamente o que eu estava procurando :) Porém tive um problema ao recuperar dados com acento de uma propreties, ele nao reconhece o acento e o resultado da palavra recuperada vem desconfigurada, voce tem alguma solução que eu possa implementar para resolver este problema? muito obrigado desde já :)
Postar um comentário