Changeset 2754 in josm


Ignore:
Timestamp:
2010-01-07T12:06:22+01:00 (10 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.