/******************************************************************************* * This file is part of logisim-evolution. * * logisim-evolution is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * logisim-evolution is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with logisim-evolution. If not, see <http://www.gnu.org/licenses/>. * * Original code by Carl Burch (http://www.cburch.com), 2011. * Subsequent modifications by : * + Haute École Spécialisée Bernoise * http://www.bfh.ch * + Haute École du paysage, d'ingénierie et d'architecture de Genève * http://hepia.hesge.ch/ * + Haute École d'Ingénierie et de Gestion du Canton de Vaud * http://www.heig-vd.ch/ * The project is currently maintained by : * + REDS Institute - HEIG-VD * Yverdon-les-Bains, Switzerland * http://reds.heig-vd.ch *******************************************************************************/ package com.cburch.logisim.util; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.HashMap; import java.util.Locale; import java.util.MissingResourceException; import java.util.ResourceBundle; import java.util.StringTokenizer; import javax.swing.JComponent; import javax.swing.JScrollPane; public class LocaleManager { private static class LocaleGetter implements StringGetter { private LocaleManager source; private String key; LocaleGetter(LocaleManager source, String key) { this.source = source; this.key = key; } public String toString() { return source.get(key); } /* * @Override public String toString() { return get(); } */ } public static void addLocaleListener(LocaleListener l) { listeners.add(l); } public static boolean canReplaceAccents() { return fetchReplaceAccents() != null; } private static HashMap<Character, String> fetchReplaceAccents() { HashMap<Character, String> ret = null; String val; try { val = Strings.source.locale.getString("accentReplacements"); } catch (MissingResourceException e) { return null; } StringTokenizer toks = new StringTokenizer(val, "/"); while (toks.hasMoreTokens()) { String tok = toks.nextToken().trim(); char c = '\0'; String s = null; if (tok.length() == 1) { c = tok.charAt(0); s = ""; } else if (tok.length() >= 2 && tok.charAt(1) == ' ') { c = tok.charAt(0); s = tok.substring(2).trim(); } if (s != null) { if (ret == null) ret = new HashMap<Character, String>(); ret.put(new Character(c), s); } } return ret; } private static void fireLocaleChanged() { for (LocaleListener l : listeners) { l.localeChanged(); } } public static Locale getLocale() { if (curLocale == null) { curLocale = Locale.getDefault(); } return curLocale; } public static void removeLocaleListener(LocaleListener l) { listeners.remove(l); } private static String replaceAccents(String src, HashMap<Character, String> repl) { // find first non-standard character - so we can avoid the // replacement process if possible int i = 0; int n = src.length(); for (; i < n; i++) { char ci = src.charAt(i); if (ci < 32 || ci >= 127) break; } if (i == n) return src; // ok, we'll have to consider replacing accents char[] cs = src.toCharArray(); StringBuilder ret = new StringBuilder(src.substring(0, i)); for (int j = i; j < cs.length; j++) { char cj = cs[j]; if (cj < 32 || cj >= 127) { String out = repl.get(Character.valueOf(cj)); if (out != null) { ret.append(out); } else { ret.append(cj); } } else { ret.append(cj); } } return ret.toString(); } public static void setLocale(Locale loc) { Locale cur = getLocale(); if (!loc.equals(cur)) { Locale[] opts = Strings.getLocaleManager().getLocaleOptions(); Locale select = null; Locale backup = null; String locLang = loc.getLanguage(); for (Locale opt : opts) { if (select == null && opt.equals(loc)) { select = opt; } if (backup == null && opt.getLanguage().equals(locLang)) { backup = opt; } } if (select == null) { if (backup == null) { select = new Locale("en"); } else { select = backup; } } curLocale = select; Locale.setDefault(select); for (LocaleManager man : managers) { man.loadDefault(); } repl = replaceAccents ? fetchReplaceAccents() : null; fireLocaleChanged(); } } public static void setReplaceAccents(boolean value) { HashMap<Character, String> newRepl = value ? fetchReplaceAccents() : null; replaceAccents = value; repl = newRepl; fireLocaleChanged(); } // static members private static final String SETTINGS_NAME = "settings"; private static ArrayList<LocaleManager> managers = new ArrayList<LocaleManager>(); private static String DATE_FORMAT = Strings.get("dateFormat"); public final static SimpleDateFormat parserSDF = new SimpleDateFormat( LocaleManager.DATE_FORMAT); private static ArrayList<LocaleListener> listeners = new ArrayList<LocaleListener>(); private static boolean replaceAccents = false; private static HashMap<Character, String> repl = null; private static Locale curLocale = null; // instance members private String dir_name; private String file_start; private ResourceBundle settings = null; private ResourceBundle locale = null; private ResourceBundle dflt_locale = null; public LocaleManager(String dir_name, String file_start) { this.dir_name = dir_name; this.file_start = file_start; loadDefault(); managers.add(this); } public JComponent createLocaleSelector() { Locale[] locales = getLocaleOptions(); if (locales == null || locales.length == 0) { Locale cur = getLocale(); if (cur == null) cur = new Locale("en"); locales = new Locale[] { cur }; } return new JScrollPane(new LocaleSelector(locales)); } public String get(String key) { String ret; try { ret = locale.getString(key); } catch (MissingResourceException e) { ResourceBundle backup = dflt_locale; if (backup == null) { Locale backup_loc = Locale.US; backup = ResourceBundle.getBundle(dir_name + "/en/" + file_start, backup_loc); dflt_locale = backup; } try { ret = backup.getString(key); } catch (MissingResourceException e2) { ret = key; } } HashMap<Character, String> repl = LocaleManager.repl; if (repl != null) ret = replaceAccents(ret, repl); return ret; } public Locale[] getLocaleOptions() { String locs = null; try { if (settings != null) locs = settings.getString("locales"); } catch (java.util.MissingResourceException e) { } if (locs == null) return new Locale[] {}; ArrayList<Locale> retl = new ArrayList<Locale>(); StringTokenizer toks = new StringTokenizer(locs); while (toks.hasMoreTokens()) { String f = toks.nextToken(); String language; String country; if (f.length() >= 2) { language = f.substring(0, 2); country = (f.length() >= 5 ? f.substring(3, 5) : null); } else { language = null; country = null; } if (language != null) { Locale loc = country == null ? new Locale(language) : new Locale(language, country); retl.add(loc); } } return retl.toArray(new Locale[retl.size()]); } public StringGetter getter(String key) { return new LocaleGetter(this, key); } public StringGetter getter(String key, String arg) { return StringUtil.formatter(getter(key), arg); } public StringGetter getter(String key, StringGetter arg) { return StringUtil.formatter(getter(key), arg); } private void loadDefault() { if (settings == null) { try { settings = ResourceBundle.getBundle(dir_name + "/" + SETTINGS_NAME); } catch (java.util.MissingResourceException e) { } } try { loadLocale(Locale.getDefault()); if (locale != null) return; } catch (java.util.MissingResourceException e) { } try { loadLocale(Locale.ENGLISH); if (locale != null) return; } catch (java.util.MissingResourceException e) { } Locale[] choices = getLocaleOptions(); if (choices != null && choices.length > 0) loadLocale(choices[0]); if (locale != null) return; throw new RuntimeException("No locale bundles are available"); } private void loadLocale(Locale loc) { String bundleName = dir_name + "/" + loc.getLanguage() + "/" + file_start; locale = ResourceBundle.getBundle(bundleName, loc); } }