Как локализовать мидлет

Автор: content Вторник, Апрель 10th, 2012 Нет комментариев

Рубрика: Java Mobile

Недавно с удивлением для себя обнаружил, что многие J2ME програмисты не используют properties файлы и вставляют строчки прямо в код. После чего имеют большие затруднения связанные с их редактированием и локализацией. Да стандартный J2MЕ не имеет в своем арсенале класс ResourseBundle, но написать свой класс предоставляющий подобные возможности не представляет большого труда.

Итак, давайте напишем такой класс Resourse. У нашего класса будет один конструктор и 3 public метода.

directory — имя директории в jar файле мидлета, в которой находятся ресурсы.
fileName — имя файла.
extenssion — расширение файла.
public Resources (String directory, String fileName, String extenssion)

Теперь перейдем к методам нашего класса.

public boolean load()
public String get (String key)
public void unload()

Метод load находит ресурс файл в jar файле, и загружает его. Если он не может этого сделать возвращает false.
Метод get (String key) возвращает ресурс.
Метод unload() освобождает все связанные c объектом Resources внутренние ресурсы.
Напишем сразу же небольшой мидлет который будет использовать класс Resources

package example;

import javax.microedition.lcdui.*;
import javax.microedition.midlet.*;

import ru.mank.me.util.Resources;

public final class Example extends MIDlet
implements CommandListener
{
/*===============[ INSTANCE VARIABLES ]=========*/
private Command exitCommand = null;

/*===============[ CLASS METHODS ]==============*/
protected void destroyApp (boolean unconditional)
throws MIDletStateChangeException
{
exitMIDlet();
}

private void exitMIDlet()
{
notifyDestroyed();
}

protected void pauseApp(){}
protected void startApp()
throws MIDletStateChangeException
{
Resources resources =
new Resources («resources», «mymidlet», «properties»);
Form form;
if (resources.load())
{
exitCommand =
new Command (resources.get(«exitCommand»), Command.EXIT, 1);
form = new Form (resources.get («title»));
StringItem countryItem = new StringItem
(resources.get («country»), resources.get («countryValue»));
StringItem townItem = new StringItem
(resources.get («town»), resources.get («townValue»));
form.append (countryItem);
form.append (townItem);

resources.unload();
}
else
{
form = new Form («Error»);
exitCommand = new Command («Exit», Command.EXIT, 1);
form.append («Cannot load resource»);
}
form.addCommand (exitCommand);
form.setCommandListener (this);
Display.getDisplay (this).setCurrent (form);
}

public void commandAction (Command c, Displayable d)
{
exitMIDlet();
}
/*============================*/
}

Cоздадим файлы mymidlet.properties и mymidlet_ru.properties и положим их в jar файл мидлета в директорию resources

mymidlet.properties:

exitCommand=Exit
title=Example
country=Country
countryValue=Russia
town=Town
townValue=Pskov

mymidlet_ru.properties:

exitCommand=\u0412\u044b\u0445\u043e\u0434
title=\u041f\u0440\u0438\u043c\u0435\u0440
country=\u0421\u0442\u0440\u0430\u043d\u0430
countryValue=\u0420\u043e\u0441\u0441\u0438\u044f
town=\u0413\u043e\u0440\u043e\u0434
townValue=\u041f\u0441\u043a\u043e\u0432

Файл mymidlet_ru.properties содержит руссифицированную версию представленную в Unicode.

Соберем наш мидлет и загрузим его в телефон. Установим в телефоне английский язык и запустим мидлет (Рис. 1).


Загрузка мидлета UTF-8 в телефонПосле этого установим в телефоне русский язык и снова запустим мидлет. (Рис. 2).

Теперь когда нам ясно как можно работать с классом Resources, рассмотрим его по подробней

package ru.mank.me.util;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

import java.util.Hashtable;

