Statistics
| Revision:

svn-gvsig-desktop / trunk / libraries / libInternationalization / src / org / gvsig / i18n / Messages.java @ 12863

History | View | Annotate | Download (24 KB)

1 4780 cesar
/* gvSIG. Sistema de Informaci?n Geogr?fica de la Generalitat Valenciana
2
*
3
* Copyright (C) 2006 IVER T.I. and Generalitat Valenciana.
4
*
5
* This program is free software; you can redistribute it and/or
6
* modify it under the terms of the GNU General Public License
7
* as published by the Free Software Foundation; either version 2
8
* of the License, or (at your option) any later version.
9
*
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
* GNU General Public License for more details.
14
*
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307,USA.
18
*
19
* For more information, contact:
20
*
21
*  Generalitat Valenciana
22
*   Conselleria d'Infraestructures i Transport
23
*   Av. Blasco Ib??ez, 50
24
*   46010 VALENCIA
25
*   SPAIN
26
*
27
*      +34 963862235
28
*   gvsig@gva.es
29
*      www.gvsig.gva.es
30
*
31
*    or
32
*
33
*   IVER T.I. S.A
34
*   Salamanca 50
35
*   46005 Valencia
36
*   Spain
37
*
38
*   +34 963163400
39
*   dac@iver.es
40
*/
41
42 4460 cesar
package org.gvsig.i18n;
43
44 5767 cesar
import java.io.File;
45 4587 cesar
import java.net.MalformedURLException;
46
import java.net.URL;
47 5767 cesar
import java.util.ArrayList;
48
import java.util.Enumeration;
49
import java.util.HashMap;
50 8010 cesar
import java.util.Iterator;
51 5767 cesar
import java.util.Locale;
52
import java.util.MissingResourceException;
53
import java.util.ResourceBundle;
54 4587 cesar
55 4460 cesar
import org.apache.log4j.Logger;
56
57
/**
58 4728 cesar
 * <p>This class offers some methods to provide internationalization services
59
 * to other projects. All the methods are static.</p>
60
 *
61
 * <p>The most useful method is {@link #getText(String) getText(key)} (and family),
62
 * which returns the translation associated
63
 * with the provided key. The class must be initialized before getText can be
64
 * used.</p>
65
 *
66
 * <p>The typical usage sequence would be:</p>
67
 * <ul>
68
 * <li>Add some locale to the prefered locales list: <code>Messages.addLocale(new Locale("es"))</code></li>
69
 * <li>Add some resource file containing translations: <code>Messages.addResourceFamily("text", new File("."))</code></li>
70
 * <li>And finaly getText can be used: <code>Messages.getText("aceptar")</code></li>
71
 * </ul>
72
 *
73
 * <p>The resource files are Java properties files, which contain <code>key=translation</code>
74
 * pairs, one
75
 * pair per line. These files must be encoded using iso-8859-1 encoding, and unicode escaped
76
 * sequences must be used to include characters outside the former encoding.
77
 * There are several ways to specify the property file to load, see the different
78
 * addResourceFamily methods for details.</p>
79
 *
80 6294 cesar
 * @author Cesar Martinez Izquierdo (cesar.martinez@iver.es)
81 4460 cesar
 *
82
 */
