web-dev-qa-db-fra.com

Parse en-tête Accept-Language en Java

L'en-tête accept-language de la requête est généralement une longue chaîne complexe -

Par exemple. 

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

Existe-t-il un moyen simple de l’analyser en java? Ou une API pour m'aider à le faire?

33
Pushkar

Je suggérerais d'utiliser ServletRequest.getLocales() pour permettre au conteneur d'analyser Accept-Language plutôt que d'essayer de gérer vous-même la complexité.

40
Brett Kail

Pour mémoire, il est maintenant possible avec Java 8 :

Locale.LanguageRange.parse()
32
Qiang Li

Voici une autre manière d’analyser l’en-tête Accept-Language qui ne nécessite pas de conteneur de servlet:

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

Vous pouvez trouver une explication de l'en-tête Accept-Language et des valeurs q associées ici:

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

Un grand merci à Karl Knechtel et Mike Samuel. Leurs commentaires sur la question initiale m'ont aidé à aller dans la bonne direction.

15
Peter

Nous utilisons Spring Boot et Java 8. Cela fonctionne.

Dans ApplicationConfig.Java, écrivez ceci

@Bean

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

et j'ai cette liste dans ma classe de constantes qui a des langues que nous soutenons

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

et écrivez la logique dans la classe ci-dessous.

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 ;
        }
}
3
Arun

ServletRequest.getLocale() est certainement la meilleure option si elle est disponible et non écrasée comme le font certains frameworks. 

Pour tous les autres cas, Java 8 offre Locale.LanguageRange.parse() comme mentionné précédemment par Quiang Li. Cependant, cela ne fait que restituer une chaîne de langue, pas une locale. Pour analyser les chaînes de langage, vous pouvez utiliser Locale.forLanguageTag() (disponible depuis 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;
3
tec
Locale.forLanguageTag("en-ca,en;q=0.8,en-us;q=0.6,de-de;q=0.4,de;q=0.2")
0
mokshino