From 6e1cac9145385c9b9dbcefbeec46b1a86985bc19 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Wed, 28 Mar 2018 01:21:36 +0200 Subject: [PATCH] AcceptHeaderLocaleResolver keeps language match among supported locales Issue: SPR-16599 --- .../i18n/AcceptHeaderLocaleResolver.java | 24 +++++++++---------- .../i18n/AcceptHeaderLocaleResolverTests.java | 16 +++++++++++-- 2 files changed, 25 insertions(+), 15 deletions(-) diff --git a/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/AcceptHeaderLocaleResolver.java b/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/AcceptHeaderLocaleResolver.java index 9984b65b80..1755549171 100644 --- a/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/AcceptHeaderLocaleResolver.java +++ b/spring-webmvc/src/main/java/org/springframework/web/servlet/i18n/AcceptHeaderLocaleResolver.java @@ -97,37 +97,35 @@ public class AcceptHeaderLocaleResolver implements LocaleResolver { return defaultLocale; } Locale requestLocale = request.getLocale(); - if (isSupportedLocale(requestLocale)) { + List supportedLocales = getSupportedLocales(); + if (supportedLocales.isEmpty() || supportedLocales.contains(requestLocale)) { return requestLocale; } - Locale supportedLocale = findSupportedLocale(request); + Locale supportedLocale = findSupportedLocale(request, supportedLocales); if (supportedLocale != null) { return supportedLocale; } return (defaultLocale != null ? defaultLocale : requestLocale); } - private boolean isSupportedLocale(Locale locale) { - List supportedLocales = getSupportedLocales(); - return (supportedLocales.isEmpty() || supportedLocales.contains(locale)); - } - - private Locale findSupportedLocale(HttpServletRequest request) { + private Locale findSupportedLocale(HttpServletRequest request, List supportedLocales) { Enumeration requestLocales = request.getLocales(); - List supported = getSupportedLocales(); Locale languageMatch = null; while (requestLocales.hasMoreElements()) { Locale locale = requestLocales.nextElement(); - if (supported.contains(locale)) { - // Full match: typically language + country - return locale; + if (supportedLocales.contains(locale)) { + if (languageMatch == null || languageMatch.getLanguage().equals(locale.getLanguage())) { + // Full match: language + country, possibly narrowed from earlier language-only match + return locale; + } } else if (languageMatch == null) { // Let's try to find a language-only match as a fallback - for (Locale candidate : supported) { + for (Locale candidate : supportedLocales) { if (!StringUtils.hasLength(candidate.getCountry()) && candidate.getLanguage().equals(locale.getLanguage())) { languageMatch = candidate; + break; } } } diff --git a/spring-webmvc/src/test/java/org/springframework/web/servlet/i18n/AcceptHeaderLocaleResolverTests.java b/spring-webmvc/src/test/java/org/springframework/web/servlet/i18n/AcceptHeaderLocaleResolverTests.java index 0ed502a573..4e5f2708f7 100644 --- a/spring-webmvc/src/test/java/org/springframework/web/servlet/i18n/AcceptHeaderLocaleResolverTests.java +++ b/spring-webmvc/src/test/java/org/springframework/web/servlet/i18n/AcceptHeaderLocaleResolverTests.java @@ -63,13 +63,25 @@ public class AcceptHeaderLocaleResolverTests { assertEquals(ENGLISH, this.resolver.resolveLocale(request(GERMANY, US, UK))); } + @Test + public void resolvePreferredAgainstCountryIfPossible() { + this.resolver.setSupportedLocales(Arrays.asList(ENGLISH, UK)); + assertEquals(UK, this.resolver.resolveLocale(request(GERMANY, US, UK))); + } + + @Test + public void resolvePreferredAgainstLanguageWithMultipleSupportedLocales() { + this.resolver.setSupportedLocales(Arrays.asList(GERMAN, US)); + assertEquals(GERMAN, this.resolver.resolveLocale(request(GERMANY, US, UK))); + } + @Test public void resolvePreferredNotSupportedWithDefault() { this.resolver.setSupportedLocales(Arrays.asList(US, JAPAN)); this.resolver.setDefaultLocale(Locale.JAPAN); MockHttpServletRequest request = new MockHttpServletRequest(); - request.addHeader("Accept-Language", KOREA.toString()); + request.addHeader("Accept-Language", KOREA.toLanguageTag()); request.setPreferredLocales(Collections.singletonList(KOREA)); assertEquals(Locale.JAPAN, this.resolver.resolveLocale(request)); } @@ -80,7 +92,7 @@ public class AcceptHeaderLocaleResolverTests { MockHttpServletRequest request = new MockHttpServletRequest(); assertEquals(JAPANESE, this.resolver.resolveLocale(request)); - request.addHeader("Accept-Language", US.toString()); + request.addHeader("Accept-Language", US.toLanguageTag()); request.setPreferredLocales(Collections.singletonList(US)); assertEquals(US, this.resolver.resolveLocale(request)); }