Statistics
| Revision:

svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.framework / org.gvsig.andami / src / main / java / org / gvsig / andami / impl / DefaultLocaleManager.java @ 43372

History | View | Annotate | Download (17.3 KB)

1
package org.gvsig.andami.impl;
2

    
3
import java.io.File;
4
import java.net.URL;
5
import java.security.AccessController;
6
import java.security.PrivilegedAction;
7
import java.util.Collections;
8
import java.util.Comparator;
9
import java.util.HashSet;
10
import java.util.Iterator;
11
import java.util.List;
12
import java.util.Locale;
13
import java.util.Set;
14
import java.util.TreeSet;
15

    
16
import javax.swing.JComponent;
17
import javax.swing.SwingUtilities;
18

    
19
import org.apache.commons.configuration.PropertiesConfiguration;
20
import org.apache.commons.lang3.LocaleUtils;
21
import org.apache.commons.lang3.StringUtils;
22
import org.slf4j.Logger;
23
import org.slf4j.LoggerFactory;
24

    
25
import org.gvsig.andami.Launcher;
26
import org.gvsig.andami.LocaleManager;
27
import org.gvsig.andami.PluginServices;
28
import org.gvsig.andami.PluginsLocator;
29
import org.gvsig.andami.PluginsManager;
30
import org.gvsig.andami.config.generate.AndamiConfig;
31
import org.gvsig.andami.installer.translations.TranslationsInstallerFactory;
32
import org.gvsig.andami.ui.mdiFrame.MDIFrame;
33
import org.gvsig.installer.lib.api.InstallerLocator;
34
import org.gvsig.installer.lib.api.InstallerManager;
35
import org.gvsig.utils.XMLEntity;
36

    
37
public class DefaultLocaleManager implements LocaleManager {
38

    
39
    private static final Logger logger
40
            = LoggerFactory.getLogger(DefaultLocaleManager.class);
41

    
42
    private static final String LOCALE_CODE_VALENCIANO = "vl";
43

    
44
    private static final String I18N_EXTENSION = "org.gvsig.i18n.extension";
45
    private static final String INSTALLED_TRANSLATIONS_HOME_FOLDER = "i18n";
46
    private static final String VARIANT = "variant";
47
    private static final String COUNTRY = "country";
48
    private static final String LANGUAGE = "language";
49
    private static final String REGISTERED_LOCALES_PERSISTENCE = "RegisteredLocales";
50

    
51
    private static final String LOCALE_CONFIG_FILENAME = "locale.config";
52

    
53
    private final Locale[] hardcoredLocales = new Locale[]{
54
        // Default supported locales
55
        SPANISH, // Spanish
56
        ENGLISH, // English
57
        new Locale("en", "US"), // English US
58
        new Locale("ca"), // Catalan
59
        new Locale("gl"), // Galician
60
        new Locale("eu"), // Basque
61
        new Locale("de"), // German
62
        new Locale("cs"), // Czech
63
        new Locale("fr"), // French
64
        new Locale("it"), // Italian
65
        new Locale("pl"), // Polish
66
        new Locale("pt"), // Portuguese
67
        new Locale("pt", "BR"), // Portuguese Brazil
68
        new Locale("ro"), // Romanian
69
        new Locale("zh"), // Chinese
70
        new Locale("ru"), // Russian
71
        new Locale("el"), // Greek
72
        new Locale("ro"), // Romanian
73
        new Locale("pl"), // Polish
74
        new Locale("tr"), // Turkish
75
        new Locale("sr"), // Serbio
76
        new Locale("sw") // Swahili
77
    };
78

    
79
    private Set installedLocales = null;
80
    private Set defaultLocales = null;
81

    
82
    private boolean storedInstalledLocales = false;
83

    
84
    public DefaultLocaleManager() {
85
        Locale currentLocale = org.gvsig.i18n.Messages.getCurrentLocale();
86
        this.setCurrentLocale(currentLocale);
87
    }
88

    
89
    public Locale getCurrentLocale() {
90
        return org.gvsig.i18n.Messages.getCurrentLocale();
91
    }
92

    
93
    public void setCurrentLocale(final Locale locale) {
94
        Locale nearestLocale = getNearestLocale(locale);
95
        if(nearestLocale == null){
96
            nearestLocale = this.getLocaleAlternatives(locale)[0];
97
        }
98
        org.gvsig.i18n.Messages.setCurrentLocale(nearestLocale, this.getLocaleAlternatives(nearestLocale));
99

    
100
        String localeStr = nearestLocale.getLanguage();
101
        if (localeStr.equalsIgnoreCase(LOCALE_CODE_VALENCIANO)) {
102
            Locale.setDefault(new Locale("ca"));
103
        } else {
104
            Locale.setDefault(nearestLocale);
105
        }
106

    
107
        AndamiConfig config = Launcher.getAndamiConfig();
108
        config.setLocaleLanguage(nearestLocale.getLanguage());
109
        config.setLocaleCountry(nearestLocale.getCountry());
110
        config.setLocaleVariant(nearestLocale.getVariant());
111

    
112
        setCurrentLocaleUI(nearestLocale);
113
    }
114

    
115
    public Locale getDefaultSystemLocale() {
116
        String language, region, country, variant;
117
        language = getSystemProperty("user.language", "en");
118
        // for compatibility, check for old user.region property
119
        region = getSystemProperty("user.region", null);
120

    
121
        if (region != null) {
122
            // region can be of form country, country_variant, or _variant
123
            int i = region.indexOf('_');
124
            if (i >= 0) {
125
                country = region.substring(0, i);
126
                variant = region.substring(i + 1);
127
            } else {
128
                country = region;
129
                variant = "";
130
            }
131
        } else {
132
            country = getSystemProperty("user.country", "");
133
            variant = getSystemProperty("user.variant", "");
134
        }
135
        return new Locale(language, country, variant);
136
    }
137

    
138
    private Set<Locale> loadLocalesFromConfing(File localesFile)  {
139
        PropertiesConfiguration config = null;
140
        if (!localesFile.canRead()) {
141
            return null;
142
        }
143
        try {
144
            config = new PropertiesConfiguration(localesFile);
145
        } catch (Exception ex) {
146
            logger.warn("Can't open locale configuration '" + localesFile + "'.", ex);
147
            return null;
148
        }
149

    
150
        Set<Locale> locales = new HashSet<Locale>();
151
        List localeCodes = config.getList("locale");
152
        for (Object localeCode : localeCodes) {
153
            try {
154
                Locale locale = LocaleUtils.toLocale((String) localeCode);
155
                locales.add(locale);
156
            } catch(IllegalArgumentException ex) {
157
                logger.warn("Can't load locale '"+localeCode+"' from config '"+localesFile.getAbsolutePath()+"'.",ex);
158
            }
159
        }
160
        return locales;
161
    }
162

    
163
    public Set<Locale> getDefaultLocales() {
164
        if (this.defaultLocales == null) {
165
            PluginsManager pluginsManager = PluginsLocator.getManager();
166
            File localesFile = new File(pluginsManager.getApplicationI18nFolder(), LOCALE_CONFIG_FILENAME);
167

    
168
            Set<Locale> locales = loadLocalesFromConfing(localesFile);
169
            defaultLocales = new HashSet<Locale>();
170
            if( locales == null ) {
171
                for (int i = 0; i < hardcoredLocales.length; i++) {
172
                    defaultLocales.add(hardcoredLocales[i]);
173
                }
174
            } else {
175
                defaultLocales.addAll(locales);
176
            }
177
        }
178
        return this.defaultLocales;
179
    }
180

    
181
    public boolean installLocales(URL localesFile) {
182
        PluginsManager pluginsManager = PluginsLocator.getManager();
183
        PropertiesConfiguration config = null;
184
        try {
185
            config = new PropertiesConfiguration(localesFile);
186
        } catch (Exception ex) {
187
            logger.warn("Can't open configuration '" + localesFile + "'.", ex);
188
        }
189
        if (config == null) {
190
            return false;
191
        }
192
        List localeCodes = config.getList("locale");
193
        for (Object localeCode : localeCodes) {
194
            Locale locale = LocaleUtils.toLocale((String) localeCode);
195
            if (!getInstalledLocales().contains(locale)) {
196
                this.installedLocales.add(locale);
197
            }
198
        }
199
        storeInstalledLocales();
200
        return true;
201
    }
202

    
203
    public Set<Locale> getInstalledLocales() {
204
        if (installedLocales == null) {
205
            installedLocales = new TreeSet<Locale>(new Comparator<Locale>() {
206
                public int compare(Locale t0, Locale t1) {
207
                    if (t1 == null || t0 == null) {
208
                        return 0;
209
                    }
210
                    // return getLanguageDisplayName(t0).compareToIgnoreCase(getLanguageDisplayName(t1));
211
                    return t0.toString().compareToIgnoreCase(t1.toString());
212
                }
213
            });
214

    
215
            XMLEntity child = getRegisteredLocalesPersistence();
216

    
217
            // If the list of registered locales is not already persisted,
218
            // this should be the first time gvSIG is run with the I18nPlugin
219
            // so we will take the list of default locales
220
            if (child == null) {
221
                installedLocales.addAll(getDefaultLocales());
222
            } else {
223
                XMLEntity localesEntity = child;
224
                for (int i = 0; i < localesEntity.getChildrenCount(); i++) {
225
                    Locale locale = null;
226
                    XMLEntity localeEntity = localesEntity.getChild(i);
227
                    String language = localeEntity.getStringProperty(LANGUAGE);
228
                    String country = localeEntity.getStringProperty(COUNTRY);
229
                    String variant = localeEntity.getStringProperty(VARIANT);
230
                    locale = new Locale(language, country, variant);
231
                    installedLocales.add(locale);
232
                }
233
            }
234
            Set<Locale> lfp = getAllLocalesFromPackages();
235
            installedLocales.addAll(lfp);
236
        }
237
        storeInstalledLocales();
238
        return Collections.unmodifiableSet(installedLocales);
239
    }
240

    
241
    public void updateInstalledLocales(){
242
        installedLocales.addAll(getAllLocalesFromPackages());
243
        storedInstalledLocales = false;
244
        storeInstalledLocales();
245
    }
246

    
247
    public boolean installLocale(Locale locale) {
248
        // Add the locale to the list of installed ones, if it
249
        // is new, otherwise, update the texts.
250
        if (!getInstalledLocales().contains(locale)) {
251
            getInstalledLocales().add(locale);
252
            storeInstalledLocales();
253
        }
254
        return true;
255
    }
256

    
257
    public boolean uninstallLocale(Locale locale) {
258
        if (!getInstalledLocales().remove(locale)) {
259
            return false;
260
        }
261
        storeInstalledLocales();
262
        return true;
263
    }
264

    
265
    public String getLanguageDisplayName(Locale locale) {
266

    
267
        String displayName;
268

    
269
        if ("eu".equals(locale.getLanguage())
270
                && "vascuence".equals(locale.getDisplayLanguage())) {
271
            // Correction for the Basque language display name,
272
            // show it in Basque, not in Spanish
273
            displayName = "Euskera";
274
        } else if (LOCALE_CODE_VALENCIANO.equals(locale.getLanguage())) {
275
            // Patch for Valencian/Catalan
276
            displayName = "Valenci?";
277
        } else {
278
            displayName = locale.getDisplayLanguage(locale);
279
        }
280

    
281
        return StringUtils.capitalize(displayName);
282
    }
283

    
284
    public String getLocaleDisplayName(Locale locale) {
285
        String displayName = this.getLanguageDisplayName(locale);
286

    
287
        if( !StringUtils.isBlank(locale.getCountry()) ) {
288
            if( !StringUtils.isBlank(locale.getVariant()) ) {
289
                displayName = displayName + " (" +
290
                        StringUtils.capitalize(locale.getDisplayCountry(locale)) + "/" +
291
                        locale.getDisplayVariant(locale) + ")";
292
            } else {
293
                displayName = displayName + " ("+locale.getDisplayCountry(locale)+")";
294
            }
295
        }
296

    
297
        return displayName;
298
    }
299

    
300
    public Locale[] getLocaleAlternatives(Locale locale) {
301
        Locale alternatives[] = null;
302

    
303
        String localeStr = locale.getLanguage();
304
        if (localeStr.equals("es")
305
                || localeStr.equals("ca")
306
                || localeStr.equals("gl")
307
                || localeStr.equals("eu")
308
                || localeStr.equals(LOCALE_CODE_VALENCIANO)) {
309
            alternatives = new Locale[2];
310
            alternatives[0] = new Locale("es");
311
            alternatives[1] = new Locale("en");
312
        } else {
313
            // prefer English for the rest
314
            alternatives = new Locale[2];
315
            alternatives[0] = new Locale("en");
316
            alternatives[1] = new Locale("es");
317
        }
318
        return alternatives;
319
    }
320

    
321
    private void setCurrentLocaleUI(final Locale locale) {
322
        if (!SwingUtilities.isEventDispatchThread()) {
323
            try {
324
                SwingUtilities.invokeAndWait(new Runnable() {
325
                    public void run() {
326
                        setCurrentLocaleUI(locale);
327
                    }
328
                });
329
            } catch (Exception ex) {
330
                // Ignore
331
            }
332
        }
333
        try {
334
            JComponent.setDefaultLocale(locale);
335
        } catch (Exception ex) {
336
            logger.warn("Problems setting locale to JComponent.", ex);
337
        }
338
        if (MDIFrame.isInitialized()) {
339
            try {
340
                MDIFrame.getInstance().setLocale(locale);
341
            } catch (Exception ex) {
342
                logger.warn("Problems settings locale to MDIFrame.", ex);
343
            }
344
        }
345
    }
346

    
347
    public File getResourcesFolder() {
348
        File i18nFolder = new File(
349
                PluginsLocator.getManager().getApplicationHomeFolder(),
350
                INSTALLED_TRANSLATIONS_HOME_FOLDER
351
        );
352
        if (!i18nFolder.exists()) {
353
            i18nFolder.mkdirs();
354
        }
355
        return i18nFolder;
356
    }
357

    
358
    /**
359
     * Returns the child XMLEntity with the RegisteredLocales.
360
     */
361
    private XMLEntity getRegisteredLocalesPersistence() {
362
        XMLEntity entity = getI18nPersistence();
363
        if (entity == null) {
364
            return null;
365
        }
366
        XMLEntity child = null;
367
        for (int i = entity.getChildrenCount() - 1; i >= 0; i--) {
368
            XMLEntity tmpchild = entity.getChild(i);
369
            if (tmpchild.getName().equals(REGISTERED_LOCALES_PERSISTENCE)) {
370
                child = tmpchild;
371
                break;
372
            }
373
        }
374
        return child;
375
    }
376

    
377
    /**
378
     * Stores the list of installed locales into the plugin persistence.
379
     */
380
    private void storeInstalledLocales() {
381
        if(this.storedInstalledLocales ){
382
            return;
383
        }
384
        XMLEntity i18nPersistence = getI18nPersistence();
385
        if(i18nPersistence == null){
386
            return;
387
        }
388
        XMLEntity localesEntity = getRegisteredLocalesPersistence();
389

    
390
        // Remove the previous list of registered languages
391
        if (localesEntity != null) {
392
            for (int i = i18nPersistence.getChildrenCount() - 1; i >= 0; i--) {
393
                XMLEntity child = i18nPersistence.getChild(i);
394
                if (child.getName().equals(REGISTERED_LOCALES_PERSISTENCE)) {
395
                    i18nPersistence.removeChild(i);
396
                    break;
397
                }
398
            }
399
        }
400

    
401
        // Create the new persistence for the registered languages
402
        localesEntity = new XMLEntity();
403

    
404
        localesEntity.setName(REGISTERED_LOCALES_PERSISTENCE);
405

    
406
        Set<Locale> locales = this.installedLocales; //getInstalledLocales();
407
        for (Iterator iterator = locales.iterator(); iterator.hasNext();) {
408
            Locale locale = (Locale) iterator.next();
409
            XMLEntity localeEntity = new XMLEntity();
410
            localeEntity.setName(locale.getDisplayName());
411
            localeEntity.putProperty(LANGUAGE, locale.getLanguage());
412
            localeEntity.putProperty(COUNTRY, locale.getCountry());
413
            localeEntity.putProperty(VARIANT, locale.getVariant());
414

    
415
            localesEntity.addChild(localeEntity);
416
        }
417

    
418
        getI18nPersistence().addChild(localesEntity);
419
        this.storedInstalledLocales = true;
420
    }
421

    
422
    /**
423
     * Returns the I18n Plugin persistence.
424
     */
425
    private XMLEntity getI18nPersistence() {
426
        try {
427
            XMLEntity entity = PluginServices.getPluginServices(I18N_EXTENSION).getPersistentXML();
428
            return entity;
429
        } catch (Throwable t) {
430
            // logger.warn("Can't get I18nPersistence",t);
431
            return null;
432
        }
433
    }
434

    
435
    @SuppressWarnings("unchecked")
436
    private String getSystemProperty(final String property, String defaultValue) {
437
        String value
438
                = (String) AccessController.doPrivileged(new PrivilegedAction() {
439
                    public Object run() {
440
                        return System.getProperty(property);
441
                    }
442
                });
443
        return value == null ? defaultValue : value;
444
    }
445

    
446
    private Set<Locale> getAllLocalesFromPackages() {
447
        Set<Locale> locales = new HashSet<Locale>();
448
        InstallerManager installerManager = InstallerLocator.getInstallerManager();
449
        List<File> folders = installerManager.getAddonFolders(TranslationsInstallerFactory.PROVIDER_NAME);
450
        for( File folder : folders ) {
451
            File file = new File(folder,LOCALE_CONFIG_FILENAME);
452
            Set<Locale> l = this.loadLocalesFromConfing(file);
453
            locales.addAll(l);
454
        }
455
        return locales;
456
    }
457

    
458
    public Locale getNearestLocale(Locale locale) {
459
        String language = locale.getLanguage();
460
        String country = locale.getCountry();
461
        String variant = locale.getVariant();
462
        Locale nearestLocale;
463
        if (language != null && !language.isEmpty()) {
464
            if (country != null && !country.isEmpty()) {
465
                if(variant != null && !variant.isEmpty()){
466
                    nearestLocale = new Locale(language, country, variant);
467
                    if (getInstalledLocales().contains(nearestLocale)) {
468
                        return nearestLocale;
469
                    }
470
                }
471
                nearestLocale = new Locale(language, country);
472
                if (getInstalledLocales().contains(nearestLocale)) {
473
                    return nearestLocale;
474
                }
475
            }
476
            nearestLocale = new Locale(language);
477
            if (getInstalledLocales().contains(nearestLocale)) {
478
                return nearestLocale;
479
            }
480
        }
481
        return null;
482
    }
483
}