Locale.java
上传用户:liming6160
上传日期:2022-06-07
资源大小:785k
文件大小:10k
源码类别:

J2ME

开发平台:

Java

  1. /*
  2.  *    Copyright (C) 2001 - 2007 Mobicom-Kavkaz, Inc
  3.  *    MFRadio - stream radio client for Java 2 Micro Edition
  4.  *    
  5.  *    Visit the project page at: http://mfradio.sourceforge.net
  6.  *
  7.  *    This program is free software; you can redistribute it and/or modify
  8.  *    it under the terms of the GNU General Public License as published by
  9.  *    the Free Software Foundation; either version 2 of the License, or
  10.  *    (at your option) any later version.
  11.  *
  12.  *    This program is distributed in the hope that it will be useful,
  13.  *    but WITHOUT ANY WARRANTY; without even the implied warranty of
  14.  *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15.  *    GNU General Public License for more details.
  16.  *
  17.  *    You should have received a copy of the GNU General Public License
  18.  *    along with this program; if not, write to the Free Software
  19.  *    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  20.  *
  21.  *    Java (TM) and all Java (TM)-based marks are a trademark or 
  22.  *    registered trademark of Sun Microsystems, Inc, in the United States 
  23.  *    and other countries.
  24.  */
  25. package ru.mobicomk.mfradio.util;
  26. import java.io.EOFException;
  27. import java.io.InputStream;
  28. import java.util.Enumeration;
  29. import java.util.Hashtable;
  30. /**
  31.  * <h2>Native language text support for UI</h2>
  32.  * <p>
  33.  * The midlet uses very basic localization system which includes folowing UTF-8
  34.  * plain text files:
  35.  * 
  36.  * <pre>
  37.  *   lang.lst
  38.  *   [locale name in &quot;lang.lst&quot;].lng
  39.  *   [locale name in &quot;lang.lst&quot;].lng
  40.  *   .... 
  41.  * </pre>
  42.  * 
  43.  * File named <code>lang.lst</code> contains list of available loclaizations.
  44.  * Each line of the file uses format
  45.  * 
  46.  * <pre>
  47.  *  [locale name]=[language name in native spelling]
  48.  * </pre>
  49.  * 
  50.  * For example: <code>en=English</code>. Other files contains localized
  51.  * messages according to the file names. Thus file <code>en.lng</code> is used
  52.  * for messages in English. Message file format is
  53.  * 
  54.  * <pre>
  55.  *   [message key]=[message text]
  56.  * </pre>
  57.  * 
  58.  * Simple formatting language is available for message text files. It uses some
  59.  * character sequences and links to previosuly declared message keys in the
  60.  * file. Tags "p", "h1" and "h2" have the same meaning as in HTML. Each new
  61.  * line of message lays on separate line in source file.
  62.  * <p>
  63.  * <h3>Multiline text example with formatting</h3>
  64.  * 
  65.  * <p>
  66.  * <code><pre>
  67.  *   PlayerUI_help_text=h1 Controls
  68.  *   p   - select station in the list.
  69.  *   h2 Right(4)/Left(6)
  70.  *   p   - volume control.
  71.  *   h2 OK(5)
  72.  *   p   - start/stop station playback.
  73.  *   h1 Menu
  74.  *   h2 &lt;Add&gt;
  75.  *   p   - add station.
  76.  *   h2 &lt;Play&gt;/&lt;Stop&gt;
  77.  *   p   - play/stop on selected station.
  78.  *   h2 &lt;Edit&gt;
  79.  *   p   - change station settings.
  80.  *   h2 &lt;Delete&gt;
  81.  *   p   - remove station from playlist.
  82.  *   h2 &lt;Exit&gt;
  83.  *   p   - exit the player.
  84.  * </pre></code>
  85.  * 
  86.  * <p>
  87.  * It is possible to inline the text of other previously declared message in the
  88.  * file.
  89.  * <h3>Inlined text example</h3>
  90.  * <p>
  91.  * Source text that uses inlined messages: <code><pre>
  92.  *   ...
  93.  *   Playlist=Список станций
  94.  *   ...
  95.  *   ...
  96.  *   WAPUI_help_text=...
  97.  *   ...
  98.  *   p   - таким значком обозначены ссылки, которые не могут быть добавлены в Ваш '
  99.  * </code>
  100.  *  &amp;lt
  101.  * <code>
  102.  *  Playlist&gt;'.
  103.  *   ...
  104.  * </pre></code> Message with name <code>WAPUI_help_text</code> will be displayed
  105.  * as: <code><pre>
  106.  *  p   - таким значком обозначены ссылки, которые не могут быть добавлены в Ваш 'Список станций'.
  107.  * </pre></code> <br>
  108.  * 
  109.  * @author Alexey Rybalko
  110.  * @see ru.mobicomk.mfradio.controller.UIController
  111.  */
  112. public final class Locale {
  113.     private String locale;
  114.     private Hashtable stringHash;
  115.     private static Hashtable localeHash;
  116.     // private static String[] availableLocaleNames;
  117.     private Locale(String name) {
  118.         this.locale = name;
  119.     }
  120.     public synchronized String getString(final String key) {
  121.         if (stringHash == null) {
  122.             stringHash = new Hashtable();
  123.             loadProperties(stringHash, "/locale/" + locale + ".lng", true);
  124.         }
  125.         final String value = (String) stringHash.get(key);
  126.         return (value != null) ? value : key;
  127.     }
  128.     public String getName() {
  129.         return locale;
  130.     }
  131.     public String getNativeName() {
  132.         loadLocaleHash();
  133.         return (String) localeHash.get(locale);
  134.     }
  135.     public boolean equals(Object obj) {
  136.         boolean isEqual = false;
  137.         if (obj.getClass().equals(getClass())) {
  138.             Locale otherLocale = (Locale) obj;
  139.             isEqual = otherLocale.getName().equals(locale);
  140.         } else {
  141.             isEqual = super.equals(obj);
  142.         }
  143.         return isEqual;
  144.     }
  145.     public String toString() {
  146.         return locale;
  147.     }
  148.     /**
  149.      * Get available locales for application
  150.      * 
  151.      * @return array of Locale objects
  152.      */
  153.     public static Locale[] getAvailable() {
  154.         loadLocaleHash();
  155.         Enumeration keysEnum = localeHash.keys();
  156.         Locale[] locales = new Locale[localeHash.size()];
  157.         int i = 0;
  158.         while (keysEnum.hasMoreElements()) {
  159.             String name = (String) keysEnum.nextElement();
  160.             locales[i++] = new Locale(name);
  161.         }
  162.         return locales;
  163.     }
  164.     private static void loadLocaleHash() {
  165.         if (localeHash == null) {
  166.             localeHash = new Hashtable();
  167.             loadProperties(localeHash, "/locale/lang.lst", false);
  168.         }
  169.     }
  170.     /**
  171.      * Get locale object for its name
  172.      * 
  173.      * @param localeName
  174.      *            shortage for locale. E.g. "ru" for Russian
  175.      * @return Locale object requested
  176.      */
  177.     public static Locale getForName(String localeName) {
  178.         loadLocaleHash();
  179.         return new Locale(localeName);
  180.     }
  181.     private static void loadProperties(Hashtable propertiesTable, String resourceName, boolean inlineTags) {
  182.         try {
  183.             propertiesTable.clear();
  184.             InputStream inStream = propertiesTable.getClass().getResourceAsStream(resourceName);
  185.             byte[] buf = new byte[1024];
  186.             byte b;
  187.             int bytesInLine = 0;
  188.             String key = null;
  189.             String lastKey = null;
  190.             StringBuffer valueBuf = null;
  191.             boolean EOF = false;
  192.             while (!EOF) {
  193.                 b = (byte) inStream.read();
  194.                 switch (b) {
  195.                     case -1:
  196.                         EOF = true;
  197.                     case 'n':
  198.                         String str = decodeUTF8(buf, 0, bytesInLine);
  199.                         int delimiterPos = str.indexOf('=');
  200.                         if (delimiterPos != -1) {
  201.                             if (lastKey != key && (valueBuf != null)) {
  202.                                 putToHash(propertiesTable, inlineTags, key, valueBuf);
  203.                             }
  204.                             lastKey = key;
  205.                             key = str.substring(0, delimiterPos);
  206.                             valueBuf = new StringBuffer(str.substring(delimiterPos + 1));
  207.                         } else {
  208.                             valueBuf.append('n' + str);
  209.                         }
  210.                         if (EOF) {
  211.                             putToHash(propertiesTable, inlineTags, key, valueBuf);
  212.                         }
  213.                         bytesInLine = 0;
  214.                         break;
  215.                     default:
  216.                         if (b != 'r') {
  217.                             buf[bytesInLine++] = b;
  218.                         }
  219.                 }
  220.             }
  221.             inStream.close();
  222.         } catch (EOFException ex) {
  223.         } catch (Exception ex) {
  224.             ex.printStackTrace();
  225.         }
  226.         System.gc();
  227.     }
  228.     private static void putToHash(Hashtable propertiesTable, boolean inlineTags, String key, StringBuffer valueBuf) {
  229.         String value = valueBuf.toString();
  230.         if (inlineTags) {
  231.             value = inlineTags(propertiesTable, value);
  232.         }
  233.         propertiesTable.put(key, value);
  234.     }
  235.     private static String decodeUTF8(byte data[], int offset, int length) {
  236.         StringBuffer buff = new StringBuffer();
  237.         int max = offset + length;
  238.         for (int i = offset; i < max; i++) {
  239.             char c = 0;
  240.             if ((data[i] & 0x80) == 0) {
  241.                 c = (char) data[i];
  242.             } else if ((data[i] & 0xe0) == 0xc0) {
  243.                 c |= ((data[i++] & 0x1f) << 6);
  244.                 c |= ((data[i] & 0x3f) << 0);
  245.             } else if ((data[i] & 0xf0) == 0xe0) {
  246.                 c |= ((data[i++] & 0x0f) << 12);
  247.                 c |= ((data[i++] & 0x3f) << 6);
  248.                 c |= ((data[i] & 0x3f) << 0);
  249.             } else if ((data[i] & 0xf8) == 0xf0) {
  250.                 c |= ((data[i++] & 0x07) << 18);
  251.                 c |= ((data[i++] & 0x3f) << 12);
  252.                 c |= ((data[i++] & 0x3f) << 6);
  253.                 c |= ((data[i] & 0x3f) << 0);
  254.             } else {
  255.                 c = '?';
  256.             }
  257.             buff.append(c);
  258.         }
  259.         return buff.toString();
  260.     }
  261.     private static String inlineTags(Hashtable propertiesTable, final String value) {
  262.         String inlinedStr = value;
  263.         int tagStart;
  264.         StringBuffer strBuf = new StringBuffer(inlinedStr);
  265.         while ((tagStart = inlinedStr.indexOf('<')) != -1) {
  266.             int tagEnd = inlinedStr.indexOf('>');
  267.             String key = inlinedStr.substring(tagStart + 1, tagEnd);
  268.             strBuf.delete(tagStart, tagEnd + 1);
  269.             String msg = (String) propertiesTable.get(key);
  270.             strBuf.insert(tagStart, (msg == null) ? key : msg);
  271.             inlinedStr = strBuf.toString();
  272.         }
  273.         return inlinedStr;
  274.     }
  275. }