Parse Accept-Language header in Java

后端 未结 7 710
孤城傲影
孤城傲影 2020-12-15 02:54

The accept-language header in request is usually a long complex string -

Eg.

Accept-Language : en-ca,en;q=0.8,en-us;q=0.6,de-de;q=0.4,de;q=0.2


        
相关标签:
7条回答
  • 2020-12-15 03:19

    We are using Spring boot and Java 8. This works

    In ApplicationConfig.java write this

    @Bean
    
    public LocaleResolver localeResolver() {
        return new SmartLocaleResolver();
    }
    

    and I have this list in my constants class that has languages that we support

    List<Locale> locales = Arrays.asList(new Locale("en"),
                                             new Locale("es"),
                                             new Locale("fr"),
                                             new Locale("es", "MX"),
                                             new Locale("zh"),
                                             new Locale("ja"));
    

    and write the logic in the below class.

    public class SmartLocaleResolver extends AcceptHeaderLocaleResolver {
              @Override
             public Locale resolveLocale(HttpServletRequest request) {
                if (StringUtils.isBlank(request.getHeader("Accept-Language"))) {
                return Locale.getDefault();
                }
                List<Locale.LanguageRange> ranges = Locale.LanguageRange.parse("da,es-MX;q=0.8");
                Locale locale = Locale.lookup(ranges, locales);
                return locale ;
            }
    }
    
    0 讨论(0)
  • 2020-12-15 03:25

    Here's an alternative way to parse the Accept-Language header which doesn't require a servlet container:

    String header = "en-ca,en;q=0.8,en-us;q=0.6,de-de;q=0.4,de;q=0.2";
    for (String str : header.split(",")){
        String[] arr = str.trim().replace("-", "_").split(";");
    
      //Parse the locale
        Locale locale = null;
        String[] l = arr[0].split("_");
        switch(l.length){
            case 2: locale = new Locale(l[0], l[1]); break;
            case 3: locale = new Locale(l[0], l[1], l[2]); break;
            default: locale = new Locale(l[0]); break;
        }
    
      //Parse the q-value
        Double q = 1.0D;
        for (String s : arr){
            s = s.trim();
            if (s.startsWith("q=")){
                q = Double.parseDouble(s.substring(2).trim());
                break;
            }
        }
    
      //Print the Locale and associated q-value
        System.out.println(q + " - " + arr[0] + "\t " + locale.getDisplayLanguage());
    }
    

    You can find an explanation of the Accept-Language header and associated q-values here:

    http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html

    Many thanks to Karl Knechtel and Mike Samuel. Thier comments to the original question helped point me in the right direction.

    0 讨论(0)
  • 2020-12-15 03:27

    For the record, now it is possible with Java 8:

    Locale.LanguageRange.parse()
    
    0 讨论(0)
  • 2020-12-15 03:30

    ServletRequest.getLocale() is certainly the best option if it is available and not overwritten as some frameworks do.

    For all other cases Java 8 offers Locale.LanguageRange.parse() as previously mentioned by Quiang Li. This however only gives back a Language String, not a Locale. To parse the language strings you can use Locale.forLanguageTag() (available since Java 7):

        final List<Locale> acceptedLocales = new ArrayList<>();
        final String userLocale = request.getHeader("Accept-Language");
        if (userLocale != null) {
            final List<LanguageRange> ranges = Locale.LanguageRange.parse(userLocale);
    
            if (ranges != null) {
                ranges.forEach(languageRange -> {
                    final String localeString = languageRange.getRange();
                    final Locale locale = Locale.forLanguageTag(localeString);
                    acceptedLocales.add(locale);
                });
            }
        }
        return acceptedLocales;
    
    0 讨论(0)
  • 2020-12-15 03:40
    Locale.forLanguageTag("en-ca,en;q=0.8,en-us;q=0.6,de-de;q=0.4,de;q=0.2")
    
    0 讨论(0)
  • 2020-12-15 03:42

    I would suggest using ServletRequest.getLocales() to let the container parse Accept-Language rather than trying to manage the complexity yourself.

    0 讨论(0)
提交回复
热议问题