All Downloads are FREE. Search and download functionalities are using the official Maven repository.

errorprone.bugpattern.UnsafeLocaleUsage.md Maven / Gradle / Ivy

The newest version!
The Java `Locale` API is broken in a few ways that should be avoided, with some
examples of error prone issues below:

#### Constructors

The constructors don't validate the parameters at all, they just "trust" it
100%.

For example:

```
Locale locale = new Locale("en_AU");
toString()        : "en_au"
getLanguage()     : "en_au"
locale.getCountry : ""

locale = new Locale("somethingBad#!34, too long, and clearly not a locale ID");
toString()    : "somethingbad#!34, too long, and clearly not a locale id"
getLanguage() : "somethingbad#!34, too long, and clearly not a locale id"
getCountry()  : ""
```

As you can see, the full string is interpreted as language, and the country is
empty.

For `new Locale("zh", "tw", "#Hant")` you get:

```
toString()    : zh_TW_#Hant
getLanguage() : zh
getCountry()  : TW
getScript()   :
getVariant()  : #Hant
```

And for `Locale.forLanguageTag("zh-hant-tw")` you get a different result:

```
toString()    : zh_TW_#Hant
getLanguage() : zh
getCountry()  : TW
getScript()   : Hant
getVariant()  :
```

We can see that while the `toString()` value for both locales are equivalent,
the individual parts are different. More specifically, the first locale is
incorrect since `#Hant` is supposed to be the script for the locale rather than
the variant. \
There's no reliable way of getting a correct result through a `Locale`
constructor, so we should prefer using `Locale.forLanguageTag()` (and the IETF
BCP 47 format) for correctness.

**Note:** You might see a `.replace("_", "-")` appended to a suggested fix for
the error prone checker for this bug pattern. This is sanitization measure to
handle the fact that `Locale.forLanguageTag()` accepts the "minus form" of a tag
(`en-US`) but not the "underscore form" (`en_US`). It will silently default to
`Locale.ROOT` if the latter form is passed in.

#### toString()

This poses the inverse of the constructor problem

```
Locale myLocale = Locale.forLanguageTag("zh-hant-tw")
String myLocaleStr = myLocale.toString() // zh_TW_#Hant
Locale derivedLocale = ??? // Not clean way to get a correct locale from this string
```

The `toString()` implementation for `Locale` isn't necessarily incorrect in
itself. \
It is intended to be _"concise but informative representation that is easy for a
person to read"_ (see documentation at
[Object.toString()](https://docs.oracle.com/javase/6/docs/api/java/lang/Object.html#toString\(\))).

So it is not intended to produce a value that can be turned back into a
`Locale`. It is not a serialization format. \
It often produces a value that _looks_ like a locale identifier, but it is not.




© 2015 - 2025 Weber Informatics LLC | Privacy Policy