public class Resources
{
/*=============[ STATIC VARIABLES ]=============*/
public static final String LIMITER = «=»;
private static final int BUFFER_SIZE = 300;

/*=============[ INSTANCE VARIABLES ]===========*/
private Hashtable hashtable;
private char [] ac;
private String fileName = null;
private String directory;
private String extenssion = «»;
private String name;
private boolean load  = false;
private boolean error  = false;

/*=============[ CONSTRUCTORS ]=================*/
public Resources (String directory, String name,
String extenssion)
{
this.extenssion = extenssion;
this.load = false;
this.name = name;
this.directory = ‘/’ +
(directory == null || directory.trim().length() ==
0? «» : directory + ‘/’);
}

/*=============[ CLASS METHODS ]================*/
public boolean load()
{
//Если при предыдущей загрузке была ошибка,
//то возвращаем false
if (error)
return false;
InputStreamReader in = null;
try
{
//Получаем InputStream ресурс файла
InputStream inputStream = getInputStream();
if (inputStream == null)
return false;

//Создаем InputStreamReader
in = new InputStreamReader (inputStream);

//Создаем Hashtable в котором будем хранить
//содержимое ресурс файла
hashtable = new Hashtable();
ac = new char [BUFFER_SIZE];
String str;

//Читаем весь файл построчно и заполняем Hashtable
while ((str = = readLine (in)) != null)
{
int len = str.indexOf (LIMITER);
if (len > 0)
{
String key = str.substring (0, len);
String value = str.substring (len+1);
hashtable.put (key, value);
}
}

//Закрываем InputStream
in.close();
ac = null;
//Файл был загружен успешно
load = true;
return true;
}
catch (Exception io)
{
//Файл не был загружен успешно
error = true;
unload();
return false;
}
finally
{
//Закрываем InputStream
if (in != null)
try {in.close();} catch (IOException ex){}
}
}

private InputStream getInputStream()
{
//Если при предыдущей загрузке была ошибка
//то возвращаем null
if (error)
return null;
if (fileName == null)
{
//Находим нужный нам файл
InputStream in = null;
String locale =
System.getProperty («microedition.locale»);
//Читаем свойство microedition.locale,
//которое представляет
//текущий Locale (язык и страна).
//К примеру если на телефоне текушим
//является русский язык, то
//locale будет равен «ru-RU».
if (locale != null)
{
//Если locale не равен нулю
//то заменяем символ ‘-’ на ‘_’ю
locale = locale.replace (‘-’, ‘_’);

//Создаем fileName с представлением языка и страны
//например fileName_ru_RU
fileName = directory + name + «_» +
locale + «.» + extenssion;

in = this.getClass().getResourceAsStream (fileName);
if (in != null)
{
//Если ресурс найден, то возвращаем InputStream
return in;
}
else
{
//Если ресурс не найден то создаем fileName
//с представлением языка
//например fileName_ru
int i = locale.indexOf (‘_’);
if (i != -1)
{
locale = locale.substring (0, i);
fileName = directory + name + «_» + locale + «.» + extenssion;
in = this.getClass().getResourceAsStream (fileName);
if (in != null)
{
//Если ресурс найден,
//то возвращаем InputStream
return in;
}
}
}
}
//Если ресурс не найден то создаем
//fileName без представления языка и страны
fileName = directory + name + «.» + extenssion;
in = this.getClass().getResourceAsStream (fileName);
if (in == null)
{
//Ресурс не найден, возвращаем null
error = true;
unload();
return null;
}
else
{
//Если ресурс найден, то возвращаем InputStream
return in;
}
}
else
{
//Если ресурс ранее уже был загружен,
//то возвращаем InputStream
return this.getClass().getResourceAsStream (fileName);
}
}

public String get (String name)
{
if (!load)
{
//Если файл с ресурсами не был загружен,
//то загружаем его
if (!load())
{
//Если файл с ресурсами невозможно загрузить
//возвращаем пустую строчку
return «»;
}
}
String str = (String) hashtable.get (name);
if (str == null)
{
//Если ресурс не обнаружен возвращаем пустую строчку
return «»;
}
else
{
//Ура! Вот ваш ресурс!
return str;
}
}

public void unload()
{
//Если объект Resources нам временно не нужен,
//освобождаем все связанные с ним ресурсы,
//позволяя Garbage Collector’у собрать их.
hashtable = null;
ac = null;
if (fileName != null)
{
name = null;
extenssion = null;
directory = null;
}
load = false;
}

//Этот метод читает строчку из потока.
private String readLine (InputStreamReader in)
throws IOException
{
int j = 0;
StringBuffer buffer = new StringBuffer();
int r = -1;
while (j < ac.length && (r = in.read()) > 0 && r != 13)
ac [j++] = (char)r;

while (j > 0)
{
int copy = -1;
for (int k = 0; k < j;)
{
if (ac [k] == ‘\\’)
{
if (k >= BUFFER_SIZE — 6)
{
copy = k;
break;
}
if (ac [k + 1] == ‘u’)
{
try
{
int l = Integer.parseInt (new String (ac, k + 2, 4), 16);
k += 6;
buffer.append (new String (new char[]{(char)l}));
}
catch (NumberFormatException ex){}
}
else
{
buffer.append (new String (ac, k, 1));
k++;
}
}
else
{
buffer.append (new String (ac, k, 1));
k++;
}
}

if (r == 13 || r < 0)
break;
if (copy != -1)
{
int limit = j;
j = 0;
for (int i = copy; i < BUFFER_SIZE && i < limit; i++)
ac [j++] = ac[i];
}
else
j = 0;
while (j < ac.length && (r = in.read()) > 0 && r != 13)
ac [j++] = (char)r;
}
if (r == -1 && buffer.length() == 0)
return null;
else
return buffer.toString().trim();
}
}
/*=====================*/

P.S. Прошу прощения за корявость языка, но просто сложно найти к устоявшиимся выражениям на английском языке, подходящий эквивалент на русском.

Источник: http://www.javaportal.ru/mobiljava/articles/midletlocal2.html
Автор: Mank

Оставить комментарий

Чтобы оставлять комментарии Вы должны быть авторизованы.

Похожие посты