Locale appending 'variation' to language and country code - java

LocaleContext.getLocale() returns the locale object currently as 'en_US_WOL'. I verified the locale object using breakpoint and looks like en- language English, US - country code of US, WOL - variation (a field of Locale object).
How and why is the variation field getting appending and returned for getLocale() method? and how can I stop that? (LocaleContext is of type ThreadLocal)

According to http://docs.oracle.com/javase/6/docs/api/java/util/Locale.html
The variant argument is a vendor or browser-specific code. For example, use WIN for Windows, MAC for Macintosh, and POSIX for POSIX. Where there are two variants, separate them with an underscore, and put the most important one first. For example, a Traditional Spanish collation might construct a locale with parameters for language, country and variant as: "es", "ES", "Traditional_WIN".
If you're after Locale for specific variant, I presume you can use this constructor:
Locale(String language, String country, String variant)
Or adjust your browser's locale settings (if your application involves browser at all)

I had a problem with this too. Unfortunately I haven't found any build-in method to nicely output lang-country code without Variant so I helped myself with such snippet (maybe would be handy to somebody) :
public static String getLanguageCode(Locale locale) {
StringBuilder sb = new StringBuilder();
sb.append(locale.getLanguage());
if (locale.getCountry() != null && locale.getCountry().length() > 0) {
sb.append("-");
sb.append(locale.getCountry());
}
return sb.toString();
}

Related

In Java-8 Locale Object convert to old ISO in some Language code. How can i fix this issue without update Java version?

Like when i take input (he-IL) then output comes like "iw_IL". But i do not want this convert to old iso.
public static void main(String[] args) {
Locale locale = getLocaleIn("he-IL");
System.out.println(locale.toString());
}
private static Locale getLocaleIn(String langCode) {
LocaleCode code = LocaleCode.getByCodeIgnoreCase(langCode);
Locale locale = code.toLocale();
return locale;
}
OutPut:
iw_IL,
Expected Output:
he-IL
Main Problem in Here, In Java Locale.Class:
Finally I Want an Locale Object without Converting to old ISO.
You should avoid non-standard 3rd party classes in problem descriptions, especially when they do not contribute to the problem at all.
We can simply use
Locale locale = new Locale("he", "IL");
System.out.println(locale.toString());
locale = new Locale("iw", "IL");
System.out.println(locale.toString());
and get
iw_IL
iw_IL
under JDK 8, which is in line with the documentation:
This constructor accepts both the old codes ("iw", "ji", and "in") and the new codes ("he", "yi", and "id"), but all other API on Locale will return only the OLD codes.
This has changed with JDK 17:
Obsolete ISO 639 codes ("iw", "ji", and "in") are mapped to their current forms.
and running the same example program with JDK 17 accordingly now prints
he_IL
he_IL
So the cleanest and probably the only solution to your issue would be updating the Java version. Any patch forcing Locale to return the new code in older versions may cause compatibility problems with other components of the runtime relying on the old behavior.

Why does the NumberFormat returns blank fields?

So a few days ago I encountered a weird problem however, I didn't change any that kind of code. The problem is the format I'm getting from my method which I used for years. All commas are now spaces (blank fields) and I have no idea what is causing this.
public static String toFancyCost(int num) {
return NumberFormat.getInstance().format((Integer) num);
}
Before even this happened the String I received was looking like for example 2,181,273 and not like 2 181 273.
You must have changed your system locale by accident. The implementation of NumberFormat.getInstance() (on 1.8.0_131):
public final static NumberFormat getInstance() {
return getInstance(Locale.getDefault(Locale.Category.FORMAT), NUMBERSTYLE);
}
It uses formatting specified by the default locale. and the java docs on Locale.getDefault say:
The Java Virtual Machine sets the default locale during startup based
on the host environment. It is used by many locale-sensitive methods
if no locale is explicitly specified. It can be changed using the
setDefault method.
If you were to use NumberFormat.getInstance(Locale) you can specify which locale the NumberFormat should use.
Your systems default local is using a space as thousands separator, number format retured by getInstance() uses settings from system's default local.
As commented above, somehow the system default may have been modified. Let's stick the code to set the locale when formatting by using below to avoid any issues.
int number = 345678987;
NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.US);// Locale.US or any other locale you required
String numberAsString = numberFormat.format(number);
System.out.println(numberAsString);
response:
345,678,987
when I use the below for example with Locale.CANADA_FRENCH
int number = 345678987;
NumberFormat numberFormat = NumberFormat.getNumberInstance(Locale.CANADA_FRENCH);
String numberAsString = numberFormat.format(number);
System.out.println(numberAsString);
response:
345 678 987
So in your case also locale may have been causing issues, so please explictly set locale.

