Merge pull request #4958 from iilei/missing_accept_language_country_code_fallback

Fix Locale Negotiation for omitted Country Code
This commit is contained in:
Stian Thorgersen 2018-02-08 20:55:19 +01:00 committed by GitHub
commit d63040283f
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 102 additions and 21 deletions

View file

@ -134,27 +134,7 @@ public class LocaleHelper {
} }
private static Locale findLocale(Set<String> supportedLocales, String... localeStrings) { private static Locale findLocale(Set<String> supportedLocales, String... localeStrings) {
for (String localeString : localeStrings) { return new LocaleNegotiator(supportedLocales).invoke(localeStrings);
if (localeString != null) {
Locale result = null;
Locale search = Locale.forLanguageTag(localeString);
for (String languageTag : supportedLocales) {
Locale locale = Locale.forLanguageTag(languageTag);
if (locale.getLanguage().equals(search.getLanguage())) {
if (locale.getCountry().equals("") && result == null) {
result = locale;
}
if (locale.getCountry().equals(search.getCountry())) {
return locale;
}
}
}
if (result != null) {
return result;
}
}
}
return null;
} }
private static void updateUsersLocale(UserModel user, String locale) { private static void updateUsersLocale(UserModel user, String locale) {

View file

@ -0,0 +1,52 @@
/*
* Copyright 2016 Red Hat, Inc. and/or its affiliates
* and other contributors as indicated by the @author tags.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.keycloak.services.util;
import java.util.Locale;
import java.util.Set;
class LocaleNegotiator {
private Set<String> supportedLocales;
LocaleNegotiator(Set<String> supportedLocales) {
this.supportedLocales = supportedLocales;
}
Locale invoke(String... localeStrings) {
for (String localeString : localeStrings) {
if (localeString != null) {
Locale result = null;
Locale search = Locale.forLanguageTag(localeString);
for (String languageTag : supportedLocales) {
Locale locale = Locale.forLanguageTag(languageTag);
if (locale.getLanguage().equals(search.getLanguage())) {
if (search.getCountry().equals("") ^ locale.getCountry().equals("") && result == null) {
result = locale;
}
if (locale.getCountry().equals(search.getCountry())) {
return locale;
}
}
}
if (result != null) {
return result;
}
}
}
return null;
}
}

View file

@ -0,0 +1,49 @@
package org.keycloak.services.util;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import java.util.HashSet;
import java.util.Locale;
import java.util.Set;
public class LocaleNegotiatorTest {
private LocaleNegotiator localeNegotiator;
@Before
public void setUp() {
Set<String> supportedLocales = new HashSet<>();
supportedLocales.add("de");
supportedLocales.add("de-AT");
supportedLocales.add("de-CH");
supportedLocales.add("de-DE");
supportedLocales.add("pt-BR");
localeNegotiator = new LocaleNegotiator(supportedLocales);
}
@Test
public void shouldMatchWithoutCountryCode() {
Locale actualLocale = localeNegotiator.invoke("de");
Assert.assertEquals(Locale.GERMAN, actualLocale);
}
@Test
public void shouldMatchWithPriorityCountryCode() {
Locale actualLocale = localeNegotiator.invoke("de-CH", "de");
Assert.assertEquals(new Locale("de", "CH"), actualLocale);
}
@Test
public void shouldMatchWithPriorityNoCountryCode() {
Locale actualLocale = localeNegotiator.invoke("de", "de-CH");
Assert.assertEquals(new Locale("de"), actualLocale);
}
@Test
public void shouldMatchOmittedCountryCodeWithBestFit() {
Locale actualLocale = localeNegotiator.invoke("pt", "es-ES");
Assert.assertEquals(new Locale("pt", "BR"), actualLocale);
}
}