Playing with Locale in Java..

Locales everywhere, effecting (affecting?) everything!

LocaleTest.java
import java.util.Locale;
 
public class LocaleTest {
 
    public static void main(String[] args) {
        final Locale defaultLocale = Locale.getDefault();
        print("Your default Locale is: " + defaultLocale);
 
        final Locale localeFR = new Locale("fr", "FR");
        final Locale localeTR = new Locale("tr", "TR");
        final Locale localeIT = new Locale("it", "IT");
 
        print("** LocaleFR - getDisplayLanguage **: " + localeFR.getDisplayLanguage());
        print("** LocaleFR - getDisplayCountry  **: " + localeFR.getDisplayCountry());
 
        print("** LocaleTR - getDisplayLanguage **: " + localeTR.getDisplayLanguage());
        print("** LocaleTR - getDisplayCountry  **: " + localeTR.getDisplayCountry());
 
        print("** LocaleIT - getDisplayLanguage **: " + localeIT.getDisplayLanguage());
        print("** LocaleIT - getDisplayCountry  **: " + localeIT.getDisplayCountry());
    }
 
    static void print(Object o) {
        System.out.println(o);
    } 
}

Lets run our example:
MacBook-Pro:~ koraytugay$ java LocaleTest
Your default Locale is: en_US
** LocaleFR - getDisplayLanguage **: French
** LocaleFR - getDisplayCountry  **: France
** LocaleTR - getDisplayLanguage **: Turkish
** LocaleTR - getDisplayCountry  **: Turkey
** LocaleIT - getDisplayLanguage **: Italian
** LocaleIT - getDisplayCountry  **: Italy

And run with setting default Locale to Fr:
MacBook-Pro:~ koraytugay$ java -Duser.language=fr -Duser.country=FR LocaleTest
Your default Locale is: fr_FR
** LocaleFR - getDisplayLanguage **: franĪ„ais
** LocaleFR - getDisplayCountry  **: France
** LocaleTR - getDisplayLanguage **: turc
** LocaleTR - getDisplayCountry  **: Turquie
** LocaleIT - getDisplayLanguage **: italien
** LocaleIT - getDisplayCountry  **: Italie

Conclusions?
The Country Name and the Language is returned to the User based on the Default Locale. So if your default Locale is fr_FR, you get Turquie as the Country name from a Turkish Locale Object. This is already well documented in the JDK documentation:
public final String getDisplayCountry()
Returns a name for the locale's country that is appropriate for display to the user. If possible, the name returned will be localized for the default locale. For example, if the locale is fr_FR and the default locale is en_US, getDisplayCountry() will return "France"; if the locale is en_US and the default locale is fr_FR, getDisplayCountry() will return "Etats-Unis". If the name returned cannot be localized for the default locale, (say, we don't have a Japanese name for Croatia), this function falls back on the English name, and uses the ISO code as a last-resort value. If the locale doesn't specify a country, this function returns the empty string.


How do I see what is "Turkey" is called in "France" if my default Locale is "US"?

You can always use the overloaded method: public String getDisplayCountry(Locale inLocale)
import java.util.Locale;
 
public class LocaleTest {
 
    public static void main(String[] args) {
        final Locale defaultLocale = Locale.getDefault();
        print("Your default Locale is: " + defaultLocale);
 
        final Locale localeFR = new Locale("fr", "FR");
        final Locale localeTR = new Locale("tr", "TR");
 
        print("** LocaleTR - getDisplayLanguage **: " + localeTR.getDisplayLanguage(localeFR));
        print("** LocaleTR - getDisplayCountry  **: " + localeTR.getDisplayCountry(localeFR));
    }
 
    static void print(Object o) {
        System.out.println(o);
    } 
}

Here is a sample execution:
MacBook-Pro:~ koraytugay$ java LocaleTest
Your default Locale is: en_US
** LocaleTR - getDisplayLanguage **: turc
** LocaleTR - getDisplayCountry  **: Turquie

Reactions?
I think the method public String getDisplayLanguage(Locale inLocale) is poorly named. I think it would have been much better if it was called something getDisplayLanguageInLocale(Locale inLocale).


Calendar and Locale please..

import java.util.Locale;
import java.util.Calendar;
import java.util.TimeZone;
 
public class LocaleTest {
 
    public static void main(String[] args) {
        final Locale defaultLocale = Locale.getDefault();
        print("Your default Locale is: " + defaultLocale);
 
        final Locale localeFR = new Locale("fr", "FR");
        final Locale localeRU = new Locale("ru", "RU");
 
        final Calendar defaultCalendar = Calendar.getInstance();
        final Calendar calendarFR = Calendar.getInstance(localeFR);
        final Calendar calendarRU = Calendar.getInstance(localeRU);
 
        print("Calendar   - First Day of week: " + defaultCalendar.getFirstDayOfWeek());
        print("CalendarFR - First Day of week: " + calendarFR.getFirstDayOfWeek());
        print("CalendarRU - First Day of week: " + calendarRU.getFirstDayOfWeek());
 
        print("Calendar   - Time Zone: " + defaultCalendar.getTimeZone().getID());
        print("CalendarFR - Time Zone: " + calendarFR.getTimeZone().getID());
        print("CalendarRU - Time Zone: " + calendarRU.getTimeZone().getID());
 
        print("Calendar   - " + calendarFR);
        print("CalendarFR - " + calendarFR);
        print("CalendarRU - " + calendarRU);
   }
 
    static void print(Object o) {
        System.out.println(o);
    } 
}

And the output will be..
MacBook-Pro:~ koraytugay$ java LocaleTest
Your default Locale is: en_US
Calendar   - First Day of week: 1
CalendarFR - First Day of week: 2
CalendarRU - First Day of week: 2
Calendar   - Time Zone: Europe/Istanbul
CalendarFR - Time Zone: Europe/Istanbul
CalendarRU - Time Zone: Europe/Istanbul
Calendar   - GregorianCalendar[zone=ZoneInfo[id="Europe/Istanbul",useDaylight=true,lastRule=java.util.SimpleTimeZone[id=Europe/Istanbul]],firstDayOfWeek=2,minimalDaysInFirstWeek=4,WEEK_OF_YEAR=29,WEEK_OF_MONTH=3]
CalendarFR - GregorianCalendar[zone=ZoneInfo[id="Europe/Istanbul",useDaylight=true,lastRule=java.util.SimpleTimeZone[id=Europe/Istanbul]],firstDayOfWeek=2,minimalDaysInFirstWeek=4,WEEK_OF_YEAR=29,WEEK_OF_MONTH=3]
CalendarRU - GregorianCalendar[zone=ZoneInfo[id="Europe/Istanbul",useDaylight=true,lastRule=java.util.SimpleTimeZone[id=Europe/Istanbul]],firstDayOfWeek=2,minimalDaysInFirstWeek=1,WEEK_OF_YEAR=30,WEEK_OF_MONTH=4]

Comments
  • Time Zones of the Calendars are independent of the Locale we set them! I do not like this!
  • First Day of weeks are correct, based on the Locale, but useDaylight is NOT!

How to Fix?
There are 2 ways actually, start with #1..
import java.util.Locale;
import java.util.Calendar;
import java.util.TimeZone;
 
public class LocaleTest {
 
    public static void main(String[] args) {
        final Locale localeRU = new Locale("ru", "RU");
        final Calendar calendarRU = Calendar.getInstance(TimeZone.getTimeZone("Europe/Kaliningrad"), localeRU);
        print("CalendarRU - First Day of week: " + calendarRU.getFirstDayOfWeek());
        print("CalendarRU - Time Zone: " + calendarRU.getTimeZone().getID());
        print("CalendarRU - " + calendarRU);
   }
 
    static void print(Object o) {
        System.out.println(o);
    } 
}

And the output..
MacBook-Pro:~ koraytugay$ java LocaleTest
CalendarRU - First Day of week: 2
CalendarRU - Time Zone: Europe/Kaliningrad
CalendarRU - java.util.GregorianCalendar[zone=sun.util.calendar.ZoneInfo[id="Europe/Kaliningrad",useDaylight=false],firstDayOfWeek=2]

So make sure you also pass the TimeZone to the Calendar 's getInstance method when you are expecting the Calendar to work well with the expected TimeZone as well!

Fix #2, given..
import java.util.Locale;
import java.util.Calendar;
import java.util.TimeZone;
 
public class LocaleTest {
 
    public static void main(String[] args) {
        final Locale localeRU = new Locale("ru", "RU");
        final Calendar calendarRU = Calendar.getInstance(localeRU);
        print("CalendarRU - First Day of week: " + calendarRU.getFirstDayOfWeek());
        print("CalendarRU - Time Zone: " + calendarRU.getTimeZone().getID());
        print("CalendarRU - " + calendarRU);
   }
 
    static void print(Object o) {
        System.out.println(o);
    } 
}

This will make things work as well.
java -Duser.timezone="Europe/Kaliningrad" LocaleTest

I find it weird that the JVM uses the default TimeZone for a Localised Calendar!