从Java中的Locale创建Locale.LanguageRange的标准方法

时间:2017-01-24 09:13:46

标签: java localization java-8

在Java中有没有办法从Locale创建Locale.LanguageRange?

目前我这样做:

List<LanguageRange> ranges = 
        Locale.LanguageRange.parse(
                locale.toString()  // locale.toString() gives en_GB
                .replace('_', '-') // parse() needs en-GB
                + ";q=1.0");       // weight

感觉很脏而且非常不优雅。

有更好的甚至是标准的方法吗?我找不到一个。

最小的工作示例:

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);
        }
    }

1 个答案:

答案 0 :(得分:2)

我使用new LanguageRange(locale.toLanguageTag())LanguageRange派生Locale来处理语法。

但是,通过将其提供给Locale.lookup(),匹配是限制性的(en_GB不会返回en

因此,我最终采用了两步机制:

  1. filter请求的区域设置的所有系统区域设置
  2. lookup第1步结果列表与支持的区域设置的最佳匹配
  3. 源代码:

    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());
    }
    

    注意:如果findBestMatch返回null,请考虑默认值。