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?
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é.
Pour mémoire, il est maintenant possible avec Java 8 :
Locale.LanguageRange.parse()
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.
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 ;
}
}
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;
Locale.forLanguageTag("en-ca,en;q=0.8,en-us;q=0.6,de-de;q=0.4,de;q=0.2")