Commit 900b1fb6 authored by Derek DeMoro's avatar Derek DeMoro Committed by derek

Added the ability to use i18n with plugins. Please refer to the...

Added the ability to use i18n with plugins. Please refer to the plugin-dev-guide.html for the how-tos.

git-svn-id: http://svn.igniterealtime.org/svn/repos/wildfire/trunk@3861 b35dd754-fafc-0310-a699-88a17e54d16e
parent a7e65a2f
...@@ -37,6 +37,7 @@ plugin directory are as follows: ...@@ -37,6 +37,7 @@ plugin directory are as follows:
|- icon_large.gif <- Optional large (32x32) icon associated with the plugin (can also be a .png file) |- icon_large.gif <- Optional large (32x32) icon associated with the plugin (can also be a .png file)
|- classes/ <- Resources your plugin needs (i.e., a properties file) |- classes/ <- Resources your plugin needs (i.e., a properties file)
|- database/ <- Optional database schema files that your plugin needs |- database/ <- Optional database schema files that your plugin needs
|- i18n/ <- Optional i18n files to allow for internationalization of plugins.
|- lib/ <- Libraries (JAR files) your plugin needs |- lib/ <- Libraries (JAR files) your plugin needs
|- web <- Resources for Admin Console integration, if any |- web <- Resources for Admin Console integration, if any
|- WEB-INF/ |- WEB-INF/
...@@ -281,6 +282,16 @@ The following HTML snippet demonstrates a valid page: ...@@ -281,6 +282,16 @@ The following HTML snippet demonstrates a valid page:
</pre> </pre>
</fieldset> </fieldset>
<h4>Using i18n in your Admin Console Pages</h4>
<p>
To use i18n in your own plugin, you must do the following:
<ul>
<li>Add i18n directory to root directory of your plugin.</li>
<li>Add each resource file using the %name_of_plugin%_i18n "_" language ".properties" naming convention.</li>
<li>To use directly within your jsp, use the LocaleUtils class, and pass in the name of the plugin.<br/><b>Example:&nbsp;</b>&lt;%= LocaleUtils.getLocalizedString("my.title", "myplugin") %&gt;
</li>
</ul>
</p>
<h2>Using the Wildfire Build Script</h2> <h2>Using the Wildfire Build Script</h2>
<p> <p>
......
...@@ -11,8 +11,23 @@ ...@@ -11,8 +11,23 @@
package org.jivesoftware.util; package org.jivesoftware.util;
import java.text.*; import org.jivesoftware.wildfire.XMPPServer;
import java.util.*; import org.jivesoftware.wildfire.container.Plugin;
import org.jivesoftware.wildfire.container.PluginManager;
import java.text.DateFormat;
import java.text.Format;
import java.text.MessageFormat;
import java.text.NumberFormat;
import java.text.ParseException;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.StringTokenizer;
import java.util.TimeZone;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
/** /**
...@@ -274,7 +289,7 @@ public class LocaleUtils { ...@@ -274,7 +289,7 @@ public class LocaleUtils {
// Add in the GMT part to the name. First, figure out the offset. // Add in the GMT part to the name. First, figure out the offset.
int offset = zone.getRawOffset(); int offset = zone.getRawOffset();
if (zone.inDaylightTime(new Date()) && zone.useDaylightTime()) { if (zone.inDaylightTime(new Date()) && zone.useDaylightTime()) {
offset += (int) JiveConstants.HOUR; offset += (int)JiveConstants.HOUR;
} }
buf.append("("); buf.append("(");
...@@ -285,8 +300,8 @@ public class LocaleUtils { ...@@ -285,8 +300,8 @@ public class LocaleUtils {
buf.append("GMT+"); buf.append("GMT+");
} }
offset = Math.abs(offset); offset = Math.abs(offset);
int hours = offset / (int) JiveConstants.HOUR; int hours = offset / (int)JiveConstants.HOUR;
int minutes = (offset % (int) JiveConstants.HOUR) / (int) JiveConstants.MINUTE; int minutes = (offset % (int)JiveConstants.HOUR) / (int)JiveConstants.MINUTE;
buf.append(hours).append(":"); buf.append(hours).append(":");
if (minutes < 10) { if (minutes < 10) {
buf.append("0").append(minutes); buf.append("0").append(minutes);
...@@ -338,7 +353,11 @@ public class LocaleUtils { ...@@ -338,7 +353,11 @@ public class LocaleUtils {
* @return the localized string. * @return the localized string.
*/ */
public static String getLocalizedString(String key) { public static String getLocalizedString(String key) {
return getLocalizedString(key, JiveGlobals.getLocale(), null); Locale locale = JiveGlobals.getLocale();
ResourceBundle bundle = ResourceBundle.getBundle(resourceBaseName, locale);
return getLocalizedString(key, locale, null, bundle);
} }
/** /**
...@@ -352,7 +371,9 @@ public class LocaleUtils { ...@@ -352,7 +371,9 @@ public class LocaleUtils {
* @return the localized string. * @return the localized string.
*/ */
public static String getLocalizedString(String key, Locale locale) { public static String getLocalizedString(String key, Locale locale) {
return getLocalizedString(key, locale, null); ResourceBundle bundle = ResourceBundle.getBundle(resourceBaseName, locale);
return getLocalizedString(key, locale, null, bundle);
} }
/** /**
...@@ -368,13 +389,58 @@ public class LocaleUtils { ...@@ -368,13 +389,58 @@ public class LocaleUtils {
* @return the localized string. * @return the localized string.
*/ */
public static String getLocalizedString(String key, List arguments) { public static String getLocalizedString(String key, List arguments) {
return getLocalizedString(key, JiveGlobals.getLocale(), arguments); Locale locale = JiveGlobals.getLocale();
ResourceBundle bundle = ResourceBundle.getBundle(resourceBaseName, locale);
return getLocalizedString(key, locale, arguments, bundle);
}
/**
* Returns an internationalized string loaded from a resource bundle from the passed
* in plugin.
*
* @param key the key to use for retrieving the string from the
* appropriate resource bundle.
* @param pluginName the name of the plugin to load the require resource bundle from.
* @return the localized string.
*/
public static String getLocalizedString(String key, String pluginName) {
return getLocalizedString(key, pluginName, null);
}
/**
* Returns an internationalized string loaded from a resource bundle from the passed
* in plugin.
*
* @param key the key to use for retrieving the string from the
* appropriate resource bundle.
* @param pluginName the name of the plugin to load the require resource bundle from.
* @param arguments a list of objects to use which are formatted, then
* inserted into the pattern at the appropriate places.
* @return the localized string.
*/
public static String getLocalizedString(String key, String pluginName, List arguments) {
Locale locale = JiveGlobals.getLocale();
String i18nFile = pluginName + "_i18n";
// Retrieve classloader from pluginName.
final XMPPServer xmppServer = XMPPServer.getInstance();
PluginManager pluginManager = xmppServer.getPluginManager();
Plugin plugin = pluginManager.getPlugin(pluginName);
if(plugin == null){
throw new NullPointerException("Plugin could not be located.");
}
ClassLoader pluginClassLoader = pluginManager.getPluginClassloader(plugin).getClassLoader();
ResourceBundle bundle = ResourceBundle.getBundle(i18nFile, locale, pluginClassLoader);
return getLocalizedString(key, locale, arguments, bundle);
} }
/** /**
* Returns an internationalized string loaded from a resource bundle using * Returns an internationalized string loaded from a resource bundle using
* the passed in Locale substituting the passed in arguments. Substitution * the passed in Locale substituting the passed in arguments. Substitution
* is handled using the {@link java.text.MessageFormat} class. * is handled using the {@link MessageFormat} class.
* *
* @param key the key to use for retrieving the string from the * @param key the key to use for retrieving the string from the
* appropriate resource bundle. * appropriate resource bundle.
...@@ -384,7 +450,7 @@ public class LocaleUtils { ...@@ -384,7 +450,7 @@ public class LocaleUtils {
* inserted into the pattern at the appropriate places. * inserted into the pattern at the appropriate places.
* @return the localized string. * @return the localized string.
*/ */
public static String getLocalizedString(String key, Locale locale, List arguments) { public static String getLocalizedString(String key, Locale locale, List arguments, ResourceBundle bundle) {
if (key == null) { if (key == null) {
throw new NullPointerException("Key cannot be null"); throw new NullPointerException("Key cannot be null");
} }
...@@ -397,7 +463,6 @@ public class LocaleUtils { ...@@ -397,7 +463,6 @@ public class LocaleUtils {
// See if the bundle has a value // See if the bundle has a value
try { try {
// The jdk caches resource bundles on it's own, so we won't bother. // The jdk caches resource bundles on it's own, so we won't bother.
ResourceBundle bundle = ResourceBundle.getBundle(resourceBaseName, locale);
value = bundle.getString(key); value = bundle.getString(key);
// perform argument substitutions // perform argument substitutions
if (arguments != null) { if (arguments != null) {
......
...@@ -34,7 +34,7 @@ import java.util.List; ...@@ -34,7 +34,7 @@ import java.util.List;
* *
* @author Derek DeMoro * @author Derek DeMoro
*/ */
class PluginClassLoader { public class PluginClassLoader {
private URLClassLoader classLoader; private URLClassLoader classLoader;
private final List<URL> list = new ArrayList<URL>(); private final List<URL> list = new ArrayList<URL>();
...@@ -58,10 +58,19 @@ class PluginClassLoader { ...@@ -58,10 +58,19 @@ class PluginClassLoader {
*/ */
public void addDirectory(File directory, boolean developmentMode) { public void addDirectory(File directory, boolean developmentMode) {
try { try {
// Add classes directory to classpath.
File classesDir = new File(directory, "classes"); File classesDir = new File(directory, "classes");
if (classesDir.exists()) { if (classesDir.exists()) {
list.add(classesDir.toURL()); list.add(classesDir.toURL());
} }
// Add i18n directory to classpath.
File i18nDir = new File(directory, "i18n");
if(i18nDir.exists()){
list.add(i18nDir.toURL());
}
// Add lib directory to classpath.
File libDir = new File(directory, "lib"); File libDir = new File(directory, "lib");
File[] jars = libDir.listFiles(new FilenameFilter() { File[] jars = libDir.listFiles(new FilenameFilter() {
public boolean accept(File dir, String name) { public boolean accept(File dir, String name) {
...@@ -161,4 +170,12 @@ class PluginClassLoader { ...@@ -161,4 +170,12 @@ class PluginClassLoader {
} }
return parent; return parent;
} }
/**
* Returns the URLClassloader used.
* @return the URLClassLoader used.
*/
public ClassLoader getClassLoader(){
return classLoader;
}
} }
...@@ -167,16 +167,14 @@ ...@@ -167,16 +167,14 @@
} }
else { else {
errorBuf.append("<br>").append( errorBuf.append("<br>").append(
LocaleUtils.getLocalizedString("group.edit.already_user", LocaleUtils.getLocalizedString("group.edit.already_user", Arrays.asList(username)));
JiveGlobals.getLocale(), Arrays.asList(username)));
} }
} }
catch (Exception e) { catch (Exception e) {
Log.debug("Problem adding new user to existing group", e); Log.debug("Problem adding new user to existing group", e);
errorBuf.append("<br>").append( errorBuf.append("<br>").append(
LocaleUtils.getLocalizedString("group.edit.inexistent_user", LocaleUtils.getLocalizedString("group.edit.inexistent_user", Arrays.asList(username)));
JiveGlobals.getLocale(), Arrays.asList(username)));
} }
} }
if (count > 0) { if (count > 0) {
......
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