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 7165f2b6c7c7..186271c3be3a 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 @@ -140,6 +140,8 @@ public class FreeMarkerLoginFormsProvider implements LoginFormsProvider { protected UserModel user; + protected String lang; + protected final Map attributes = new HashMap<>(); private Function, Map> attributeMapper; @@ -150,6 +152,7 @@ public FreeMarkerLoginFormsProvider(KeycloakSession session) { this.realm = session.getContext().getRealm(); this.client = session.getContext().getClient(); this.uriInfo = session.getContext().getUri(); + this.lang = Locale.ENGLISH.toLanguageTag(); } @SuppressWarnings("unchecked") @@ -544,7 +547,10 @@ protected void createCommonAttributes(Theme theme, Locale locale, Properties mes b.queryParam(Constants.KEY, authenticationSession.getAuthNote(Constants.KEY)); } - attributes.put("locale", new LocaleBean(realm, locale, b, messagesBundle)); + final var localeBean = new LocaleBean(realm, locale, b, messagesBundle); + attributes.put("locale", localeBean); + + lang = localeBean.getCurrentLanguageTag(); } if (Profile.isFeatureEnabled(Feature.ORGANIZATION)) { @@ -564,6 +570,8 @@ protected void createCommonAttributes(Theme theme, Locale locale, Properties mes && !Boolean.TRUE.toString().equals(authenticationSession.getClientNote(Constants.KC_ACTION_ENFORCED))) { attributes.put("isAppInitiatedAction", true); } + + attributes.put("lang", lang); } /** @@ -601,8 +609,6 @@ public Response createLoginUsername() { return createResponse(LoginFormsPages.LOGIN_USERNAME); } - ; - public Response createLoginPassword() { return createResponse(LoginFormsPages.LOGIN_PASSWORD); } diff --git a/services/src/main/java/org/keycloak/services/error/KeycloakErrorHandler.java b/services/src/main/java/org/keycloak/services/error/KeycloakErrorHandler.java index 960b5d44a9a5..6f255687360f 100644 --- a/services/src/main/java/org/keycloak/services/error/KeycloakErrorHandler.java +++ b/services/src/main/java/org/keycloak/services/error/KeycloakErrorHandler.java @@ -184,12 +184,15 @@ private static Map initAttributes(KeycloakSession session, Realm Map attributes = new HashMap<>(); Properties messagesBundle = theme.getMessages(locale); + final var localeBean = new LocaleBean(realm, locale, session.getContext().getUri().getRequestUriBuilder(), messagesBundle); + final var lang = realm.isInternationalizationEnabled() ? localeBean.getCurrentLanguageTag() : Locale.ENGLISH.toLanguageTag(); + attributes.put("statusCode", responseStatus.getStatusCode()); attributes.put("realm", realm); attributes.put("url", new UrlBean(realm, theme, session.getContext().getUri().getBaseUri(), null)); - attributes.put("locale", new LocaleBean(realm, locale, session.getContext().getUri().getRequestUriBuilder(), messagesBundle)); - + attributes.put("locale", localeBean); + attributes.put("lang", lang); String errorKey = responseStatus == Response.Status.NOT_FOUND ? Messages.PAGE_NOT_FOUND : Messages.INTERNAL_SERVER_ERROR; String errorMessage = messagesBundle.getProperty(errorKey); 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 0965cdbc0586..27ef2ca7c947 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 @@ -24,6 +24,7 @@ import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder; import org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient43Engine; import org.junit.Assert; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.keycloak.OAuth2Constants; @@ -83,6 +84,11 @@ public class LoginPageTest extends AbstractI18NTest { @Rule public AssertEvents events = new AssertEvents(this); + @Before + public void before() { + setRealmInternationalization(true); + } + @Override public void configureTestRealm(RealmRepresentation testRealm) { testRealm.addIdentityProvider(IdentityProviderBuilder.create() @@ -135,7 +141,7 @@ public void uiLocalesParameter() { } @Test - public void htmlLangAttribute() { + public void htmlLangAttributeWithInternationalizationEnabled() { loginPage.open(); assertEquals("en", loginPage.getHtmlLanguage()); @@ -144,6 +150,14 @@ public void htmlLangAttribute() { assertEquals("de", loginPage.getHtmlLanguage()); } + @Test + public void htmlLangAttributeWithInternationalizationDisabled() { + setRealmInternationalization(false); + + loginPage.open(); + assertEquals("en", loginPage.getHtmlLanguage()); + } + @Test public void acceptLanguageHeader() throws IOException { try(CloseableHttpClient httpClient = HttpClientBuilder.create().build()) { @@ -381,4 +395,11 @@ private void switchLanguageToGermanAndBack(String expectedEnglishMessage, String assertThat(pageSource, containsString(expectedEnglishMessage)); assertThat(pageSource, not(containsString(expectedGermanMessage))); } + + private void setRealmInternationalization(final boolean enabled) { + final var realmResource = testRealm(); + RealmRepresentation realm = realmResource.toRepresentation(); + realm.setInternationalizationEnabled(enabled); + realmResource.update(realm); + } } diff --git a/themes/src/main/resources/theme/base/login/template.ftl b/themes/src/main/resources/theme/base/login/template.ftl index 81dddbd592fb..7a277b39534b 100644 --- a/themes/src/main/resources/theme/base/login/template.ftl +++ b/themes/src/main/resources/theme/base/login/template.ftl @@ -1,7 +1,7 @@ <#import "footer.ftl" as loginFooter> <#macro registrationLayout bodyClass="" displayInfo=false displayMessage=true displayRequiredFields=false> - lang="${locale.currentLanguageTag}" dir="${(locale.rtl)?then('rtl','ltr')}"> + dir="${(locale.rtl)?then('rtl','ltr')}"> diff --git a/themes/src/main/resources/theme/keycloak.v2/login/template.ftl b/themes/src/main/resources/theme/keycloak.v2/login/template.ftl index a4986a7bc053..7f8eb24a6079 100644 --- a/themes/src/main/resources/theme/keycloak.v2/login/template.ftl +++ b/themes/src/main/resources/theme/keycloak.v2/login/template.ftl @@ -23,7 +23,7 @@ <#macro registrationLayout bodyClass="" displayInfo=false displayMessage=true displayRequiredFields=false> - lang="${locale.currentLanguageTag}" dir="${(locale.rtl)?then('rtl','ltr')}"> + dir="${(locale.rtl)?then('rtl','ltr')}">