Merge pull request #4958 from iilei/missing_accept_language_country_code_fallback
Fix Locale Negotiation for omitted Country Code
This commit is contained in:
commit
d63040283f
3 changed files with 102 additions and 21 deletions
|
@ -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) {
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue