001: /*
002: *
003: * Copyright (c) 2007, Sun Microsystems, Inc.
004: *
005: * All rights reserved.
006: *
007: * Redistribution and use in source and binary forms, with or without
008: * modification, are permitted provided that the following conditions
009: * are met:
010: *
011: * * Redistributions of source code must retain the above copyright
012: * notice, this list of conditions and the following disclaimer.
013: * * Redistributions in binary form must reproduce the above copyright
014: * notice, this list of conditions and the following disclaimer in the
015: * documentation and/or other materials provided with the distribution.
016: * * Neither the name of Sun Microsystems nor the names of its contributors
017: * may be used to endorse or promote products derived from this software
018: * without specific prior written permission.
019: *
020: * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
021: * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
022: * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
023: * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
024: * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
025: * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
026: * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
027: * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
028: * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
029: * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
030: * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
031: */
032: package example.mia.demo;
033:
034: import java.util.Vector;
035:
036: import javax.microedition.global.ResourceException;
037: import javax.microedition.global.ResourceManager;
038: import javax.microedition.lcdui.*;
039: import javax.microedition.midlet.*;
040:
041: /**
042: * MicroLexicon midlet is an example for JSR238 (Mobile Internationalization API)
043: * @see http://www.jcp.org/en/jsr/detail?id=238
044: *
045: * Example uses device resources of the emulator as well as application
046: * resources bundled with the application.<br>
047: * To see content of device resource files use manager
048: * <i>WTK_HOME/bin/i18ntool.</i>. To see content of application resource
049: * files use <i>i18n Resource Manager</i> from ktoolbar, look into menu project.
050: * Application resources are placed under example's <project name>/res directory.
051: * You will see how easy is to add your own language to the lexicon ;-)
052: *
053: *
054: * @version 1.4
055: */
056: public class MicroLexicon extends MIDlet implements CommandListener {
057: /** constant saying that phrases resource ids start from 100 */
058: private static final int PHRASES_OFFSET = 100;
059:
060: /** language choice item index */
061: private static final int ITEM_LANG_CHOICE = 2;
062:
063: /** flag image item index*/
064: private static final int ITEM_FLAG = 0;
065:
066: /** phrase list item index */
067: private static final int ITEM_PHRASE = 2;
068:
069: /** resource id constants definitions for language names */
070: private static final int RES_LANG_EN_US = 201;
071: private static final int RES_LANG_CS_CZ = 202;
072: private static final int RES_LANG_SK_SK = 203;
073: private static final int RES_LANG_HE_IL = 204;
074: private static final int RES_LANG_ZH_CN = 205;
075: private static final int RES_LANG_JA_JP = 206;
076: private static final int RES_LANG_DE_DE = 207;
077: private static final int RES_LANG_IT_IT = 208;
078: private static final int RES_LANG_ES_ES = 209;
079:
080: /** resource id constant for flag image */
081: private static final int RES_FLAG = 101;
082:
083: /** resource id constant for welcome message*/
084: private static final int RES_WELCOME_MSG = 1;
085:
086: /** resource id for company title */
087: private static final int RES_COMPANY = 2;
088:
089: /** resource ids for screen titles */
090: private static final int RES_TITLE_1 = 3;
091: private static final int RES_TITLE_2 = 4;
092: private static final int RES_TITLE_3 = 5;
093:
094: /** bundle names */
095: private static final String COMMON_RESOURCE_NAME = "common";
096: private static final String PHRASES_RESOURCE_NAME = "phrases";
097:
098: /**
099: * Resource ids for control buttons
100: * are read from device resources
101: */
102: private static final int RES_EXIT = 101;
103: private static final int RES_NEXT = 102;
104: private static final int RES_BACK = 103;
105:
106: /**
107: * Phrases are read from resources
108: * but the array is initialized with defaults (english)
109: */
110: static final String[] phrases = new String[] { "Hello",
111: "Good morning", "How are you?", "See you", "I am fine",
112: "I like wtk", "What is the time?", "How much is it?",
113: "I want one beer", "I want next beer" };
114:
115: /** Resource Manager of target language */
116: static ResourceManager targetPhrasesManager;
117:
118: /** resources manager for accessing phrases */
119: static ResourceManager phrasesManager;
120:
121: /** resources manager for accessing ui resources */
122: static ResourceManager uiManager;
123:
124: /** device resources manager */
125: static ResourceManager devManager;
126:
127: /** languages available */
128: Languages languages = null;
129:
130: /** currently visible screen */
131: Displayable currentDisplay;
132:
133: /** screens lazy initialize */
134: Form frmLangChooser = null;
135: List lstPhraseChooser = null;
136: Form frmTranslate = null;
137:
138: /** language selected */
139: String language;
140:
141: /** flag selected */
142: Image flag;
143:
144: /** phrase selected */
145: String phrase;
146: int phraseId;
147:
148: /** commands definitions */
149: Command exitCommand;
150: Command nextCommand;
151: Command backCommand;
152:
153: /**
154: * Start application.
155: * By default initialized with form for choosing languages
156: */
157: public void startApp() {
158: if (!initResources()) {
159: Form errFrm = new Form("Error",
160: new Item[] { new StringItem(null,
161: "Cannot load resources!") });
162: exitCommand = new Command("Exit", Command.EXIT, 1);
163: errFrm.addCommand(exitCommand);
164: errFrm.setCommandListener(this );
165: setDisplay(errFrm);
166: } else {
167: initCommands();
168: currentDisplay = getLangChooserForm();
169: setDisplay(getLangChooserForm());
170: initPhrases();
171: }
172: }
173:
174: public void pauseApp() {
175: }
176:
177: public void destroyApp(boolean unconditional) {
178: }
179:
180: public void commandAction(Command command, Displayable displayable) {
181: if (command == exitCommand) { // immediately exit application
182: destroyApp(true);
183: notifyDestroyed();
184: } else if (command == nextCommand) {
185: if (currentDisplay == frmLangChooser) {
186: // get the chosen language and go to phrases
187: ChoiceGroup grp = (ChoiceGroup) getLangChooserForm()
188: .get(ITEM_LANG_CHOICE);
189: int idx = grp.getSelectedIndex();
190: language = grp.getString(idx);
191: flag = languages.getFlagForLanguage(language);
192: setDisplay(getPhraseChooserList());
193: } else if (currentDisplay == lstPhraseChooser) {
194: setDisplay(getTranslatedForm());
195: }
196: } else if (command == backCommand) {
197: if (currentDisplay == lstPhraseChooser) {
198: setDisplay(getLangChooserForm());
199: } else if (currentDisplay == frmTranslate) {
200: setDisplay(getPhraseChooserList());
201: }
202: } else if (command == List.SELECT_COMMAND) {
203: if (currentDisplay == lstPhraseChooser) {
204: //get chosen phrase and go to translation page
205: int idx = lstPhraseChooser.getSelectedIndex();
206: phrase = lstPhraseChooser.getString(idx);
207: phraseId = idx;
208: setDisplay(getTranslatedForm());
209: }
210: }
211: }
212:
213: private boolean initResources() {
214: try {
215: phrasesManager = ResourceManager.getManager("phrases");
216: uiManager = ResourceManager.getManager("common");
217: devManager = ResourceManager.getManager("");
218: } catch (ResourceException re) {
219: re.printStackTrace();
220:
221: return false;
222: }
223:
224: return true;
225: }
226:
227: private void initCommands() {
228: exitCommand = new Command(devManager.getString(RES_EXIT),
229: Command.EXIT, 1);
230: nextCommand = new Command(devManager.getString(RES_NEXT),
231: Command.SCREEN, 1);
232: backCommand = new Command(devManager.getString(RES_BACK),
233: Command.BACK, 1);
234: }
235:
236: /**
237: * Load phrases into array.
238: */
239: private void initPhrases() {
240: int resourceId = 0;
241: ResourceManager rm = phrasesManager;
242:
243: for (int i = 0; i < phrases.length; i++) {
244: try {
245: resourceId = PHRASES_OFFSET + i;
246: phrases[i] = rm.getString(resourceId);
247: } catch (ResourceException re) {
248: System.err.println("Resource with id " + resourceId
249: + "not found");
250: }
251: }
252: }
253:
254: /**
255: * display another screen
256: */
257: private void setDisplay(Displayable d) {
258: Display.getDisplay(this ).setCurrent(d);
259: currentDisplay = d;
260: }
261:
262: /**
263: * Form definition for choosing languages.
264: * Contains welcome message and ChoiceGroup of languages.
265: */
266: private Form getLangChooserForm() {
267: if (frmLangChooser == null) {
268: String title = uiManager.getString(RES_COMPANY);
269: frmLangChooser = new Form(
270: title,
271: new Item[] {
272: new StringItem(
273: null,
274: "Running in locale: "
275: + System
276: .getProperty("microedition.locale")),
277: new StringItem(null, uiManager
278: .getString(RES_WELCOME_MSG)),
279: new ChoiceGroup(uiManager
280: .getString(RES_TITLE_1)
281: + ":", Choice.POPUP, getLanguages()
282: .getNames(), null) });
283: frmLangChooser.addCommand(exitCommand);
284: frmLangChooser.addCommand(nextCommand);
285: frmLangChooser.setCommandListener(this );
286: language = getLanguages().getNames()[0];
287: }
288:
289: return frmLangChooser;
290: }
291:
292: /**
293: * Screen for choosing phrases contains list
294: * filled with phrases.
295: */
296: private List getPhraseChooserList() {
297: if (lstPhraseChooser == null) {
298: lstPhraseChooser = new List(uiManager
299: .getString(RES_TITLE_2)
300: + ":", Choice.IMPLICIT, phrases, null);
301: lstPhraseChooser.setFitPolicy(Choice.TEXT_WRAP_ON);
302: lstPhraseChooser.addCommand(exitCommand);
303: lstPhraseChooser.addCommand(backCommand);
304: lstPhraseChooser.setCommandListener(this );
305: phrase = phrases[0];
306: phraseId = 0;
307: }
308:
309: String code = languages.getCodeForLanguage(language);
310: // depending on language switch to another resource file
311: targetPhrasesManager = ResourceManager.getManager("phrases",
312: code);
313:
314: return lstPhraseChooser;
315: }
316:
317: /**
318: * Initialize form displaying translated phrase.
319: * Form contains country flag and phrase translation.
320: */
321: private Form getTranslatedForm() {
322: if (frmTranslate == null) {
323: frmTranslate = new Form(uiManager.getString(RES_TITLE_3)
324: + ":", new Item[] {
325: new ImageItem(null, Image.createImage(1, 1),
326: Item.LAYOUT_LEFT | Item.LAYOUT_TOP, ""),
327: new Spacer(10, 10), new StringItem("", "") });
328: frmTranslate.addCommand(exitCommand);
329: frmTranslate.addCommand(backCommand);
330: frmTranslate.setCommandListener(this );
331: }
332:
333: ImageItem iimage = (ImageItem) frmTranslate.get(ITEM_FLAG);
334: iimage.setImage(flag);
335:
336: StringItem istring = (StringItem) frmTranslate.get(ITEM_PHRASE);
337: istring.setText(translate(phraseId, phrase));
338:
339: return frmTranslate;
340: }
341:
342: /**
343: * Translation just retrieves string resource of
344: * given resource id.
345: */
346: private String translate(int id, String text) {
347: try {
348: return targetPhrasesManager.getString(PHRASES_OFFSET + id);
349: } catch (ResourceException re) {
350: return "Phrase translation not found";
351: }
352: }
353:
354: /**
355: * Initialize languages class
356: */
357: private Languages getLanguages() {
358: if (languages == null) {
359: languages = Languages.getInstance();
360: }
361:
362: return languages;
363: }
364:
365: /**
366: * Helper class holds language names, locale codes and flags all in one.
367: */
368: static class Languages {
369: static Languages ls = null;
370: private Object[] langlist;
371:
372: private Languages() {
373: init();
374: }
375:
376: private void init() {
377: ResourceManager rm = uiManager;
378:
379: //offsets of objects in common resources
380: int lang_offset = 200;
381: int flag_offset = 100;
382:
383: //initialize language names and flags
384: String[] availableLocales = ResourceManager
385: .getSupportedLocales(COMMON_RESOURCE_NAME);
386: int localesCount = availableLocales.length;
387:
388: Vector languagesV = new Vector();
389: Vector flagsV = new Vector();
390: Vector localesV = new Vector();
391: int idx = 1;
392:
393: for (int i = 1; i < localesCount; i++) {
394: try {
395: String language = rm.getString(lang_offset + idx);
396:
397: if ((language != null) && (language.length() > 0)) {
398: byte[] idata = rm.getData(flag_offset + idx);
399: Image flag = Image.createImage(idata, 0,
400: idata.length);
401: languagesV.addElement(language);
402: flagsV.addElement(flag);
403: localesV.addElement(availableLocales[idx]);
404: idx++;
405: }
406: } catch (ResourceException e) {
407: }
408: }
409:
410: String[] languages = new String[languagesV.size()];
411: String[] locales = new String[localesV.size()];
412: Image[] flags = new Image[flagsV.size()];
413: languagesV.copyInto(languages);
414: localesV.copyInto(locales);
415: flagsV.copyInto(flags);
416: langlist = new Object[] { languages, locales, flags };
417:
418: localesV = null;
419: languagesV = null;
420: flagsV = null;
421: }
422:
423: static Languages getInstance() {
424: if (ls == null) {
425: ls = new Languages();
426: }
427:
428: return ls;
429: }
430:
431: /** @return all language names */
432: String[] getNames() {
433: return (String[]) langlist[0];
434: }
435:
436: /** @return all locale codes */
437: String[] getCodes() {
438: return (String[]) langlist[1];
439: }
440:
441: /** @return all country flags */
442: Image[] getFlags() {
443: return (Image[]) langlist[2];
444: }
445:
446: /** @return flag for given language */
447: Image getFlagForLanguage(String lang) {
448: String[] languages = getNames();
449:
450: for (int i = 0; i < languages.length; i++) {
451: if (languages[i].equals(lang)) {
452: return getFlags()[i];
453: }
454: }
455:
456: return Image.createImage(10, 10);
457: }
458:
459: /** @return locale code for given language */
460: String getCodeForLanguage(String lang) {
461: String[] languages = getNames();
462:
463: for (int i = 0; i < languages.length; i++) {
464: if (languages[i].equals(lang)) {
465: return getCodes()[i];
466: }
467: }
468:
469: return "";
470: }
471: }
472: }
|