83
public class Messages {
84
    private static Logger logger = Logger.getLogger("Messages");
85 4516 cesar
    private static String _CLASSNAME = "org.gvsig.i18n.Messages";
86 5599 cesar
    private static int _INITIALSIZE = 3700; // I try to set an initial capacity similar to the amount of strings in gvSIG
87 4460 cesar
88 5767 cesar
    /* Each entry will contain a hashmap with translations. Each hasmap
89
     * contains the translations for one language, indexed by the
90
     * translation key. The translations for language (i) in the preferred locales
91
     * list are contained in the position (i) of the localeResources list */
92
    private static ArrayList localeResources = new ArrayList();
93
        private static ArrayList preferredLocales = new ArrayList(); // contains the ordered list of prefered languages/locales (class Locale)
94 4460 cesar
95
        /**
96 4728 cesar
         * <p>Gets the localized message associated with the provided key.
97
         * If the key is not in the dictionary, return the key and register
98
         * the failure in the log.</p>
99
         *
100
         * <p>The <code>callerName</code> parameter is only
101
         * used as a label when logging, so any String can be used. However, a
102
         * meaningful String should be used, such as the name of the class requiring
103
         * the translation services, in order to identify the source of the failure
104
         * in the log.</p>
105
         *
106
         * @param key         An String which identifies the translation that we want to get.
107 4516 cesar
         * @param callerName  A symbolic name given to the caller of this method, to
108 4728 cesar
         *                    show it in the log if the key was not found
109
         * @return            an String with the message associated with the provided key.
110
         *                    If the key is not in the dictionary, return the key. If the key
111
         *                    is null, return null.
112 4460 cesar
         */
113 4516 cesar
        public static String getText(String key, String callerName) {
114
                if (key==null) return null;
115 5767 cesar
                for (int numLocale=0; numLocale<localeResources.size(); numLocale++) {
116
                        // try to get the translation for any of the languagues in the preferred languages list
117
                        String translation = (String) ((HashMap)localeResources.get(numLocale)).get(key);
118 6343 cesar
                        if (translation!=null && !translation.equals(""))
119 5767 cesar
                                return translation;
120
                }
121 8010 cesar
                logger.warn(callerName+ " -- " +Messages.getText("No_se_encontro_la_traduccion_para", _CLASSNAME ,false)+" "+key);
122 4460 cesar
                return key;
123
        }
124
125
        /**
126 4728 cesar
         * <p>Gets the localized message associated with the provided key.
127 6664 cesar
         * If the key is not in the dictionary or the translation is empty,
128
         * return the key and register the failure in the log.</p>
129 4518 cesar
         *
130 4728 cesar
         * @param key     An String which identifies the translation that we want to get.
131
         * @return        an String with the message associated with the provided key.
132 6664 cesar
         *                If the key is not in the dictionary or the translation is empty,
133
         *                return the key. If the key is null, return null.
134 4518 cesar
         */
135
        public static String getText(String key) {
136 5767 cesar
                return getText(key, _CLASSNAME);
137 4518 cesar
        }
138
139
        /**
140 4728 cesar
         * <p>Gets the localized message associated with the provided key.
141 6664 cesar
         * If the key is not in the dictionary or the translation is empty,
142
         * it returns null and the failure is only registered in the log if
143
         * the param log is true.</p>
144 4460 cesar
         *
145 6664 cesar
         * @param key        An String which identifies the translation that we want
146
         *                                 to get.
147
         * @param log        Determines whether log a key failure or not
148
         * @return                an String with the message associated with the provided key,
149
         *                                 or null if the key is not in the dictionary or the
150
         *                                 translation is empty.
151 4460 cesar
         */
152 4728 cesar
        public static String getText(String key, boolean log) {
153 5767 cesar
                return getText(key, _CLASSNAME, log);
154 4736 cesar
        }
155
156
        /**
157
         * <p>Gets the localized message associated with the provided key.
158
         * If the key is not in the dictionary, it returns null and the failure
159
         * is only registered in the log if the param log is true.</p>
160
         *
161
         * @param key         An String which identifies the translation that we want to get.
162
         * @param callerName  A symbolic name given to the caller of this method, to
163
         *                    show it in the log if the key was not found
164
         * @param log         Determines whether log a key failure or not
165
         * @return            an String with the message associated with the provided key,
166
         *                    or null if the key is not in the dictionary.
167
         */
168
        public static String getText(String key, String callerName, boolean log) {
169
                if (key==null) return null;
170 5767 cesar
                for (int numLocale=0; numLocale<localeResources.size(); numLocale++) {
171
                        // try to get the translation for any of the languagues in the preferred languages list
172
                        String translation = (String) ((HashMap)localeResources.get(numLocale)).get(key);
173 6343 cesar
                        if (translation!=null && !translation.equals(""))
174 5767 cesar
                                return translation;
175
                }
176 5599 cesar
                if (log) {
177 8010 cesar
                        logger.warn(callerName+" -- "+Messages.getText("No_se_encontro_la_traduccion_para", _CLASSNAME ,false)+" "+key);
178 5599 cesar
                }
179 5767 cesar
                return null;
180 4736 cesar
        }
181 4516 cesar
182 4460 cesar
        /**
183 4728 cesar
         * <p>Adds an additional family of resource files containing some translations.
184 4460 cesar
         * A family is a group of files with a common baseName.
185 4728 cesar
         * The file must be an iso-8859-1 encoded file, which can contain any unicode
186
         * character using unicode escaped sequences, and following the syntax:
187
         * <code>key1=value1
188
         * key2=value2</code>
189 4460 cesar
         * where 'key1' is the key used to identify the string and must not
190 4728 cesar
         * contain the '=' symbol, and 'value1' is the associated translation.</p>
191
         * <p<For example:</p>
192
         * <code>cancel=Cancelar
193
         * accept=Aceptar</code>
194
         * <p>Only one pair key-value is allowed per line.</p>
195 4460 cesar
         *
196 4728 cesar
         * <p>The actual name of the resource file to load is determined using the rules
197
         * explained in the class java.util.ResourceBundle. Summarizing, for each language
198
         * in the specified preferred locales list it will try to load a file with
199
         *  the following structure: <code>family_locale.properties</code></p>
200
         *
201
         * <p>For example, if the preferred locales list contains {"fr", "es", "en"}, and
202
         * the family name is "text", it will try to load the files "text_fr.properties",
203
         * "text_es.properties" and finally "text_en.properties".</p>
204
         *
205
         * <p>Locales might be more specific, such us "es_AR"  (meaning Spanish from Argentina)
206
         * or "es_AR_linux" (meaning Linux system preferring Spanish from Argentina). In the
207
         * later case, it will try to load "text_es_AR_linux.properties", then
208
         * "text_es_AR.properties" if the former fails, and finally "text_es.properties".</p>
209
         *
210
         * <p>The directory used to locate the resource file is determining by using the
211
         * getResource method from the provided ClassLoader.</p>
212
         *
213
         * @param family    The family name (or base name) which is used to search
214
         *                  actual properties files.
215
         * @param loader    A ClassLoader which is able to find a property file matching
216
         *                                         the specified family name and the preferred locales
217
         * @see             <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/ResourceBundle.html">ResourceBundle</a>
218 4460 cesar
         */
219 4516 cesar
        public static void addResourceFamily(String family, ClassLoader loader) {
220 5767 cesar
                addResourceFamily(family, loader, "");
221 4516 cesar
        }
222 4587 cesar
223 4728 cesar
        /**
224
         * <p>Adds an additional family of resource files containing some translations.
225
         * The search path to locate the files is provided by the dirList parameter.</p>
226
         *
227
         * <p>See {@link addResourceFamily(String, ClassLoader)} for a discussion about the
228
         * format of the property files and the way to determine the candidat files
229
         * to load. Note that those methods are different in the way to locate the
230
         * candidat files. This method searches in the provided paths (<code>dirList</code>
231
         * parameter), while the referred method searches using the getResource method
232
         * of the provided ClassLoader.</p>
233
         *
234
         * @param family    The family name (or base name) which is used to search
235
         *                  actual properties files.
236
         * @param dirList   A list of search paths to locate the property files
237
         * @throws MalformedURLException
238
         * @see             <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/ResourceBundle.html">ResourceBundle</a>
239
         */
240 4587 cesar
        public static void addResourceFamily(String family, File[] dirList) throws MalformedURLException{
241 4597 cesar
                // use our own classloader
242 4587 cesar
                URL[] urls = new URL[dirList.length];
243
244
                        int i;
245
                        for (i=0; i<urls.length; i++) {
246
                                urls[i] = dirList[i].toURL();
247
                        }
248
249 5868 cesar
                ClassLoader loader = new MessagesClassLoader(urls);
250 5767 cesar
                addResourceFamily(family, loader, "");
251 4587 cesar
        }
252 4516 cesar
253 4728 cesar
        /**
254
         * <p>Adds an additional family of resource files containing some translations.
255
         * The search path to locate the files is provided by the dir parameter.</p>
256
         *
257
         * <p>See {@link addResourceFamily(String, ClassLoader)} for a discussion about the
258
         * format of the property files and the way to determine the candidat files
259
         * to load. Note that those methods are different in the way to locate the
260
         * candidat files. This method searches in the provided path (<code>dir</code>
261
         * parameter), while the referred method searches using the getResource method
262
         * of the provided ClassLoader.</p>
263
         *
264
         * @param family    The family name (or base name) which is used to search
265
         *                  actual properties files.
266
         * @param dir       The search path to locate the property files
267
         * @throws MalformedURLException
268
         * @see             <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/ResourceBundle.html">ResourceBundle</a>
269
         */
270 4587 cesar
        public static void addResourceFamily(String family, File dir) throws MalformedURLException{
271 4597 cesar
                // use our own classloader
272 4587 cesar
                URL[] urls = new URL[1];
273
                urls[0] = dir.toURL();
274 5868 cesar
                ClassLoader loader = new MessagesClassLoader(urls);
275 5767 cesar
                addResourceFamily(family, loader, "");
276 4587 cesar
        }
277
278
279 4516 cesar
        /**
280 4728 cesar
         * <p>Adds an additional family of resource files containing some translations.
281
         * The search path is determined by the getResource method from the
282
         * provided ClassLoader.</p>
283 4516 cesar
         *
284 4728 cesar
         * <p>This method is identical to {@link addResourceFamily(String, ClassLoader)},
285
         * except that it adds a <pode>callerName</code> parameter to show in the log.</p>
286
         *
287
         * <p>See {@link addResourceFamily(String, ClassLoader)} for a discussion about the
288
         * format of the property files andthe way to determine the candidat files
289
         * to load.</p>
290
         *
291
         * @param family      The family name (or base name) which is used to search
292
         *                    actual properties files.
293
         * @param loader      A ClassLoader which is able to find a property file matching
294
         *                                           the specified family name and the preferred locales
295
         * @param callerName  A symbolic name given to the caller of this method, to
296
         *                    show it in the log if there is an error
297
         * @see               <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/ResourceBundle.html">ResourceBundle</a>
298 4516 cesar
         */
299
        public static void addResourceFamily(String family, ClassLoader loader, String callerName) {
300
                String currentKey;
301 5767 cesar
                Enumeration properties;
302 12863 cesar
                Locale defaultLocale = Locale.getDefault();
303 5767 cesar
                int totalLocales = preferredLocales.size();
304
305
                if (totalLocales == 0) {
306 4728 cesar
                        // if it's empty, warn about that
307 8010 cesar
                        logger.warn(Messages.getText("No_hay_lista_de_idiomas_preferidos_quiza_olvido_inicializar_clase", _CLASSNAME, false));
308 4780 cesar
                }
309 4516 cesar
                Locale lang;
310
                ResourceBundle bundle = null;
311
312 5767 cesar
                for (int numLocale=0; numLocale<totalLocales; numLocale++) { // for each language
313
                        lang = (Locale) preferredLocales.get(numLocale);
314 4597 cesar
                        try {
315 5767 cesar
                                /**
316
                                 * Here we are doing a pervert use of getBundle method. Normally, it is call it in in this way:
317
                                 * getBundle("text", "en", loader), in order to get the file 'text_en.properties'. However, in
318
                                 * this way the default file ('text.properties') is also loaded, and we want to avoid this
319
                                 * (because 'text.properties contains the Spanish translation).
320
                                 * So we use the method in this non-standard way:
321
                                 * getBundle("text_en", "en", loader), ensuring that we are just loading the file 'text_en.properties'
322
                                 **/
323
                                if (!lang.getLanguage().equals("es"))
324
                                        bundle = ResourceBundle.getBundle(family+"_"+lang.getLanguage(), lang, loader);
325 12863 cesar
                                else { // we allow 'text.properties' to be loaded for Spanish
326
                                         if (Locale.getDefault().equals(lang)) {
327
                                                 bundle = ResourceBundle.getBundle(family, lang, loader);
328
                                         }
329
                                         else {
330
                                                // we need to temporarily change the default locale to properly load spanish in corner cases
331
                                                 Locale.setDefault(lang);
332
                                                 bundle = ResourceBundle.getBundle(family, lang, loader);
333
                                                 Locale.setDefault(defaultLocale);
334
                                         }
335
                                }
336
337 5767 cesar
                                properties = bundle.getKeys();
338
                                while (properties.hasMoreElements()) {
339
                                        currentKey = (String) properties.nextElement();
340
                                        if (! ((HashMap)localeResources.get(numLocale)).containsKey(currentKey)) {
341
                                                ((HashMap)localeResources.get(numLocale)).put(currentKey, bundle.getString(currentKey));
342 4460 cesar
                                        }
343
                                }
344
                        }
345 4597 cesar
                        catch (MissingResourceException ex) {
346 12863 cesar
                                Locale.setDefault(defaultLocale);
347 8010 cesar
                                logger.warn(Messages.getText("Las_traducciones_no_pudieron_ser_cargadas", false)+" -- "+callerName+" -- "+lang.getLanguage());
348 4597 cesar
                        }
349 4460 cesar
                }
350
        }
351
352 4728 cesar
        /**
353
         * <p>Adds an additional family of resource files containing some translations.</p>
354
         *
355
         * <p>This method is identical to {@link addResourceFamily(String, ClassLoader, String)},
356
         * except that it uses the caller's class loader.</p>
357
         *
358
         * <p>See {@link addResourceFamily(String, ClassLoader)} for a discussion about the
359
         * format of the property files and the way to determine the candidat files
360
         * to load.</p>
361
         *
362
         * @param family      The family name (or base name) which is used to search
363
         *                    actual properties files.
364
         * @param callerName  A symbolic name given to the caller of this method, to
365
         *                    show it in the log if there is an error. This is only used
366
         *                    to show
367
         *                    something meaningful in the log, so you can use any string
368
         * @see               <a href="http://java.sun.com/j2se/1.4.2/docs/api/java/util/ResourceBundle.html">ResourceBundle</a>
369
         */
370
        public static void addResourceFamily(String family, String callerName) {
371
                String currentKey;
372 5767 cesar
                Enumeration properties;
373 12863 cesar
                Locale defaultLocale = Locale.getDefault();
374 5767 cesar
                int totalLocales = preferredLocales.size();
375
376
                if (totalLocales == 0) {
377 4728 cesar
                        // if it's empty, warn about that
378 8471 cesar
                        logger.warn(Messages.getText("No_hay_lista_de_idiomas_preferidos_quiza_olvido_inicializar_clase", _CLASSNAME, false));
379 5767 cesar
                }
380 4728 cesar
                Locale lang;
381
                ResourceBundle bundle = null;
382
383 5767 cesar
                for (int numLocale=0; numLocale<totalLocales; numLocale++) { // for each language
384 4728 cesar
                        try {
385 5767 cesar
                                lang = (Locale) preferredLocales.get(numLocale);
386 8010 cesar
                                if (!lang.getLanguage().equals("es"))         // ensure we don't get a fallback
387 6294 cesar
                                        bundle = ResourceBundle.getBundle(family+"_"+lang.getLanguage(), lang);
388 12863 cesar
                                else { // we allow 'text.properties' to be loaded for Spanish
389
                                         if (Locale.getDefault().equals(lang)) {
390
                                                 bundle = ResourceBundle.getBundle(family, lang);
391
                                         }
392
                                         else {
393
                                                // we need to temporarily change the default locale to properly load spanish in corner cases
394
                                                 Locale.setDefault(lang);
395
                                                 bundle = ResourceBundle.getBundle(family, lang);
396
                                                 Locale.setDefault(defaultLocale);
397
                                         }
398
                                }
399 5767 cesar
400 8010 cesar
                                properties = bundle.getKeys();
401
                                while (properties.hasMoreElements()) {
402
                                        currentKey = (String) properties.nextElement();
403
                                        if (! ((HashMap)localeResources.get(numLocale)).containsKey(currentKey)) {
404
                                                ((HashMap)localeResources.get(numLocale)).put(currentKey, bundle.getString(currentKey));
405 4728 cesar
                                        }
406 8010 cesar
                                }
407 4728 cesar
                        }
408
                        catch (MissingResourceException ex) {
409 12863 cesar
                                Locale.setDefault(defaultLocale);
410 6294 cesar
                                logger.warn(callerName+" " + ex.getLocalizedMessage());
411 4728 cesar
                        }
412
                }
413
        }
414 4516 cesar
415 8010 cesar
        private static void addResourceFamily(String family, Locale lang, HashMap dict) {
416
                String currentKey;
417
                Enumeration properties;
418
419
                ResourceBundle bundle = null;
420 12863 cesar
                Locale defaultLocale = Locale.getDefault();
421 8010 cesar
422
                try {
423
                        if (!lang.getLanguage().equals("es")) // ensure we don't get a fallback
424
                                bundle = ResourceBundle.getBundle(family+"_"+lang.getLanguage(), lang);
425 12863 cesar
                        else { // we allow 'text.properties' to be loaded for Spanish
426
                                 if (Locale.getDefault().equals(lang)) {
427
                                         bundle = ResourceBundle.getBundle(family, lang);
428
                                 }
429
                                 else {
430
                                        // we need to temporarily change the default locale to properly load spanish in corner cases
431
                                         Locale.setDefault(lang);
432
                                         bundle = ResourceBundle.getBundle(family, lang);
433
                                         Locale.setDefault(defaultLocale);
434
                                 }
435
                        }
436 8010 cesar
                        properties = bundle.getKeys();
437
                        while (properties.hasMoreElements()) {
438
                                currentKey = (String) properties.nextElement();
439
                                if (! dict.containsKey(currentKey)) {
440
                                        dict.put(currentKey, bundle.getString(currentKey));
441
                                }
442
                        }
443
                }
444
                catch (MissingResourceException ex) {
445 12863 cesar
                        Locale.setDefault(defaultLocale);
446 8010 cesar
                        logger.warn(Messages.class.getName()+" " + ex.getLocalizedMessage());
447
                }
448
        }
449
450 4728 cesar
451 4460 cesar
        /**
452 5599 cesar
         * Returns an ArrayList containing the ordered list of prefered Locales
453
         * Each element of the ArrayList is a Locale object.
454 4460 cesar
         *
455 5599 cesar
         * @return an ArrayList containing the ordered list of prefered Locales
456
         * Each element of the ArrayList is a Locale object.
457 4460 cesar
         */
458 5599 cesar
        public static ArrayList getPreferredLocales() {
459 5767 cesar
                return preferredLocales;
460 4460 cesar
        }
461
462
        /**
463 5767 cesar
         * <p>Sets the ordered list of preferred locales.
464
         * Each element of the ArrayList is a Locale object.</p>
465 4460 cesar
         *
466 5767 cesar
         * <p>Note that calling this method does not load any translation, it just
467
         * adds the language to the preferred locales list, so this method must
468
         * be always called before the translations are loaded using
469
         * the addResourceFamily() methods.</p>
470
         *
471 8010 cesar
         * <p>It there was any language in the preferred locale list, the language
472
         * and its associated translations are deleted.</p>
473
         *
474
         *
475 5599 cesar
         * @param preferredLocales an ArrayList containing Locale objects.
476
         * The ArrayList represents an ordered list of preferred locales
477 4460 cesar
         */
478 5767 cesar
        public static void setPreferredLocales(ArrayList preferredLocalesList) {
479 8010 cesar
                // delete all existing locales
480
                Iterator oldLocales = preferredLocales.iterator();
481
                while (oldLocales.hasNext()) {
482
                        removeLocale((Locale) oldLocales.next());
483
                }
484
485
                // add the new locales now
486 5767 cesar
                for (int numLocale=0; numLocale < preferredLocalesList.size(); numLocale++) {
487
                        addLocale((Locale) preferredLocalesList.get(numLocale));
488
                }
489 4460 cesar
        }
490 4728 cesar
491
        /**
492
         * Adds a Locale at the end of the ordered list of preferred locales.
493 5767 cesar
         * Note that calling this method does not load any translation, it just
494
         * adds the language to the preferred locales list, so this method must
495
         * be always called before the translations are loaded using
496
         * the addResourceFamily() methods.
497 4728 cesar
         *
498
         * @param lang   A Locale object specifying the locale to add
499
         */
500 4516 cesar
        public static void addLocale(Locale lang) {
501 5767 cesar
                if (!preferredLocales.contains(lang)) { // avoid duplicates
502
                                preferredLocales.add(lang); // add the lang to the ordered list of preferred locales
503 8010 cesar
                                HashMap dict = new HashMap(_INITIALSIZE);
504
                                localeResources.add(dict); // add a hashmap which will contain the translation for this language
505
                                addResourceFamily("org.gvsig.i18n.resources.translations.text", lang, dict);
506 4516 cesar
                }
507
        }
508 4728 cesar
509
        /**
510 5767 cesar
         * Removes the specified Locale from the list of preferred locales and the
511
         * translations associated with this locale.
512 4728 cesar
         *
513
         * @param lang   A Locale object specifying the locale to remove
514 5599 cesar
         * @return       True if the locale was in the preferred locales list, false otherwise
515 4728 cesar
         */
516 4587 cesar
        public static boolean removeLocale(Locale lang) {
517 5767 cesar
                int numLocale = preferredLocales.indexOf(lang);
518
                if (numLocale!=-1) { // we found the locale in the list
519
                        try {
520
                                preferredLocales.remove(numLocale);
521
                                localeResources.remove(numLocale);
522
                        }
523
                        catch (IndexOutOfBoundsException ex) {
524
                                logger.warn(_CLASSNAME + "." + "removeLocale: " + ex.getLocalizedMessage());
525
                        }
526
                        return true;
527 5599 cesar
                }
528 5767 cesar
                return false;
529 4587 cesar
        }
530 4728 cesar
531 4460 cesar
        /**
532 5767 cesar
         * Cleans the translation tables (removes all the translations from memory).
533 4728 cesar
         */
534
        public static void removeResources() {
535 5767 cesar
                for (int numLocale=0; numLocale<localeResources.size(); numLocale++) {
536
                        ((HashMap)localeResources.get(numLocale)).clear();
537
                }
538 4728 cesar
        }
539
540
        /**
541
         * The number of translation keys which have been loaded till now
542
         * (In other words: the number of available translation strings).
543 5767 cesar
         *
544
         * @param lang The language for which we want to know the number of translation keys
545
         * return The number of translation keys for the provided language.
546 4728 cesar
         */
547 5767 cesar
        protected static int size(Locale lang) {
548
                int numLocale = preferredLocales.indexOf(lang);
549
                if (numLocale!=-1) {
550
                        return ((HashMap)localeResources.get(numLocale)).size();
551
                };
552
                return 0;
553 4728 cesar
        }
554 7258 cesar
555 4728 cesar
        /**
556 7258 cesar
         * Checks if some locale has been added to the preferred locales
557
         * list, which is necessary before loading any translation because
558
         * only the translations for the preferred locales are loaded.
559
         *
560
         * @return
561
         */
562
        public static boolean hasLocales() {
563
                return preferredLocales.size()>0;
564
        }
565
566
        /**
567 4460 cesar
         * Searches the subdirectories of the provided directory, finding
568
         * all the translation files, and constructing a list of available translations.
569
         * It reports different country codes or variants, if available.
570
         * For example, if there is an en_US translation and an en_GB translation, both
571
         * locales will be present in the Vector.
572
         *
573
         * @return
574
         */
575
576
        /**
577
         *
578
         * @return A Vector containing the available locales. Each element is a Locale object
579
         */
580 4728 cesar
        /*public static Vector getAvailableLocales() {
581 4460 cesar
                return _availableLocales;
582 4728 cesar
        }*/
583 4460 cesar
584
        /**
585
         *
586
         * @return A Vector containing the available languages. Each element is an String object
587
         */
588 4728 cesar
        /*public static Vector getAvailableLanguages() {
589 4460 cesar
                Vector availableLanguages = new Vector();
590
                Locale lang;
591
                Enumeration locales = _availableLocales.elements();
592
                while (locales.hasMoreElements()) {
593
                        lang = (Locale) locales.nextElement();
594
                        availableLanguages.add(lang.getLanguage());
595
                }
596
                return availableLanguages;
597 4728 cesar
        }*/
598 5767 cesar
}