Commit 7041c144 authored by Matt Tucker's avatar Matt Tucker Committed by matt

Full plugin i18n.

git-svn-id: http://svn.igniterealtime.org/svn/repos/wildfire/trunk@4092 b35dd754-fafc-0310-a699-88a17e54d16e
parent 0b3f777a
......@@ -13,6 +13,7 @@ package org.jivesoftware.admin;
import org.jivesoftware.util.ClassUtils;
import org.jivesoftware.util.Log;
import org.jivesoftware.util.LocaleUtils;
import org.jivesoftware.wildfire.XMPPServer;
import org.dom4j.Document;
import org.dom4j.Element;
......@@ -89,7 +90,8 @@ public class AdminConsole {
public static String getAppName() {
Element appName = (Element)generatedModel.selectSingleNode("//adminconsole/global/appname");
if (appName != null) {
return appName.getText();
String pluginName = appName.attributeValue("plugin");
return getAdminText(appName.getText(), pluginName);
}
else {
return null;
......@@ -105,7 +107,8 @@ public class AdminConsole {
Element globalLogoImage = (Element)generatedModel.selectSingleNode(
"//adminconsole/global/logo-image");
if (globalLogoImage != null) {
return globalLogoImage.getText();
String pluginName = globalLogoImage.attributeValue("plugin");
return getAdminText(globalLogoImage.getText(), pluginName);
}
else {
return null;
......@@ -121,7 +124,8 @@ public class AdminConsole {
Element globalLoginLogoImage = (Element)generatedModel.selectSingleNode(
"//adminconsole/global/login-image");
if (globalLoginLogoImage != null) {
return globalLoginLogoImage.getText();
String pluginName = globalLoginLogoImage.attributeValue("plugin");
return getAdminText(globalLoginLogoImage.getText(), pluginName);
}
else {
return null;
......@@ -137,7 +141,8 @@ public class AdminConsole {
Element globalVersion = (Element)generatedModel.selectSingleNode(
"//adminconsole/global/version");
if (globalVersion != null) {
return globalVersion.getText();
String pluginName = globalVersion.attributeValue("plugin");
return getAdminText(globalVersion.getText(), pluginName);
}
else {
// Default to the Wildfire version if none has been provided via XML.
......@@ -166,6 +171,30 @@ public class AdminConsole {
return (Element)generatedModel.selectSingleNode("//*[@id='" + id + "']");
}
/**
* Returns a text element for the admin console, applying the appropriate locale.
* Internationalization logic will only be applied if the String is specially encoded
* in the format "${key.name}". If it is, the String is pulled from the resource bundle.
* If the pluginName is not <tt>null</tt>, the plugin's resource bundle will be used
* to look up the key.
*
* @param string the String.
* @param pluginName the name of the plugin that the i18n String can be found in,
* or <tt>null</tt> if the standard Wildfire resource bundle should be used.
* @return the string, or if the string is encoded as an i18n key, the value from
* the appropriate resource bundle.
*/
public static String getAdminText(String string, String pluginName) {
if (string == null) {
return null;
}
// Look for the key symbol:
if (string.indexOf("${") == 0 && string.indexOf("}") == string.length()-1) {
return LocaleUtils.getLocalizedString(string.substring(2, string.length()-1), pluginName);
}
return string;
}
private static void load() {
// Load the core model as the admin-sidebar.xml file from the classpath.
InputStream in = ClassUtils.getResourceAsStream("/admin-sidebar.xml");
......@@ -234,18 +263,27 @@ public class AdminConsole {
Element existingAppName = (Element)generatedModel.selectSingleNode(
"//adminconsole/global/appname");
existingAppName.setText(appName.getText());
if (appName.attributeValue("plugin") != null) {
existingAppName.addAttribute("plugin", appName.attributeValue("plugin"));
}
}
Element appLogoImage = (Element)element.selectSingleNode("//adminconsole/global/logo-image");
if (appLogoImage != null) {
Element existingLogoImage = (Element)generatedModel.selectSingleNode(
"//adminconsole/global/logo-image");
existingLogoImage.setText(appLogoImage.getText());
if (appLogoImage.attributeValue("plugin") != null) {
existingLogoImage.addAttribute("plugin", appLogoImage.attributeValue("plugin"));
}
}
Element appLoginImage = (Element)element.selectSingleNode("//adminconsole/global/login-image");
if (appLoginImage != null) {
Element existingLoginImage = (Element)generatedModel.selectSingleNode(
"//adminconsole/global/login-image");
existingLoginImage.setText(appLoginImage.getText());
if (appLoginImage.attributeValue("plugin") != null) {
existingLoginImage.addAttribute("plugin", appLoginImage.attributeValue("plugin"));
}
}
Element appVersion = (Element)element.selectSingleNode("//adminconsole/global/version");
if (appVersion != null) {
......@@ -253,6 +291,9 @@ public class AdminConsole {
"//adminconsole/global/version");
if (existingVersion != null) {
existingVersion.setText(appVersion.getText());
if (appVersion.attributeValue("plugin") != null) {
existingVersion.addAttribute("plugin", appVersion.attributeValue("plugin"));
}
}
else {
((Element)generatedModel.selectSingleNode(
......@@ -298,6 +339,9 @@ public class AdminConsole {
if (overrideTab.attributeValue("description") != null) {
tab.addAttribute("description", overrideTab.attributeValue("description"));
}
if (overrideTab.attributeValue("plugin") != null) {
tab.addAttribute("plugin", overrideTab.attributeValue("plugin"));
}
// Override sidebar items.
for (Iterator i=overrideTab.elementIterator(); i.hasNext(); ) {
Element sidebar = (Element)i.next();
......@@ -321,6 +365,9 @@ public class AdminConsole {
if (overrideSidebar.attributeValue("name") != null) {
sidebar.addAttribute("name", overrideSidebar.attributeValue("name"));
}
if (overrideSidebar.attributeValue("plugin") != null) {
sidebar.addAttribute("plugin", overrideSidebar.attributeValue("plugin"));
}
// Override entries.
for (Iterator i=overrideSidebar.elementIterator(); i.hasNext(); ) {
Element entry = (Element)i.next();
......@@ -350,6 +397,9 @@ public class AdminConsole {
if (overrideEntry.attributeValue("description") != null) {
entry.addAttribute("description", overrideEntry.attributeValue("description"));
}
if (overrideEntry.attributeValue("plugin") != null) {
entry.addAttribute("plugin", overrideEntry.attributeValue("plugin"));
}
// Override any sidebars contained in the entry.
for (Iterator i=overrideEntry.elementIterator(); i.hasNext(); ) {
Element sidebar = (Element)i.next();
......
......@@ -12,7 +12,6 @@
package org.jivesoftware.admin;
import org.jivesoftware.util.StringUtils;
import org.jivesoftware.util.LocaleUtils;
import org.dom4j.Element;
import javax.servlet.jsp.tagext.BodyTagSupport;
......@@ -153,8 +152,8 @@ public class SidebarTag extends BodyTagSupport {
String subPageID = (String)request.getAttribute("subPageID");
String pageID = (String)request.getAttribute("pageID");
// If the pageID is null, use the subPageID to set it. If both the pageID and subPageIDs are null,
// return because these are key to execution of the tag.
// If the pageID is null, use the subPageID to set it. If both the pageID and
// subPageIDs are null, return because these are key to execution of the tag.
if (subPageID != null || pageID != null) {
if (pageID == null) {
......@@ -190,12 +189,14 @@ public class SidebarTag extends BodyTagSupport {
for (Iterator iter=items.iterator(); iter.hasNext(); ) {
Element sidebar = (Element)iter.next();
String header = sidebar.attributeValue("name");
String pluginName = sidebar.attributeValue("plugin");
// Print the header:
String hcss = getHeadercss();
if (hcss == null) {
hcss = "";
}
buf.append("<li class=\"").append(hcss).append("\">").append(clean(i18n(header))).append("</li>");
buf.append("<li class=\"").append(hcss).append("\">").append(
clean(AdminConsole.getAdminText(header, pluginName))).append("</li>");
// Now print all items:
for (Iterator subitems=sidebar.elementIterator(); subitems.hasNext(); ) {
......@@ -204,11 +205,14 @@ public class SidebarTag extends BodyTagSupport {
String subitemName = item.attributeValue("name");
String subitemURL = item.attributeValue("url");
String subitemDescr = item.attributeValue("description");
pluginName = item.attributeValue("plugin");
String value = getBodyContent().getString();
if (value != null) {
value = StringUtils.replace(value, "[id]", clean(subitemID));
value = StringUtils.replace(value, "[name]", clean(i18n(subitemName)));
value = StringUtils.replace(value, "[description]", clean(i18n(subitemDescr)));
value = StringUtils.replace(value, "[name]",
clean(AdminConsole.getAdminText(subitemName, pluginName)));
value = StringUtils.replace(value, "[description]",
clean(AdminConsole.getAdminText(subitemDescr, pluginName)));
value = StringUtils.replace(value, "[url]",
request.getContextPath() + "/" + clean(subitemURL));
}
......@@ -231,7 +235,9 @@ public class SidebarTag extends BodyTagSupport {
buf.append("<ul class=\"subitems\">\n");
// Print the header LI
String subheader = subcurrent.getParent().attributeValue("name");
buf.append("<li class=\"").append(hcss).append("\">").append(clean(i18n(subheader))).append("</li>");
pluginName = subcurrent.getParent().attributeValue("plugin");
buf.append("<li class=\"").append(hcss).append("\">").append(
clean(AdminConsole.getAdminText(subheader, pluginName))).append("</li>");
}
String extraParams = (String)request.getAttribute("extraParams");
while (siblings.hasNext()) {
......@@ -240,6 +246,7 @@ public class SidebarTag extends BodyTagSupport {
String sibName = sibling.attributeValue("name");
String sibDescr = sibling.attributeValue("description");
String sibURL = sibling.attributeValue("url");
pluginName = sibling.attributeValue("plugin");
if (extraParams != null) {
sibURL += ((sibURL.indexOf('?') > -1 ? "&" : "?") + extraParams);
}
......@@ -251,8 +258,10 @@ public class SidebarTag extends BodyTagSupport {
String svalue = getSubsidebarTag().getBody();
if (svalue != null) {
svalue = StringUtils.replace(svalue, "[id]", clean(sibID));
svalue = StringUtils.replace(svalue, "[name]", clean(i18n(sibName)));
svalue = StringUtils.replace(svalue, "[description]", clean(i18n(sibDescr)));
svalue = StringUtils.replace(svalue, "[name]",
clean(AdminConsole.getAdminText(sibName, pluginName)));
svalue = StringUtils.replace(svalue, "[description]",
clean(AdminConsole.getAdminText(sibDescr, pluginName)));
svalue = StringUtils.replace(svalue, "[url]",
request.getContextPath() + "/" + clean(sibURL));
}
......@@ -289,15 +298,4 @@ public class SidebarTag extends BodyTagSupport {
private String clean(String in) {
return (in == null ? "" : StringUtils.replace(in, "'", "\\'"));
}
private static String i18n(String in) {
if (in == null) {
return null;
}
// Look for the key symbol:
if (in.indexOf("${") == 0 && in.indexOf("}") == in.length()-1) {
return LocaleUtils.getLocalizedString(in.substring(2, in.length()-1));
}
return in;
}
}
\ No newline at end of file
......@@ -12,7 +12,6 @@
package org.jivesoftware.admin;
import org.jivesoftware.util.StringUtils;
import org.jivesoftware.util.LocaleUtils;
import org.dom4j.Element;
import javax.servlet.jsp.tagext.BodyTagSupport;
......@@ -139,11 +138,14 @@ public class TabsTag extends BodyTagSupport {
String value = body;
if (value != null) {
// The URL for the tab should be the URL of the first item in the tab.
String pluginName = tab.attributeValue("plugin");
value = StringUtils.replace(value, "[id]", clean(tab.attributeValue("id")));
value = StringUtils.replace(value, "[url]",
request.getContextPath() + "/" + clean(tab.attributeValue("url")));
value = StringUtils.replace(value, "[name]", clean(i18n(tab.attributeValue("name"))));
value = StringUtils.replace(value, "[description]", clean(i18n(tab.attributeValue("description"))));
value = StringUtils.replace(value, "[name]",
clean(AdminConsole.getAdminText(tab.attributeValue("name"), pluginName)));
value = StringUtils.replace(value, "[description]",
clean(AdminConsole.getAdminText(tab.attributeValue("description"), pluginName)));
}
String css = getCss();
if (tab.equals(currentTab)) {
......@@ -175,15 +177,4 @@ public class TabsTag extends BodyTagSupport {
private String clean(String in) {
return (in == null ? "" : StringUtils.replace(in, "'", "\\'"));
}
private String i18n(String in) {
if (in == null) {
return null;
}
// Look for the key symbol:
if (in.indexOf("${") == 0 && in.indexOf("}") == in.length()-1) {
return LocaleUtils.getLocalizedString(in.substring(2, in.length()-1));
}
return in;
}
}
\ No newline at end of file
......@@ -397,7 +397,8 @@ public class LocaleUtils {
/**
* Returns an internationalized string loaded from a resource bundle from the passed
* in plugin.
* in plugin. If the plugin name is <tt>null</tt>, the key will be looked up using
* the standard resource bundle.
*
* @param key the key to use for retrieving the string from the
* appropriate resource bundle.
......@@ -410,7 +411,8 @@ public class LocaleUtils {
/**
* Returns an internationalized string loaded from a resource bundle from the passed
* in plugin.
* in plugin. If the plugin name is <tt>null</tt>, the key will be looked up using
* the standard resource bundle.
*
* @param key the key to use for retrieving the string from the
* appropriate resource bundle.
......@@ -420,8 +422,11 @@ public class LocaleUtils {
* @return the localized string.
*/
public static String getLocalizedString(String key, String pluginName, List arguments) {
Locale locale = JiveGlobals.getLocale();
if (pluginName == null) {
return getLocalizedString(key, arguments);
}
Locale locale = JiveGlobals.getLocale();
String i18nFile = pluginName + "_i18n";
// Retrieve classloader from pluginName.
......@@ -429,7 +434,7 @@ public class LocaleUtils {
PluginManager pluginManager = xmppServer.getPluginManager();
Plugin plugin = pluginManager.getPlugin(pluginName);
if (plugin == null) {
throw new NullPointerException("Plugin could not be located.");
throw new NullPointerException("Plugin could not be located: " + pluginName);
}
ClassLoader pluginClassLoader = pluginManager.getPluginClassloader(plugin).getClassLoader();
......
......@@ -389,15 +389,25 @@ public class PluginManager {
pluginName = parentPluginNode.getTextTrim();
}
Element appName = (Element)adminElement.selectSingleNode(
"/plugin/adminconsole/global/appname");
if (appName != null) {
// Set the plugin name so that the proper i18n String can be loaded.
appName.addAttribute("plugin", pluginName);
}
// If global images are specified, override their URL.
Element imageEl = (Element)adminElement.selectSingleNode(
"/plugin/adminconsole/global/logo-image");
if (imageEl != null) {
imageEl.setText("plugins/" + pluginName + "/" + imageEl.getText());
// Set the plugin name so that the proper i18n String can be loaded.
imageEl.addAttribute("plugin", pluginName);
}
imageEl = (Element)adminElement.selectSingleNode("/plugin/adminconsole/global/login-image");
if (imageEl != null) {
imageEl.setText("plugins/" + pluginName + "/" + imageEl.getText());
// Set the plugin name so that the proper i18n String can be loaded.
imageEl.addAttribute("plugin", pluginName);
}
// Modify all the URL's in the XML so that they are passed through
// the plugin servlet correctly.
......@@ -406,6 +416,22 @@ public class PluginManager {
Attribute attr = (Attribute)url;
attr.setValue("plugins/" + pluginName + "/" + attr.getValue());
}
// In order to internationalize the names and descriptions in the model,
// we add a "plugin" attribute to each tab, sidebar, and item so that
// the the renderer knows where to load the i18n Strings from.
String[] elementNames = new String [] { "tab", "sidebar", "item" };
for (int i=0; i<elementNames.length; i++) {
List values = adminElement.selectNodes("//" + elementNames[i]);
for (Object value : values) {
Element element = (Element)value;
// Make sure there's a name or description. Otherwise, no need to
// override i18n settings.
if (element.attribute("name") != null || element.attribute("value") != null) {
element.addAttribute("plugin", pluginName);
}
}
}
AdminConsole.addModel(pluginName, adminElement);
}
}
......@@ -518,11 +544,12 @@ public class PluginManager {
*/
public String getName(Plugin plugin) {
String name = getElementValue(plugin, "/plugin/name");
String pluginName = pluginDirs.get(plugin).getName();
if (name != null) {
return name;
return AdminConsole.getAdminText(name, pluginName);
}
else {
return pluginDirs.get(plugin).getName();
return pluginName;
}
}
......@@ -534,7 +561,8 @@ public class PluginManager {
* @return the plugin's description.
*/
public String getDescription(Plugin plugin) {
return getElementValue(plugin, "/plugin/description");
String pluginName = pluginDirs.get(plugin).getName();
return AdminConsole.getAdminText(getElementValue(plugin, "/plugin/description"), pluginName);
}
/**
......@@ -740,9 +768,9 @@ public class PluginManager {
System.gc();
int count = 0;
while (!deleteDir(dir) && count < 5) {
Log.error("Error unloading plugin " + pluginName + ". " +
Log.warn("Error unloading plugin " + pluginName + ". " +
"Will attempt again momentarily.");
Thread.sleep(5000);
Thread.sleep(10000);
count++;
}
// Now unzip the plugin.
......
......@@ -2,7 +2,7 @@
<adminconsole>
<global>
<appname>Wildfire</appname>
<appname>${title}</appname>
<logo-image>images/header-title.gif</logo-image>
<login-image>images/logo-wildfire.gif</login-image>
</global>
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment