In Java is there a way to create a Locale.LanguageRange from a Locale?
At the moment I do this:
List<LanguageRange> ranges =
Locale.LanguageRange.parse(
locale.toString() // locale.toString() gives en_GB
.replace('_', '-') // parse() needs en-GB
+ ";q=1.0"); // weight
It feels dirty and very inelegant.
Is there a better or even standard way to do so? I wasn't able to find one.
Minimal working example:
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Locale.LanguageRange;
public class LanguageUtil {
public static Locale getClosestMatch(Locale locale, Locale defaultLocale, Collection<Locale> allowedLanguages) {
List<LanguageRange> ranges = Locale.LanguageRange.parse(
locale.toString().replace('_', '-') + ";q=1.0," + //exact match e.g. en-GB -> en-GB
locale.getLanguage() + ";q=0.5," + //close match e.g. en-US -> en-GB
defaultLocale.toString().replace('_', '-') + ";q=0.0")); //default match e.g. fr-FR -> en-GB
return Locale.filter(ranges, allowedLanguages).get(0);
}
}
I use new LanguageRange(locale.toLanguageTag())
to derive a LanguageRange
from a Locale
which takes care of the syntax.
However by feeding this to Locale.lookup()
the matching is to restrictive (it would not return en_GB
for en
).
I therefore ended up with a two-step mechanism:
filter
all system locales by the requested localeslookup
the best match from result list of step 1 against the supported localesSource code:
List<Locale> allAvailableLocales = Arrays.asList(Locale.getAvailableLocales());
private Locale findBestMatch(final List<Locale> requested, final List<Locale> supported) {
final List<LanguageRange> languageRanges = toLanguageRanges(requested);
final List<Locale> allMatches = Locale.filter(languageRanges, allAvailableLocales);
final Locale bestMatch = Locale.lookup(toLanguageRanges(allMatches), supported);
return bestMatch;
}
private static List<LanguageRange> toLanguageRanges(final List<Locale> locales) {
final ArrayList<LanguageRange> languageRanges = new ArrayList<>();
for (final Locale locale : locales) {
languageRanges.add(toLanguageRange(locale));
}
return languageRanges;
}
private static LanguageRange toLanguageRange(final Locale locale) {
return new LanguageRange(locale.toLanguageTag());
}
Note: consider a default in case findBestMatch
returns null
.
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