Changeset 2754 in josm


Ignore:
Timestamp:
Jan 7, 2010 12:06:22 PM (3 years ago)
Author:
stoecker
Message:

fixed translation problems, i18n update

Location:
trunk
Files:
28 added
2 deleted
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/build.xml

    r2748 r2754  
    9898                        <zipfileset dir="images" prefix="images" /> 
    9999                        <zipfileset dir="data" prefix="data" /> 
    100                         <zipfileset src="lib/josm-translation.jar" /> 
    101100 
    102101                        <!-- All jar files necessary to run only JOSM (no tests) --> 
    103                         <zipfileset src="lib/gettext-commons-0.9.6.jar" /> 
    104102                        <zipfileset src="lib/metadata-extractor-2.3.1-nosun.jar" /> 
    105103                        <zipfileset src="lib/commons-codec-1.4.jar" /> 
  • trunk/src/org/openstreetmap/josm/gui/preferences/LanguagePreference.java

    r2745 r2754  
    55 
    66import java.awt.Component; 
    7 import java.io.IOException; 
    8 import java.lang.reflect.InvocationTargetException; 
    97import java.util.ArrayList; 
    108import java.util.Arrays; 
    119import java.util.List; 
    1210import java.util.Locale; 
    13 import java.util.logging.Logger; 
    1411 
    1512import javax.swing.Box; 
     
    2118import javax.swing.JPanel; 
    2219import javax.swing.ListCellRenderer; 
    23 import javax.swing.SwingUtilities; 
    24 import javax.swing.event.ChangeEvent; 
    25 import javax.swing.event.ChangeListener; 
    2620 
    2721import org.openstreetmap.josm.Main; 
    28 import org.openstreetmap.josm.gui.PleaseWaitRunnable; 
    29 import org.openstreetmap.josm.io.OsmTransferException; 
    3022import org.openstreetmap.josm.tools.GBC; 
    3123import org.openstreetmap.josm.tools.I18n; 
    32 import org.xml.sax.SAXException; 
    3324 
    3425public class LanguagePreference implements PreferenceSetting { 
    35     static private final Logger logger = Logger.getLogger(LanguagePreference.class.getName()); 
    36  
    3726    public static class Factory implements PreferenceSettingFactory { 
    3827        public PreferenceSetting createPreferenceSetting() { 
     
    5241        langCombo = new JComboBox(model); 
    5342        langCombo.setRenderer(new LanguageCellRenderer(langCombo.getRenderer())); 
     43        model.selectLanguage(Main.pref.get("language")); 
    5444 
    5545        LafPreference lafPreference = gui.getSetting(LafPreference.class); 
     
    5949        panel.add(langCombo, GBC.eol().fill(GBC.HORIZONTAL)); 
    6050        panel.add(Box.createVerticalGlue(), GBC.eol().fill(GBC.BOTH)); 
    61  
    62         // this defers loading of available translations to the first time the tab 
    63         // with the available translations is selected by the user 
    64         // 
    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         ); 
    7651    } 
    7752 
     
    8762    } 
    8863 
    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 translations 
    101      * 
    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         @Override 
    117         protected void cancel() { 
    118             // can't cancel 
    119         } 
    120  
    121         @Override 
    122         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         @Override 
    143         protected void finish() {} 
    144     } 
    145  
    14664    private static class LanguageComboBoxModel extends DefaultComboBoxModel { 
    14765        private final List<Locale> data = new ArrayList<Locale>(); 
    14866 
    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())); 
    15870        } 
    15971 
  • trunk/src/org/openstreetmap/josm/tools/I18n.java

    r2536 r2754  
    22package org.openstreetmap.josm.tools; 
    33 
     4import java.io.BufferedInputStream; 
     5import java.io.InputStream; 
     6import java.net.URL; 
    47import java.text.MessageFormat; 
    58import java.util.Arrays; 
    69import java.util.Comparator; 
     10import java.util.HashMap; 
    711import java.util.LinkedList; 
    812import java.util.Locale; 
    913import java.util.MissingResourceException; 
    1014import java.util.Vector; 
    11 import java.util.logging.Logger; 
    12  
    13 import org.openstreetmap.josm.gui.MainApplication; 
     15 
     16import org.openstreetmap.josm.Main; 
    1417import org.openstreetmap.josm.gui.progress.ProgressMonitor; 
    15 import org.xnap.commons.i18n.I18nFactory; 
    1618 
    1719/** 
     
    2123 */ 
    2224public 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>(); 
    2731 
    2832    /** 
     
    3034     * many strings are already loaded. 
    3135     */ 
    32     public static org.xnap.commons.i18n.I18n i18n; 
    33  
    3436    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); 
    3838    } 
    3939 
    4040    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); 
    4442    } 
    4543 
    4644    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); 
    5046    } 
    5147 
     
    6056 
    6157    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); 
    6559    } 
    6660 
    6761    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); 
    7163    } 
    7264 
    7365    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); 
    7767    } 
    7868 
    7969    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) 
    8674    { 
    8775        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        } 
    9087        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; 
    91107    } 
    92108 
     
    95111     * @return an array of locale objects. 
    96112     */ 
    97     public static final Locale[] getAvailableTranslations(ProgressMonitor monitor) { 
    98         monitor.indeterminateSubTask(tr("Loading available locales...")); 
     113    public static final Locale[] getAvailableTranslations() { 
    99114        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()]; 
    128125        l = v.toArray(l); 
    129126        Arrays.sort(l, new Comparator<Locale>() { 
     
    137134    public static void init() 
    138135    { 
     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 
    139164        /* 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; 
    142312    } 
    143313 
     
    154324        if (localeName != null) { 
    155325            Locale l; 
    156             Locale d = Locale.getDefault(); 
    157326            if (localeName.equals("he")) { 
    158327                localeName = "iw_IL"; 
     
    164333                l = new Locale(localeName); 
    165334            } 
    166             try { 
     335            if(load(localeName)) { 
    167336                Locale.setDefault(l); 
    168                 i18n = I18nFactory.getI18n(MainApplication.class); 
    169             } catch (MissingResourceException ex) { 
     337            } else { 
    170338                if (!l.getLanguage().equals("en")) { 
    171339                    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())); 
    174341                } else { 
    175                     i18n = null; 
     342                    strings = null; 
     343                    pstrings = null; 
    176344                } 
    177345            } 
    178346        } 
    179347    } 
     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    } 
    180380} 
Note: See TracChangeset for help on using the changeset viewer.