Java String.contains() not working on a cyrillic string

Here is what happens.
User types in "лос ан"
I have a bunch of products whose location is "лос анджелис"
if I do:
String userInput = "лос ан"
for(Product product : products) {
if(product.getCity().trim().toLowerCase().contains(userInput.trim().toLowerCase())) {
System.out.println("MATCH");
}
}
I don't get MATCH.
This works for Latin characters
try specifying Locale in toLowerCase() on both sides of the equation: http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#toLowerCase(java.util.Locale)
The editor and the compiler (javac -encoding) must use the same encoding.
The compiler encoding are done easily. The editor, source encoding, can be tested with a programmer's editor like NotePad++ or JEdit, which can switch encodings.
You can also u-escape the Java source text to check this:
String userInput = "\u043b\u043e\u0441 \u0430\u043d";
If that does not work, there is a discrepancy between the encodings.
Furthermore String.toLowerCase(new Locale("ru", "RU")) or such is already mentioned.
Using jdk 1.8.0_45, the following code gives a match in both cases:
System.out.println("лос анджелис".trim().toLowerCase().contains("лос ан".trim().toLowerCase()));
System.out.println("лос анджелис".trim().toLowerCase(Locale.ROOT).contains("лос ан".trim().toLowerCase(Locale.ROOT)));
As others already mentioned, you may look for a working Locale as argument to String#toLowerCase.

How to get iso2code from a country name by locale

I have a form that user enter a country name, then I have to convert it to iso2 or iso3 code.
How is it possible? I prefer not to use map, as it seems not running on my Android app.
This code is for converthing iso2 to an actual name, I want the other way around:
Locale l = new Locale("", "CH");
System.out.println(l.getDisplayCountry());
Have you tried Locale.getISO3Country() ?
To actually do the conversion, you might need to loop through all the available locales and look for the one whose getDisplayCountry() matches your input country name.
It doesn't sound efficient (but you said to not use maps), but you might try something like:
Locale convertCountryNameToIsoCode(String countryName)
for(Locale l : Locale.getAvailableLocales()) {
if (l.getDisplayCountry().equals(countryName)) {
return l;
}
}
return null;
}
http://docs.oracle.com/javase/7/docs/api/java/util/Locale.html#getISO3Country()
However, if the input comes from a web form, than it would be easier to set the country code directly as the web form input value. If the input comes from an Android native App, then I'm not sure but I'd bet you might a similar thing

How to validate & instantiate Java Locale from strings?

My app is being fed string from an external process, where each string is either 2- or 5-characters in length, and represents a java.util.Locales. For example:
en-us
ko
The first example is a 5-char string where "en" is the ISO language code, and "us" is the ISO country code. This should correspond to the "en_US" Locale. The second example is only a 2-char string, where "ko" is the ISO language code, and should correspond to the "ko_KR" (Korean) Locale.
I need a way to take these strings (either the 2- or 5-char variety), validate it (as a supported Java 6 Locale), and then create a Locale instance with it.
I would have hoped that Locale came with such validation out of the box, but unfortunately this code runs without exceptions being thrown:
Locale loc = new Locale("waawaaweewah", "greatsuccess");
// Prints: "waawaaweewah"
System.out.println(loc.getDisplayLanguage());
So I ask, given me the 2 forms that these string will be given to me in, how can I:
Validate the string (both forms) and throw an exception for strings corresponding to non-existent or unsupported Java 6 Locales; and
Instantiate a new Locale from the string? This question really applies to the 2-char form, where I might only have "ko" and need it to map to the "ko_KR" Locale, etc.
Thanks in advance!
Locale.getISOCountries() and Locale.getISOLanguages()
return a list of all 2-letter country and language codes defined in ISO 3166 and ISO 639 respectively and can be used to create Locales.
You can use this to validate your inputs.
You have two options,
Use a library for doing this commons-lang has the LocaleUtils class that has a method that can parse a String to a Locale.
While your own method, the validation here is non trivial as there are a number of different sets of country codes that a valid for a Locale - see the javadoc
A starting point would be to split the String and switch on the number of elements:
public static Locale parseLocale(final String locale) {
final String[] localeArr = locale.split("_");
switch (localeArr.length) {
case 1:
return new Locale(localeArr[0]);
case 2:
return new Locale(localeArr[0], localeArr[1]);
case 3:
return new Locale(localeArr[0], localeArr[1], localeArr[2]);
default:
throw new IllegalArgumentException("Invalid locale format;");
}
}
Presumably you would need to get lists of all valid country codes and languages and compare the elements in the String[] to the valid values before calling the constructor.

Categories

Resources