Load admin messages through Themes.

This commit is contained in:
Stan Silvert 2015-09-08 15:22:50 -04:00
parent e455cbf319
commit 75bd8d4627
7 changed files with 44 additions and 67 deletions

View file

@ -181,6 +181,12 @@ import=common/keycloak
<literal>messages/messages.properties</literal> inside your theme folder and add the following content:
</para>
<programlisting>username=Your Username</programlisting>
<para>
For the admin console, there is a second resource bundle named <literal>admin-messages.properties</literal>.
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.
</para>
</section>
<section>
<title>Modifying HTML</title>

View file

@ -1,6 +0,0 @@
enabled=de Enabled
name=de Name
save=de Save
cancel=de Cancel
onText=AN
offText=AUS

View file

@ -1,6 +0,0 @@
enabled=Enabled
name=Name
save=Save
cancel=Cancel
onText=ON
offText=OFF

View file

@ -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.

View file

@ -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.

View file

@ -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);

View file

@ -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<String, Properties> allMessages = new HashMap<String, Properties>();
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;
}
}