diff --git a/services/src/main/java/org/keycloak/email/freemarker/FreeMarkerEmailTemplateProvider.java b/services/src/main/java/org/keycloak/email/freemarker/FreeMarkerEmailTemplateProvider.java index ccfc12d8a6..7bbf3f2485 100755 --- a/services/src/main/java/org/keycloak/email/freemarker/FreeMarkerEmailTemplateProvider.java +++ b/services/src/main/java/org/keycloak/email/freemarker/FreeMarkerEmailTemplateProvider.java @@ -207,9 +207,9 @@ public class FreeMarkerEmailTemplateProvider implements EmailTemplateProvider { Theme theme = getTheme(); Locale locale = session.getContext().resolveLocale(user); attributes.put("locale", locale); - Properties rb = theme.getMessages(locale); - Map localizationTexts = realm.getRealmLocalizationTextsByLocale(locale.toLanguageTag()); - rb.putAll(localizationTexts); + Properties rb = new Properties(); + rb.putAll(theme.getMessages(locale)); + rb.putAll(realm.getRealmLocalizationTextsByLocale(locale.toLanguageTag())); attributes.put("msg", new MessageFormatterMethod(locale, rb)); attributes.put("properties", theme.getProperties()); String subject = new MessageFormat(rb.getProperty(subjectKey, subjectKey), locale).format(subjectAttributes.toArray()); diff --git a/services/src/main/java/org/keycloak/forms/account/freemarker/FreeMarkerAccountProvider.java b/services/src/main/java/org/keycloak/forms/account/freemarker/FreeMarkerAccountProvider.java index 87c71caa02..fd916084f6 100755 --- a/services/src/main/java/org/keycloak/forms/account/freemarker/FreeMarkerAccountProvider.java +++ b/services/src/main/java/org/keycloak/forms/account/freemarker/FreeMarkerAccountProvider.java @@ -129,8 +129,6 @@ public class FreeMarkerAccountProvider implements AccountProvider { Locale locale = session.getContext().resolveLocale(user); Properties messagesBundle = handleThemeResources(theme, locale, attributes); - Map localizationTexts = realm.getRealmLocalizationTextsByLocale(locale.toLanguageTag()); - messagesBundle.putAll(localizationTexts); URI baseUri = uriInfo.getBaseUri(); UriBuilder baseUriBuilder = uriInfo.getBaseUriBuilder(); @@ -217,9 +215,10 @@ public class FreeMarkerAccountProvider implements AccountProvider { * @return message bundle for other use */ protected Properties handleThemeResources(Theme theme, Locale locale, Map attributes) { - Properties messagesBundle; + Properties messagesBundle = new Properties(); try { - messagesBundle = theme.getMessages(locale); + messagesBundle.putAll(theme.getMessages(locale)); + messagesBundle.putAll(realm.getRealmLocalizationTextsByLocale(locale.toLanguageTag())); attributes.put("msg", new MessageFormatterMethod(locale, messagesBundle)); } catch (IOException e) { logger.warn("Failed to load messages", e); diff --git a/services/src/main/java/org/keycloak/forms/login/freemarker/FreeMarkerLoginFormsProvider.java b/services/src/main/java/org/keycloak/forms/login/freemarker/FreeMarkerLoginFormsProvider.java index e8cda84aab..fe056214c6 100755 --- a/services/src/main/java/org/keycloak/forms/login/freemarker/FreeMarkerLoginFormsProvider.java +++ b/services/src/main/java/org/keycloak/forms/login/freemarker/FreeMarkerLoginFormsProvider.java @@ -198,8 +198,6 @@ public class FreeMarkerLoginFormsProvider implements LoginFormsProvider { Locale locale = session.getContext().resolveLocale(user); Properties messagesBundle = handleThemeResources(theme, locale); - Map localizationTexts = realm.getRealmLocalizationTextsByLocale(locale.toLanguageTag()); - messagesBundle.putAll(localizationTexts); handleMessages(locale, messagesBundle); @@ -288,8 +286,6 @@ public class FreeMarkerLoginFormsProvider implements LoginFormsProvider { Locale locale = session.getContext().resolveLocale(user); Properties messagesBundle = handleThemeResources(theme, locale); - Map localizationTexts = realm.getRealmLocalizationTextsByLocale(locale.getCountry()); - messagesBundle.putAll(localizationTexts); handleMessages(locale, messagesBundle); @@ -339,9 +335,10 @@ public class FreeMarkerLoginFormsProvider implements LoginFormsProvider { * @return message bundle for other use */ protected Properties handleThemeResources(Theme theme, Locale locale) { - Properties messagesBundle; + Properties messagesBundle = new Properties(); try { - messagesBundle = theme.getMessages(locale); + messagesBundle.putAll(theme.getMessages(locale)); + messagesBundle.putAll(realm.getRealmLocalizationTextsByLocale(locale.toLanguageTag())); attributes.put("msg", new MessageFormatterMethod(locale, messagesBundle)); attributes.put("advancedMsg", new AdvancedMessageFormatterMethod(locale, messagesBundle)); } catch (IOException e) { diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminMessageFormatter.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminMessageFormatter.java index d375df18d0..c4b4718b29 100644 --- a/services/src/main/java/org/keycloak/services/resources/admin/AdminMessageFormatter.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminMessageFormatter.java @@ -48,10 +48,10 @@ public class AdminMessageFormatter implements BiFunction localizationTexts = realm.getRealmLocalizationTextsByLocale(locale.toLanguageTag()); - messages.putAll(localizationTexts); + messages.putAll(realm.getRealmLocalizationTextsByLocale(locale.toLanguageTag())); } catch (IOException cause) { throw new RuntimeException("Failed to configure error messages", cause); } diff --git a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/i18n/LoginPageTest.java b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/i18n/LoginPageTest.java index 928ca340f0..d96e8d5f4b 100755 --- a/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/i18n/LoginPageTest.java +++ b/testsuite/integration-arquillian/tests/base/src/test/java/org/keycloak/testsuite/i18n/LoginPageTest.java @@ -16,9 +16,12 @@ */ package org.keycloak.testsuite.i18n; +import java.io.IOException; import java.util.Arrays; +import java.util.Locale; import org.apache.http.impl.client.CloseableHttpClient; +import org.hamcrest.Matchers; import org.jboss.resteasy.client.jaxrs.ResteasyClient; import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder; import org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine; @@ -44,6 +47,8 @@ import org.keycloak.testsuite.pages.OAuthGrantPage; import org.keycloak.testsuite.util.IdentityProviderBuilder; import org.openqa.selenium.Cookie; +import static org.hamcrest.MatcherAssert.assertThat; + /** * @author Michael Gerber * @author Stan Silvert ssilvert@redhat.com (C) 2016 Red Hat Inc. @@ -117,21 +122,25 @@ public class LoginPageTest extends AbstractI18NTest { } @Test - public void acceptLanguageHeader() { + public void acceptLanguageHeader() throws IOException { ProfileAssume.assumeCommunity(); - CloseableHttpClient httpClient = (CloseableHttpClient) new HttpClientBuilder().build(); - ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient); - ResteasyClient client = new ResteasyClientBuilder().httpEngine(engine).build(); + try(CloseableHttpClient httpClient = (CloseableHttpClient) new HttpClientBuilder().build()) { + ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient); + ResteasyClient client = new ResteasyClientBuilder().httpEngine(engine).build(); - loginPage.open(); - Response response = client.target(driver.getCurrentUrl()).request().acceptLanguage("de").get(); - Assert.assertTrue(response.readEntity(String.class).contains("Anmeldung bei test")); + loginPage.open(); - response = client.target(driver.getCurrentUrl()).request().acceptLanguage("en").get(); - Assert.assertTrue(response.readEntity(String.class).contains("Sign in to test")); + try(Response responseDe = client.target(driver.getCurrentUrl()).request().acceptLanguage("de").get()) { + Assert.assertTrue(responseDe.readEntity(String.class).contains("Anmeldung bei test")); - client.close(); + try(Response responseEn = client.target(driver.getCurrentUrl()).request().acceptLanguage("en").get()) { + Assert.assertTrue(responseEn.readEntity(String.class).contains("Sign in to test")); + } + } + + client.close(); + } } @Test @@ -242,6 +251,45 @@ public class LoginPageTest extends AbstractI18NTest { Assert.assertNull(localeCookie); } + // KEYCLOAK-18590 + @Test + public void realmLocalizationMessagesAreNotCachedWithinTheTheme() throws IOException { + final String locale = Locale.ENGLISH.toLanguageTag(); + + final String realmLocalizationMessageKey = "loginAccountTitle"; + final String realmLocalizationMessageValue = "Localization Test"; + + try(CloseableHttpClient httpClient = (CloseableHttpClient) new HttpClientBuilder().build()) { + ApacheHttpClient4Engine engine = new ApacheHttpClient4Engine(httpClient); + + testRealm().localization().saveRealmLocalizationText(locale, realmLocalizationMessageKey, + realmLocalizationMessageValue); + + ResteasyClient client = new ResteasyClientBuilder().httpEngine(engine).build(); + + loginPage.open(); + + try(Response responseWithLocalization = + client.target(driver.getCurrentUrl()).request().acceptLanguage(locale).get()) { + + assertThat(responseWithLocalization.readEntity(String.class), + Matchers.containsString(realmLocalizationMessageValue)); + + testRealm().localization().deleteRealmLocalizationText(locale, realmLocalizationMessageKey); + + loginPage.open(); + + try(Response responseWithoutLocalization = + client.target(driver.getCurrentUrl()).request().acceptLanguage(locale).get()) { + + assertThat(responseWithoutLocalization.readEntity(String.class), + Matchers.not(Matchers.containsString(realmLocalizationMessageValue))); + } + } + + client.close(); + } + } private void switchLanguageToGermanAndBack(String expectedEnglishMessage, String expectedGermanMessage, LanguageComboboxAwarePage page) { // Switch language to Deutsch