What is the difference between a Locale
country and language such as Locale.ITALY
and Locale.ITALIAN
? Where can I find all these differences for other locales? When should I use each one?
And is it possible to develop our required locale? How?
[loˈkale ] adjective. local. (treno) stopping (British) ⧫ local (US)
A Locale object represents a specific geographical, political, or cultural region. An operation that requires a Locale to perform its task is called locale-sensitive and uses the Locale to tailor information for the user.
The default locale determines the format. The number may be a primitive (such as int or double ) or a wrapper object (such as Integer or Double ). The language is english and the country is Great Britain. Locales specify both language and country.
Locale Class is used to perform locale task and provides locale information for the user. Constructors : Locale(String L): Creates Locale form the given language code. Locale(String L, String C): Creates Locale form the given language, country code.
Locale.ITALIAN sets only Italian language, country is left unspecified. Locale.ITALY sets both Italian as language and Italy as country.
It depends on classes that use Locale how they will inteprete this combination. Eg DateFormat API says to format a date for a different Locale, specify it in the call to getDateInstance(). but it does not say how exactly language and country will be interpreted. From my experience DateFormat (and other JDK classes except ResourceBundle) use only language part and ignore country. That is you may create DateFormat for it_IT or it_US or it_UK locales the DateFormat output will be the same
Locale
= ( human language + cultural norms of a country/region )
Best to specify both, when known.
Example: If you want Italian language (it
) with the cultural norms of Italy (IT
), use: new Locale( "it" , "IT" )
. If you want Italian language with the cultural norms of Vatican City (VA
), use: new Locale( "it" , "VA" )
. If you want Italian language with the cultural norms of Switzerland, use: new Locale( "it" , "CH" )
.
If you specify one part but not the other, Java must fall-back:
The details vary across implementations and versions of Java; behavior may vary. As of Java 9, Java implementations based on OpenJDK use by default the locale definitions provided by the Unicode Common Locale Data Repository (CLDR) project. The CLDR dataset is quite mature now. So no major changes are likely, but some changes may still occur in fresh updates.
Avoid the hard-coded constants in Locale
. There are only a few, and they muddy the waters as to the distinction between language and culture. Rather than use either Locale.ITALIAN
or Locale.ITALY
, use new Locale
as seen above.
Locale
A Locale
object holds two pieces of information: The human language, and cultural norms.
The human language portion of a Locale
specifies the language used in translation.
For example, when formatting a date-time value, the name of the month and name of the day-of-week are generated according to the human language. Monday
in English, and lundi
in French.
The cultural norms portion specifies various rules to follow when localizing. These rules include punctuation, abbreviation, capitalization, element ordering, and such.
For example, Canada is a dual cultural country. So when formatting a date-time object, the date in Locale.CANADA_FRENCH
the cultural norm is to format the date portion with the day-of-month coming before the name-of-month while in Locale.CANADA
(English) the cultural norm is the opposite. See below for example.
Some example code using the dual cultures of Canada.
package work.basil.example;
import java.time.*;
import java.time.format.*;
import java.util.Locale;
public class TickTock {
public static void main ( String[] args ) {
TickTock app = new TickTock();
app.doIt();
}
private void doIt ( ) {
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.now( z );
FormatStyle fs = FormatStyle.MEDIUM;
Locale lCanadaFrench = Locale.CANADA_FRENCH;
DateTimeFormatter fCanadaFrench = DateTimeFormatter.ofLocalizedDateTime( fs ).withLocale( lCanadaFrench );
String outputCanadaFrench = zdt.format( fCanadaFrench );
Locale lCanadaEnglish = Locale.CANADA;
DateTimeFormatter fCanadaEnglish = DateTimeFormatter.ofLocalizedDateTime( fs ).withLocale( lCanadaEnglish );
String outputCanadaEnglish = zdt.format( fCanadaEnglish );
System.out.println( zdt );
System.out.println( outputCanadaFrench );
System.out.println( outputCanadaEnglish );
}
}
When run in Java 11 using Zulu by Azul Systems, built on OpenJDK, running on macOS Mojave.
2019-01-17T17:36:10.818469-05:00[America/Montreal]
17 janv. 2019 17 h 36 min 10 s
Jan. 17, 2019, 5:36:10 p.m.
When you specify a locale with only a human language but no country/region for cultural norms, Java falls back onto some set of cultural norms as a default. The details are up to the particular implementation of Java. And those details are subject to change in successive versions of that implementation.
Indeed, the details changed dramatically in implementations of Java based on the OpenJDK project. In OpenJDK 8, at least two sources of locale data were bundled: the legacy source and the much richer source from the Unicode Consortium (https://en.wikipedia.org/wiki/Unicode_Consortium), the Common Locale Data Repository (CLDR), with the legacy source used first. In OpenJDK 9 and later, a change was made (JEP 252) to always check the CLDR first for locale data. This change altered the behavior for some locales.
When you know the desired/expected cultural norms to be used, specify by indicating the country code. For example, rather than just ar
for Arabic, specify the cultural norms of Saudi Arabia (ar-SA
), Tunisia (ar-TN
), or Morocco (ar-MA
).
In addition to the grosser level of country code, you can also specify a locale with a variant, for a subculture. While not many variants were available in the legacy Java locale data, many many variants are provided in the CLDR.
For more info, read the JavaDoc for Locale
and the CLDR documentation.
The Locale
class has only a few locales hard-coded as named constants. In retrospect, including those constants was probably a poor design decision. You may want to ignore them and always use constructors (new Locale
) or the factory methods.
For Italian language with cultural norms, specify both to make your code crystal-clear as to your intentions.
Locale locale = new Locale( "it" , "IT" ) ; // Pass standard code for human language, and standard code for country (cultural norms).
To see all constants, run this code. Be aware, as discussed above, available locales and their behavior may vary by implementation of Java.
for ( Locale locale : Locale.getAvailableLocales() ) {
System.out.println( locale.toString() + " Name: " + locale.getDisplayName( Locale.US ) );
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With