diff --git a/docbook/reference/en/en-US/modules/themes.xml b/docbook/reference/en/en-US/modules/themes.xml index cd59f382ad..10b2417a46 100755 --- a/docbook/reference/en/en-US/modules/themes.xml +++ b/docbook/reference/en/en-US/modules/themes.xml @@ -181,6 +181,12 @@ import=common/keycloak messages/messages.properties inside your theme folder and add the following content: username=Your Username + + For the admin console, there is a second resource bundle named admin-messages.properties. + This resource bundle is converted to JSON and shipped to the console to be processed by + angular-translate. It is found in the same directory as messages.properties and can be overridden + in the same way as described above. +
Modifying HTML diff --git a/forms/common-themes/src/main/resources/theme/base/admin/angular-messages/common_de.properties b/forms/common-themes/src/main/resources/theme/base/admin/angular-messages/common_de.properties deleted file mode 100644 index 2ad35ba6d2..0000000000 --- a/forms/common-themes/src/main/resources/theme/base/admin/angular-messages/common_de.properties +++ /dev/null @@ -1,6 +0,0 @@ -enabled=de Enabled -name=de Name -save=de Save -cancel=de Cancel -onText=AN -offText=AUS \ No newline at end of file diff --git a/forms/common-themes/src/main/resources/theme/base/admin/angular-messages/common_en.properties b/forms/common-themes/src/main/resources/theme/base/admin/angular-messages/common_en.properties deleted file mode 100644 index 7b6c509091..0000000000 --- a/forms/common-themes/src/main/resources/theme/base/admin/angular-messages/common_en.properties +++ /dev/null @@ -1,6 +0,0 @@ -enabled=Enabled -name=Name -save=Save -cancel=Cancel -onText=ON -offText=OFF \ No newline at end of file diff --git a/forms/common-themes/src/main/resources/theme/base/admin/angular-messages/realm-settings_de.properties b/forms/common-themes/src/main/resources/theme/base/admin/messages/admin-messages_de.properties similarity index 92% rename from forms/common-themes/src/main/resources/theme/base/admin/angular-messages/realm-settings_de.properties rename to forms/common-themes/src/main/resources/theme/base/admin/messages/admin-messages_de.properties index 2643771c26..7721290988 100644 --- a/forms/common-themes/src/main/resources/theme/base/admin/angular-messages/realm-settings_de.properties +++ b/forms/common-themes/src/main/resources/theme/base/admin/messages/admin-messages_de.properties @@ -1,3 +1,12 @@ +# Common messages +enabled=de Enabled +name=de Name +save=de Save +cancel=de Cancel +onText=AN +offText=AUS + +# Realm settings realm-detail.enabled.tooltip=de Users and clients can only access a realm if it's enabled registrationAllowed=de User registration registrationAllowed.tooltip=de Enable/disable the registration page. A link for registration will show on login page too. diff --git a/forms/common-themes/src/main/resources/theme/base/admin/angular-messages/realm-settings_en.properties b/forms/common-themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties similarity index 92% rename from forms/common-themes/src/main/resources/theme/base/admin/angular-messages/realm-settings_en.properties rename to forms/common-themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties index 227c2f113d..bb66578f72 100644 --- a/forms/common-themes/src/main/resources/theme/base/admin/angular-messages/realm-settings_en.properties +++ b/forms/common-themes/src/main/resources/theme/base/admin/messages/admin-messages_en.properties @@ -1,3 +1,12 @@ +# Common messages +enabled=Enabled +name=Name +save=Save +cancel=Cancel +onText=ON +offText=OFF + +# Realm settings realm-detail.enabled.tooltip=Users and clients can only access a realm if it's enabled registrationAllowed=User registration registrationAllowed.tooltip=Enable/disable the registration page. A link for registration will show on login page too. diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java index 31b1d22b76..2f845e0a8c 100755 --- a/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminConsole.java @@ -285,8 +285,7 @@ public class AdminConsole { map.put("resourceUrl", Urls.themeRoot(baseUri) + "/admin/" + adminTheme); map.put("resourceVersion", Version.RESOURCES_VERSION); - ThemeProvider themeProvider = session.getProvider(ThemeProvider.class, "extending"); - Theme theme = themeProvider.getTheme(realm.getAdminTheme(), Theme.Type.ADMIN); + Theme theme = getTheme(); map.put("properties", theme.getProperties()); @@ -298,6 +297,11 @@ public class AdminConsole { } } + private Theme getTheme() throws IOException { + ThemeProvider themeProvider = session.getProvider(ThemeProvider.class, "extending"); + return themeProvider.getTheme(realm.getAdminTheme(), Theme.Type.ADMIN); + } + @GET @Path("{indexhtml: index.html}") // this expression is a hack to get around jaxdoclet generation bug. Doesn't like index.html public Response getIndexHtmlRedirect() { @@ -314,14 +318,14 @@ public class AdminConsole { } try { - Properties msgs = AdminMessagesLoader.getMessages(lang); + Properties msgs = AdminMessagesLoader.getMessages(getTheme(), lang); if (msgs.isEmpty()) { logger.warn("Message bundle not found for language code '" + lang + "'"); - msgs = AdminMessagesLoader.getMessages("en"); // fall back to en + msgs = AdminMessagesLoader.getMessages(getTheme(), "en"); // fall back to en } if (msgs.isEmpty()) logger.fatal("Message bundle not found for language code 'en'"); - + return msgs; } catch (IOException e) { throw new RuntimeException(e); diff --git a/services/src/main/java/org/keycloak/services/resources/admin/AdminMessagesLoader.java b/services/src/main/java/org/keycloak/services/resources/admin/AdminMessagesLoader.java index 709cb12684..df0ce27352 100644 --- a/services/src/main/java/org/keycloak/services/resources/admin/AdminMessagesLoader.java +++ b/services/src/main/java/org/keycloak/services/resources/admin/AdminMessagesLoader.java @@ -22,11 +22,13 @@ import java.io.FileInputStream; import java.io.FilenameFilter; import java.io.IOException; import java.util.HashMap; +import java.util.Locale; import java.util.Map; import java.util.Properties; +import org.keycloak.freemarker.Theme; /** - * Simple loader for message bundles consumed by angular-translate. + * Simple loader and cache for message bundles consumed by angular-translate. * * Note that these bundles are converted to JSON before being shipped to the UI. * Also, the content should be formatted such that it can be interpolated by @@ -35,59 +37,18 @@ import java.util.Properties; * @author Stan Silvert ssilvert@redhat.com (C) 2015 Red Hat Inc. */ public class AdminMessagesLoader { - private static final String CONFIG_DIR = System.getProperty("jboss.server.config.dir"); - private static final String BUNDLE_DIR = CONFIG_DIR + "/themes/base/admin/angular-messages/"; - private static final Map allMessages = new HashMap(); - static Properties getMessages(String locale) throws IOException { - Properties messages = allMessages.get(locale); + static Properties getMessages(Theme theme, String strLocale) throws IOException { + String allMessagesKey = theme.getName() + "_" + strLocale; + Properties messages = allMessages.get(allMessagesKey); if (messages != null) return messages; - return loadMessages(locale); - } + Locale locale = new Locale(strLocale); + messages = theme.getMessages("admin-messages", locale); + if (messages == null) return new Properties(); - private static Properties loadMessages(String locale) throws IOException { - Properties masterMsgs = new Properties(); - - for (File file : getBundlesForLocale(locale)) { - try (FileInputStream msgStream = new FileInputStream(file)){ - Properties propsFromFile = new Properties(); - propsFromFile.load(msgStream); - checkForDups(masterMsgs, propsFromFile, file, locale); - masterMsgs.putAll(propsFromFile); - } - } - - allMessages.put(locale, masterMsgs); - return masterMsgs; - } - - private static void checkForDups(Properties masterMsgs, Properties propsFromFile, File file, String locale) { - for (String prop : propsFromFile.stringPropertyNames()) { - if (masterMsgs.getProperty(prop) != null) { - String errorMsg = "Message bundle " + file.getName() + " contains key '" + prop; - errorMsg += "', which already exists in another bundle for " + locale + " locale."; - throw new RuntimeException(errorMsg); - } - } - } - - private static File[] getBundlesForLocale(String locale) { - File bundleDir = new File(BUNDLE_DIR); - return bundleDir.listFiles(new LocaleFilter(locale)); - } - - private static class LocaleFilter implements FilenameFilter { - private final String locale; - - public LocaleFilter(String locale) { - this.locale = locale; - } - - @Override - public boolean accept(File dir, String name) { - return name.endsWith("_" + locale + ".properties"); - } + allMessages.put(allMessagesKey, messages); + return messages; } }