- Timestamp:
- 2010-01-07T12:06:22+01:00 (15 years ago)
- Location:
- trunk
- Files:
-
- 28 added
- 2 deleted
- 3 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/build.xml
r2748 r2754 98 98 <zipfileset dir="images" prefix="images" /> 99 99 <zipfileset dir="data" prefix="data" /> 100 <zipfileset src="lib/josm-translation.jar" />101 100 102 101 <!-- All jar files necessary to run only JOSM (no tests) --> 103 <zipfileset src="lib/gettext-commons-0.9.6.jar" />104 102 <zipfileset src="lib/metadata-extractor-2.3.1-nosun.jar" /> 105 103 <zipfileset src="lib/commons-codec-1.4.jar" /> -
trunk/src/org/openstreetmap/josm/gui/preferences/LanguagePreference.java
r2745 r2754 5 5 6 6 import java.awt.Component; 7 import java.io.IOException;8 import java.lang.reflect.InvocationTargetException;9 7 import java.util.ArrayList; 10 8 import java.util.Arrays; 11 9 import java.util.List; 12 10 import java.util.Locale; 13 import java.util.logging.Logger;14 11 15 12 import javax.swing.Box; … … 21 18 import javax.swing.JPanel; 22 19 import javax.swing.ListCellRenderer; 23 import javax.swing.SwingUtilities;24 import javax.swing.event.ChangeEvent;25 import javax.swing.event.ChangeListener;26 20 27 21 import org.openstreetmap.josm.Main; 28 import org.openstreetmap.josm.gui.PleaseWaitRunnable;29 import org.openstreetmap.josm.io.OsmTransferException;30 22 import org.openstreetmap.josm.tools.GBC; 31 23 import org.openstreetmap.josm.tools.I18n; 32 import org.xml.sax.SAXException;33 24 34 25 public class LanguagePreference implements PreferenceSetting { 35 static private final Logger logger = Logger.getLogger(LanguagePreference.class.getName());36 37 26 public static class Factory implements PreferenceSettingFactory { 38 27 public PreferenceSetting createPreferenceSetting() { … … 52 41 langCombo = new JComboBox(model); 53 42 langCombo.setRenderer(new LanguageCellRenderer(langCombo.getRenderer())); 43 model.selectLanguage(Main.pref.get("language")); 54 44 55 45 LafPreference lafPreference = gui.getSetting(LafPreference.class); … … 59 49 panel.add(langCombo, GBC.eol().fill(GBC.HORIZONTAL)); 60 50 panel.add(Box.createVerticalGlue(), GBC.eol().fill(GBC.BOTH)); 61 62 // this defers loading of available translations to the first time the tab63 // with the available translations is selected by the user64 //65 gui.displaycontent.addChangeListener(66 new ChangeListener() {67 public void stateChanged(ChangeEvent e) {68 int i = gui.displaycontent.getSelectedIndex();69 String title = gui.displaycontent.getTitleAt(i);70 if (title.equals(tr("Look and Feel"))) {71 initiallyLoadAvailableTranslations();72 }73 }74 }75 );76 51 } 77 52 … … 87 62 } 88 63 89 /**90 * Load available translations if not loaded yet.91 */92 public void initiallyLoadAvailableTranslations() {93 if (!translationsLoaded) {94 reloadAvailableTranslations();95 }96 translationsLoaded = true;97 }98 99 /**100 * Asynchronously loads available translations101 *102 */103 protected void reloadAvailableTranslations() {104 Main.worker.submit(new AvailableTranslationsLoader());105 }106 107 /**108 * Asynchronous task to lookup the available translations.109 *110 */111 private class AvailableTranslationsLoader extends PleaseWaitRunnable {112 public AvailableTranslationsLoader() {113 super(tr("Looking up available translations..."));114 }115 116 @Override117 protected void cancel() {118 // can't cancel119 }120 121 @Override122 protected void realRun() throws SAXException, IOException, OsmTransferException {123 final List<Locale> locales = new ArrayList<Locale>(124 Arrays.asList(I18n.getAvailableTranslations(getProgressMonitor()))125 );126 locales.add(0,Locale.ENGLISH);127 Runnable r = new Runnable() {128 public void run() {129 model.setAvailableLocales(locales);130 model.selectLanguage(Main.pref.get("language"));131 }132 };133 try {134 SwingUtilities.invokeAndWait(r);135 } catch(InvocationTargetException e) {136 throw new RuntimeException(e.getCause());137 } catch(InterruptedException e) {138 throw new RuntimeException(e);139 }140 }141 142 @Override143 protected void finish() {}144 }145 146 64 private static class LanguageComboBoxModel extends DefaultComboBoxModel { 147 65 private final List<Locale> data = new ArrayList<Locale>(); 148 66 149 public LanguageComboBoxModel() {} 150 151 public void setAvailableLocales(List<Locale> locales) { 152 data.clear(); 153 if (locales != null) { 154 data.add(null); // the default locale 155 data.addAll(locales); 156 } 157 fireContentsChanged(this, 0, getSize()); 67 public LanguageComboBoxModel(){ 68 data.add(0,null); 69 data.addAll(Arrays.asList(I18n.getAvailableTranslations())); 158 70 } 159 71 -
trunk/src/org/openstreetmap/josm/tools/I18n.java
r2536 r2754 2 2 package org.openstreetmap.josm.tools; 3 3 4 import java.io.BufferedInputStream; 5 import java.io.InputStream; 6 import java.net.URL; 4 7 import java.text.MessageFormat; 5 8 import java.util.Arrays; 6 9 import java.util.Comparator; 10 import java.util.HashMap; 7 11 import java.util.LinkedList; 8 12 import java.util.Locale; 9 13 import java.util.MissingResourceException; 10 14 import java.util.Vector; 11 import java.util.logging.Logger; 12 13 import org.openstreetmap.josm.gui.MainApplication; 15 16 import org.openstreetmap.josm.Main; 14 17 import org.openstreetmap.josm.gui.progress.ProgressMonitor; 15 import org.xnap.commons.i18n.I18nFactory;16 18 17 19 /** … … 21 23 */ 22 24 public class I18n { 23 static private final Logger logger = Logger.getLogger(I18n.class.getName()); 24 25 /* Base name for translation data. Used for detecting available translations */ 26 private static final String TR_BASE = "org.openstreetmap.josm.i18n.Translation_"; 25 private enum PluralMode { MODE_NOTONE, MODE_NONE, MODE_GREATERONE, 26 MODE_CS, MODE_AR, MODE_PL, MODE_RO, MODE_RU, MODE_SK, MODE_SL} 27 private static PluralMode pluralMode = PluralMode.MODE_NOTONE; /* english default */ 28 private static HashMap<String, String> strings = null; 29 private static HashMap<String, String[]> pstrings = null; 30 private static HashMap<String, PluralMode> languages = new HashMap<String, PluralMode>(); 27 31 28 32 /** … … 30 34 * many strings are already loaded. 31 35 */ 32 public static org.xnap.commons.i18n.I18n i18n;33 34 36 public static final String tr(String text, Object... objects) { 35 if (i18n == null) 36 return MessageFormat.format(filter(text), objects); 37 return filter(i18n.tr(text, objects)); 37 return MessageFormat.format(gettext(text, null), objects); 38 38 } 39 39 40 40 public static final String tr(String text) { 41 if (i18n == null) 42 return filter(text); 43 return filter(i18n.tr(text)); 41 return gettext(text, null); 44 42 } 45 43 46 44 public static final String trc(String ctx, String text) { 47 if (i18n == null) 48 return text; 49 return i18n.trc(ctx, text); 45 return gettext(text, ctx); 50 46 } 51 47 … … 60 56 61 57 public static final String trn(String text, String pluralText, long n, Object... objects) { 62 if (i18n == null) 63 return n == 1 ? tr(text, objects) : tr(pluralText, objects); 64 return filter(i18n.trn(text, pluralText, n, objects)); 58 return MessageFormat.format(gettextn(text, pluralText, null, n), objects); 65 59 } 66 60 67 61 public static final String trn(String text, String pluralText, long n) { 68 if (i18n == null) 69 return n == 1 ? tr(text) : tr(pluralText); 70 return filter(i18n.trn(text, pluralText, n)); 62 return gettextn(text, pluralText, null, n); 71 63 } 72 64 73 65 public static final String trnc(String ctx, String text, String pluralText, long n, Object... objects) { 74 if (i18n == null) 75 return n == 1 ? tr(text, objects) : tr(pluralText, objects); 76 return i18n.trnc(ctx, text, pluralText, n, objects); 66 return MessageFormat.format(gettextn(text, pluralText, ctx, n), objects); 77 67 } 78 68 79 69 public static final String trnc(String ctx, String text, String pluralText, long n) { 80 if (i18n == null) 81 return n == 1 ? tr(text) : tr(pluralText); 82 return i18n.trnc(ctx, text, pluralText, n); 83 } 84 85 public static final String filter(String text) 70 return gettextn(text, pluralText, ctx, n); 71 } 72 73 public static final String gettext(String text, String ctx) 86 74 { 87 75 int i; 88 if(text.startsWith("_:") && (i = text.indexOf("\n")) >= 0) 89 return text.substring(i+1); 76 if(ctx == null && text.startsWith("_:") && (i = text.indexOf("\n")) >= 0) 77 { 78 ctx = text.substring(2,i-1); 79 text = text.substring(i+1); 80 } 81 if(strings != null) 82 { 83 String trans = strings.get(ctx == null ? text : "_:"+ctx+"\n"+text); 84 if(trans != null) 85 return trans; 86 } 90 87 return text; 88 } 89 90 public static final String gettextn(String text, String plural, String ctx, long num) 91 { 92 int i; 93 if(ctx == null && text.startsWith("_:") && (i = text.indexOf("\n")) >= 0) 94 { 95 ctx = text.substring(2,i-1); 96 text = text.substring(i+1); 97 } 98 if(pstrings != null) 99 { 100 i = pluralEval(num); 101 String[] trans = pstrings.get(ctx == null ? text : "_:"+ctx+"\n"+text); 102 if(trans != null && trans.length >= i) 103 return trans[i]; 104 } 105 106 return num == 1 ? text : plural; 91 107 } 92 108 … … 95 111 * @return an array of locale objects. 96 112 */ 97 public static final Locale[] getAvailableTranslations(ProgressMonitor monitor) { 98 monitor.indeterminateSubTask(tr("Loading available locales...")); 113 public static final Locale[] getAvailableTranslations() { 99 114 Vector<Locale> v = new Vector<Locale>(); 100 LinkedList<String>str = new LinkedList<String>(); 101 Locale[] l = Locale.getAvailableLocales(); 102 monitor.subTask(tr("Checking locales...")); 103 monitor.setTicksCount(l.length); 104 for (int i = 0; i < l.length; i++) { 105 monitor.setCustomText(tr("Checking translation for locale ''{0}''", l[i].getDisplayName())); 106 String loc = l[i].toString(); 107 String cn = TR_BASE + loc; 108 try { 109 Class.forName(cn); 110 v.add(l[i]); 111 str.add(loc); 112 } catch (ClassNotFoundException e) { 113 } 114 monitor.worked(1); 115 } 116 /* hmm, don't know why this is necessary */ 117 try { 118 if(!str.contains("nb")) { 119 v.add(new Locale("nb")); 120 } 121 } catch (Exception e) {} 122 try { 123 if(!str.contains("gl")) { 124 v.add(new Locale("gl")); 125 } 126 } catch (Exception e) {} 127 l = new Locale[v.size()]; 115 if(Main.class.getResource("/data/en.lang") != null) 116 { 117 for (String loc : languages.keySet()) { 118 if(Main.class.getResource("/data/"+loc+".lang") != null) { 119 v.add(new Locale(loc)); 120 } 121 } 122 } 123 v.add(Locale.ENGLISH); 124 Locale[] l = new Locale[v.size()]; 128 125 l = v.toArray(l); 129 126 Arrays.sort(l, new Comparator<Locale>() { … … 137 134 public static void init() 138 135 { 136 languages.put("ar", PluralMode.MODE_AR); 137 languages.put("bg", PluralMode.MODE_NOTONE); 138 languages.put("cs", PluralMode.MODE_CS); 139 languages.put("da", PluralMode.MODE_NOTONE); 140 languages.put("de", PluralMode.MODE_NOTONE); 141 languages.put("el", PluralMode.MODE_NOTONE); 142 languages.put("en_GB", PluralMode.MODE_NOTONE); 143 languages.put("es", PluralMode.MODE_NOTONE); 144 languages.put("et", PluralMode.MODE_NOTONE); 145 languages.put("fi", PluralMode.MODE_NOTONE); 146 languages.put("fr", PluralMode.MODE_GREATERONE); 147 languages.put("gl", PluralMode.MODE_NOTONE); 148 languages.put("is", PluralMode.MODE_NOTONE); 149 languages.put("it", PluralMode.MODE_NOTONE); 150 languages.put("iw_IL", PluralMode.MODE_NOTONE); 151 languages.put("ja", PluralMode.MODE_NONE); 152 languages.put("nb", PluralMode.MODE_NOTONE); 153 languages.put("nl", PluralMode.MODE_NOTONE); 154 languages.put("pl", PluralMode.MODE_PL); 155 languages.put("pt_BR", PluralMode.MODE_GREATERONE); 156 languages.put("ro", PluralMode.MODE_RO); 157 languages.put("ru", PluralMode.MODE_RU); 158 languages.put("sk", PluralMode.MODE_SK); 159 languages.put("sl", PluralMode.MODE_SL); 160 languages.put("sv", PluralMode.MODE_NOTONE); 161 languages.put("tr", PluralMode.MODE_NONE); 162 languages.put("zh_TW", PluralMode.MODE_NONE); 163 139 164 /* try initial language settings, may be changed later again */ 140 try { i18n = I18nFactory.getI18n(MainApplication.class); } 141 catch (MissingResourceException ex) { Locale.setDefault(Locale.ENGLISH);} 165 if(!load(Locale.getDefault().toString())) 166 Locale.setDefault(Locale.ENGLISH); 167 } 168 169 public static boolean load(String l) 170 { 171 if(l.equals("en")) 172 { 173 strings = null; 174 pstrings = null; 175 pluralMode = PluralMode.MODE_NOTONE; 176 return true; 177 } 178 URL en = Main.class.getResource("/data/en.lang"); 179 if(en == null) 180 return false; 181 URL tr = Main.class.getResource("/data/"+l+".lang"); 182 if(tr == null) 183 { 184 int i = l.indexOf('_'); 185 if (i > 0) 186 l = l.substring(0, i); 187 tr = Main.class.getResource("/data/"+l+".lang"); 188 if(tr == null) 189 return false; 190 } 191 192 HashMap<String, String> s = new HashMap<String, String>(); 193 HashMap<String, String[]> p = new HashMap<String, String[]>(); 194 /* file format: 195 for all single strings: 196 { 197 unsigned short (2 byte) stringlength 198 string 199 } 200 unsigned short (2 byte) 0xFFFF (marks end of single strings) 201 for all multi strings: 202 { 203 unsigned char (1 byte) stringcount 204 for stringcount 205 unsigned short (2 byte) stringlength 206 string 207 } 208 */ 209 try 210 { 211 InputStream ens = new BufferedInputStream(en.openStream()); 212 InputStream trs = new BufferedInputStream(tr.openStream()); 213 if(ens == null || trs == null) 214 return false; 215 byte[] enlen = new byte[2]; 216 byte[] trlen = new byte[2]; 217 boolean multimode = false; 218 byte[] str = new byte[4096]; 219 for(;;) 220 { 221 if(multimode) 222 { 223 int ennum = ens.read(); 224 int trnum = trs.read(); 225 if((ennum == -1 && trnum != -1) || (ennum != -1 && trnum == -1)) /* files do not match */ 226 return false; 227 if(ennum == -1) /* EOF */ 228 break; 229 String[] enstrings = new String[ennum]; 230 String[] trstrings = new String[trnum]; 231 for(int i = 0; i < ennum; ++i) 232 { 233 int val = ens.read(enlen); 234 if(val != 2) /* file corrupt */ 235 return false; 236 val = (enlen[0] < 0 ? 256+enlen[0]:enlen[0])*256+(enlen[1] < 0 ? 256+enlen[1]:enlen[1]); 237 if(val > str.length) 238 str = new byte[val]; 239 int rval = ens.read(str, 0, val); 240 if(rval != val) /* file corrupt */ 241 return false; 242 enstrings[i] = new String(str, 0, val, "utf-8"); 243 } 244 for(int i = 0; i < trnum; ++i) 245 { 246 int val = trs.read(trlen); 247 if(val != 2) /* file corrupt */ 248 return false; 249 val = (trlen[0] < 0 ? 256+trlen[0]:trlen[0])*256+(trlen[1] < 0 ? 256+trlen[1]:trlen[1]); 250 if(val > str.length) 251 str = new byte[val]; 252 int rval = trs.read(str, 0, val); 253 if(rval != val) /* file corrupt */ 254 return false; 255 trstrings[i] = new String(str, 0, val, "utf-8"); 256 } 257 if(trnum > 0) 258 p.put(enstrings[0], trstrings); 259 } 260 else 261 { 262 int enval = ens.read(enlen); 263 int trval = trs.read(trlen); 264 if(enval != trval) /* files do not match */ 265 return false; 266 if(enval == -1) /* EOF */ 267 break; 268 if(enval != 2) /* files corrupt */ 269 return false; 270 enval = (enlen[0] < 0 ? 256+enlen[0]:enlen[0])*256+(enlen[1] < 0 ? 256+enlen[1]:enlen[1]); 271 trval = (trlen[0] < 0 ? 256+trlen[0]:trlen[0])*256+(trlen[1] < 0 ? 256+trlen[1]:trlen[1]); 272 if(enval == 0xFFFF) 273 { 274 multimode = true; 275 if(trval != 0xFFFF) /* files do not match */ 276 return false; 277 } 278 else 279 { 280 if(enval > str.length) 281 str = new byte[enval]; 282 if(trval > str.length) 283 str = new byte[trval]; 284 int val = ens.read(str, 0, enval); 285 if(val != enval) /* file corrupt */ 286 return false; 287 String enstr = new String(str, 0, enval, "utf-8"); 288 if(trval != 0) 289 { 290 val = trs.read(str, 0, trval); 291 if(val != trval) /* file corrupt */ 292 return false; 293 String trstr = new String(str, 0, trval, "utf-8"); 294 s.put(enstr, trstr); 295 } 296 } 297 } 298 } 299 } 300 catch(Exception e) 301 { 302 return false; 303 } 304 if(!s.isEmpty()) 305 { 306 strings = s; 307 pstrings = p; 308 pluralMode = languages.get(l); 309 return true; 310 } 311 return false; 142 312 } 143 313 … … 154 324 if (localeName != null) { 155 325 Locale l; 156 Locale d = Locale.getDefault();157 326 if (localeName.equals("he")) { 158 327 localeName = "iw_IL"; … … 164 333 l = new Locale(localeName); 165 334 } 166 try{335 if(load(localeName)) { 167 336 Locale.setDefault(l); 168 i18n = I18nFactory.getI18n(MainApplication.class); 169 } catch (MissingResourceException ex) { 337 } else { 170 338 if (!l.getLanguage().equals("en")) { 171 339 System.out.println(tr("Unable to find translation for the locale {0}. Reverting to {1}.", 172 l.getDisplayName(), d.getDisplayName())); 173 Locale.setDefault(d); 340 l.getDisplayName(), Locale.getDefault().getDisplayName())); 174 341 } else { 175 i18n = null; 342 strings = null; 343 pstrings = null; 176 344 } 177 345 } 178 346 } 179 347 } 348 349 private static int pluralEval(long n) 350 { 351 switch(pluralMode) 352 { 353 case MODE_NOTONE: /* bg, da, de, el, en, en_GB, es, et, fi, gl, is, it, iw_IL, nb, nl, sv */ 354 return ((n != 1) ? 1 : 0); 355 case MODE_NONE: /* ja, tr, zh_TW */ 356 return 0; 357 case MODE_GREATERONE: /* fr, pt_BR */ 358 return ((n > 1) ? 1 : 0); 359 case MODE_CS: 360 return ((n == 1) ? 0 : (((n >= 2) && (n <= 4)) ? 1 : 2)); 361 case MODE_AR: 362 return ((n == 0) ? 0 : ((n == 1) ? 1 : ((n == 2) ? 2 : ((((n % 100) >= 3) 363 && ((n % 100) <= 10)) ? 3 : ((((n % 100) >= 11) && ((n % 100) <= 99)) ? 4 : 5))))); 364 case MODE_PL: 365 return ((n == 1) ? 0 : (((((n % 10) >= 2) && ((n % 10) <= 4)) 366 && (((n % 100) < 10) || ((n % 100) >= 20))) ? 1 : 2)); 367 case MODE_RO: 368 return ((n == 1) ? 0 : ((((n % 100) > 19) || (((n % 100) == 0) && (n != 0))) ? 2 : 1)); 369 case MODE_RU: 370 return ((((n % 10) == 1) && ((n % 100) != 11)) ? 0 : (((((n % 10) >= 2) 371 && ((n % 10) <= 4)) && (((n % 100) < 10) || ((n % 100) >= 20))) ? 1 : 2)); 372 case MODE_SK: 373 return ((n == 1) ? 1 : (((n >= 2) && (n <= 4)) ? 2 : 0)); 374 case MODE_SL: 375 return (((n % 100) == 1) ? 1 : (((n % 100) == 2) ? 2 : ((((n % 100) == 3) 376 || ((n % 100) == 4)) ? 3 : 0))); 377 } 378 return 0; 379 } 180 380 }
Note:
See TracChangeset
for help on using the changeset viewer.