views:

906

answers:

3

E.g. eng, spa, ita, ger

I could iterate all locales and compare the codes, but I wonder whether there is a more elegant & performant way to achieve this....

Thanks a lot for any hints :)

+1  A: 

You can use constructor Locale(String language), where language is the 2 letter ISO-639-1 code. I think the easiest way to convert ISO-639-2 to ISO-639-1 would be to create HashMap<String,String> constant.

vartec
I know I could. Unfortunately 3 letter codes is what I get from the DB.
PeterP
Use this list. http://en.wikipedia.org/wiki/List_of_ISO_639-1_codes
vartec
Hm would work, but is not quite elegant, I'd say...Sometimes I wonder about Java... :-/
PeterP
No it's not elegant. But using ISO-639-2 codes is rather uncommon.
vartec
+3  A: 

I don't know if there's an easy way to convert the 3-letter to the 2-letter versions, but in a worse case scenario, you could create a Map of them, like so:

String[] languages = Locale.getISOLanguages();
Map<String, Locale> localeMap = new HashMap<String, Locale>(languages.length);
for (String language : languages) {
    Locale locale = new Locale(language);
    localeMap.put(locale.getISO3Language(), locale);
}

Now you can look up locales using things like localeMap.get("eng");

Edit: Modified the way the map is created. Now there should be one object per language.

Edit 2: It's been a while, but changed the code to use the actual length of the languages array when initializing the Map.

R. Bemrose
Thanks - I cannot say this is the answer I hoped for, but obviously there really is no better way :(
PeterP
Not ideal, I know. You'd think there'd be a built-in way of handling this... Also, I modified the code to pre-allocate the map with 185 entries, as that's what (the windows version of) Java 6u11 has.
R. Bemrose
Yep, that is what I hoped - Java is weird sometimes.Thanks for your input on this
PeterP
It would e better to get languages first, then allocate localeMap based on languages' size.
Daniel
Good point. Done.
R. Bemrose
A: 

Some modified code from my project, which has a similar requirement. We have our own historical timezone format so we can't use standard libraries.

public class MyProjectTimeZoneFactory  {

   private static Map timeZoneDb;

   /**
   * Set up our timezone id mappings; call this from any constructor
   * or static method that needs it.
   */
   private static void init() {
      if(null == TimeZoneDb) {
         timeZoneDb = new HashMap();   // Maybe a TreeMap would be more appropriate
         timeZoneDb.put("     ","GMT+00");
         timeZoneDb.put("EAD  ","GMT+10");
         timeZoneDb.put("JST  ","GMT+9");
         // etc.
       }
   }

   public static TimeZone getTimeZone(String id) 
                          throws CommandFormatException {
       init();

       TimeZone tz;
       if(timeZoneDb.containsKey(id)) {
           tz = TimeZone.getTimeZone((String)timeZoneDb.get(id));
       } else {
           throw new CommandFormatException("Invalid Timezone value");
       }

       return tz;
   }

 }

You could argue that it would be better to have the map in configuration rather than code - perhaps in a properties file. That may be true - but do remember the Pragmatic Programmers' rule 'Your not going to need it'.

slim