001: /*
002: * SQLeonardo :: java database frontend
003: * Copyright (C) 2004 nickyb@users.sourceforge.net
004: *
005: * This program is free software; you can redistribute it and/or
006: * modify it under the terms of the GNU General Public License
007: * as published by the Free Software Foundation; either version 2
008: * of the License, or (at your option) any later version.
009: *
010: * This program is distributed in the hope that it will be useful,
011: * but WITHOUT ANY WARRANTY; without even the implied warranty of
012: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
013: * GNU General Public License for more details.
014: *
015: * You should have received a copy of the GNU General Public License
016: * along with this program; if not, write to the Free Software
017: * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
018: *
019: * File contributed by JasperSoft Corp.
020: */
021:
022: package nickyb.sqleonardo.common.util;
023:
024: import java.util.*;
025: import java.util.jar.*;
026: import java.net.*;
027: import java.io.*;
028:
029: public class I18n {
030: private static String localPackageName = "nickyb/sqleonardo/common/locale/";
031: private static String baseName = "sqleonardo";
032: private static java.util.ResourceBundle oLanguage = null;
033:
034: public static java.util.Vector languageChangedListeners = null;
035:
036: static {
037: languageChangedListeners = new Vector();
038: }
039:
040: public static void addOnLanguageChangedListener(
041: LanguageChangedListener listener) {
042: languageChangedListeners.add(listener);
043: }
044:
045: /**
046: * Look in the classpath for locale resource bundles.
047: * Return a list of Locale objects.
048: *
049: */
050: public static java.util.List getListOfAvailLanguages() {
051: java.util.List supportedLocales = new java.util.ArrayList();
052: try {
053: Set names = getResoucesInPackage(getLocalPackageName());
054: Iterator it = names.iterator();
055: while (it.hasNext()) {
056: String n = (String) it.next();
057:
058: String lang = n.substring(n.lastIndexOf('/') + 1);
059:
060: // only except resources with extension '.properties'
061: if (lang.indexOf(".properties") < 0) {
062: continue; // not very nice but efficient
063: //TODO: wrap the curly braces around the next statements
064: }
065:
066: lang = lang.substring(0, lang.indexOf(".properties"));
067:
068: StringTokenizer tokenizer = new StringTokenizer(lang,
069: "_");
070: if (tokenizer.countTokens() <= 1) {
071: // empty filename or "iReport.properties"
072: continue; // not very nice but efficient
073: //TODO: wrap the curly braces around the next statements
074: }
075:
076: String language = "";
077: String country = "";
078: String variant = "";
079:
080: //String[] parts = new String[tokenizer.countTokens()];
081: // first token (position 0) is iReport
082: //System.out.println( "\n File: " + lang + "\n" );
083:
084: //System.out.println( "\n Aantal tokens: " + " " + tokenizer.countTokens() + "\n" );
085: int i = 0;
086: while (tokenizer.hasMoreTokens()) {
087: String token = tokenizer.nextToken();
088:
089: //System.out.println( "\n" + i + " " + token + "\n" );
090:
091: switch (i) {
092: case 0:
093: //the word iReport
094: break;
095: case 1:
096: language = token;
097: break;
098: case 2:
099: country = token;
100: break;
101: case 3:
102: variant = token;
103: break;
104: default:
105: //
106: }
107: i++;
108:
109: }
110:
111: Locale model = new Locale(language, country, variant);
112: supportedLocales.add(model);
113:
114: }
115: } catch (Exception e) {
116: e.printStackTrace();
117: }
118:
119: // Sort the list. Probably should use the current locale when getting the
120: // DisplayLanguage so the sort order is correct for the user.
121: Collections.sort(supportedLocales, new Comparator() {
122: public int compare(Object lhs, Object rhs) {
123: //Locale ll = (Locale)lhs;
124: //Locale rl = (Locale)rhs;
125: String ls = ((Locale) lhs).getDisplayLanguage();
126: String rs = ((Locale) rhs).getDisplayLanguage();
127:
128: //return ll.getDisplayLanguage().compareTo( rl.getDisplayLanguage() );
129: return ls.compareTo(rs);
130: }
131: });
132:
133: return supportedLocales;
134: }
135:
136: // Default to english
137: private static Locale currentLocale = Locale.ENGLISH;
138:
139: public static void setCurrentLocale(String language) {
140: setCurrentLocale(language, null);
141: }
142:
143: public static void setCurrentLocale(String language, String country) {
144: if (language != null && !language.equals("")) {
145: if (country != null && !country.equals("")) {
146: setCurrentLocale(new java.util.Locale(language, country));
147: } else {
148: setCurrentLocale(new java.util.Locale(language));
149: }
150: } else {
151: setCurrentLocale(java.util.Locale.getDefault());
152: }
153:
154: }
155:
156: public static void setCurrentLocale(Locale locale) {
157: currentLocale = locale;
158: oLanguage = null;
159:
160: Enumeration enum_listeners = languageChangedListeners
161: .elements();
162: while (enum_listeners.hasMoreElements()) {
163: try {
164: ((LanguageChangedListener) (enum_listeners
165: .nextElement()))
166: .languageChanged(new LanguageChangedEvent(
167: locale));
168: } catch (Exception ex) {
169: }
170: }
171: }
172:
173: public static Locale getCurrentLocale() {
174: return currentLocale;
175: }
176:
177: /**
178: * Retreive a resource string using the current locale.
179: * @param cID The resouce sting identifier
180: * @return The locale specific string
181: */
182: public static String getString(String cID) {
183: return getString(cID, currentLocale);
184: }
185:
186: public static String getString(String cID, String defaultValue) {
187: return getString(cID, currentLocale, defaultValue);
188: }
189:
190: /**
191: * Retreive a resource string using the current locale.
192: * @param cID The resouce sting identifier
193: * @return The locale specific string
194: */
195: public static String getFormattedString(String cID,
196: String defaultValue, Object[] args) {
197: String pattern = getString(cID, getCurrentLocale(),
198: defaultValue);
199: java.text.MessageFormat mf = new java.text.MessageFormat(
200: pattern, I18n.getCurrentLocale());
201: return mf.format(args);
202: }
203:
204: private static String getString(String cID, Locale currentLocale) {
205: if (currentLocale == null) {
206: currentLocale = Locale.getDefault();
207: }
208: if (oLanguage == null) {
209: oLanguage = java.util.ResourceBundle.getBundle(
210: getLocalPackageName() + getBaseName(),
211: currentLocale);
212: }
213:
214: try {
215: return oLanguage.getString(cID);
216: } catch (Exception ex) {
217: return cID;
218: }
219: }
220:
221: public static String getString(String cID, Locale currentLocale,
222: String defaultValue) {
223: try {
224: if (oLanguage == null) {
225: oLanguage = java.util.ResourceBundle.getBundle(
226: getLocalPackageName() + getBaseName(),
227: currentLocale);
228: }
229: return oLanguage.getString(cID);
230: } catch (MissingResourceException ex) {
231: System.out.println("Can't find the translation for key = "
232: + cID + ": using default (" + defaultValue + ")");
233: } catch (Exception ex) {
234: System.out.println("Exception loading cID = " + cID + ": "
235: + ex.getMessage());
236: }
237: return defaultValue;
238: }
239:
240: /**
241: * Enumerates the resouces in a give package name.
242: * This works even if the resources are loaded from a jar file!
243: *
244: * Adapted from code by mikewse
245: * on the java.sun.com message boards.
246: * http://forum.java.sun.com/thread.jsp?forum=22&thread=30984
247: *
248: * @param packageName The package to enumerate
249: * @return A Set of Strings for each resouce in the package.
250: */
251: public static Set getResoucesInPackage(String packageName)
252: throws IOException {
253: String localPackageName;
254: if (packageName.endsWith("/")) {
255: localPackageName = packageName;
256: } else {
257: localPackageName = packageName + '/';
258: }
259:
260: ClassLoader cl = I18n.class.getClassLoader();
261:
262: Enumeration dirEnum = cl.getResources(localPackageName);
263:
264: Set names = new HashSet();
265:
266: // System.out.println("names in " + localPackageName + " " + names);
267:
268: // Loop CLASSPATH directories
269: while (dirEnum.hasMoreElements()) {
270: URL resUrl = (URL) dirEnum.nextElement();
271:
272: // Pointing to filesystem directory
273: if (resUrl.getProtocol().equals("file")) {
274: try {
275: File dir = new File(resUrl.getFile());
276: File[] files = dir.listFiles();
277: if (files != null) {
278: for (int i = 0; i < files.length; i++) {
279: File file = files[i];
280: if (file.isDirectory())
281: continue;
282: names
283: .add(localPackageName
284: + file.getName());
285: }
286: }
287: } catch (Exception ex) {
288: ex.printStackTrace();
289: }
290:
291: // Pointing to Jar file
292: } else if (resUrl.getProtocol().equals("jar")) {
293: JarURLConnection jconn = (JarURLConnection) resUrl
294: .openConnection();
295: JarFile jfile = jconn.getJarFile();
296: Enumeration entryEnum = jfile.entries();
297: while (entryEnum.hasMoreElements()) {
298: JarEntry entry = (JarEntry) entryEnum.nextElement();
299: String entryName = entry.getName();
300: // Exclude our own directory
301: if (entryName.equals(localPackageName))
302: continue;
303: String parentDirName = entryName.substring(0,
304: entryName.lastIndexOf('/') + 1);
305: if (!parentDirName.equals(localPackageName))
306: continue;
307: names.add(entryName);
308: }
309: } else {
310: // Invalid classpath entry
311: }
312: }
313:
314: return names;
315: }
316:
317: public static String getLocalPackageName() {
318: return localPackageName;
319: }
320:
321: public static void setLocalPackageName(String aLocalPackageName) {
322: localPackageName = aLocalPackageName;
323: }
324:
325: public static String getBaseName() {
326: return baseName;
327: }
328:
329: public static void setBaseName(String aBaseName) {
330: baseName = aBaseName;
331: }
332: }
|