Index: /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/ServiceRack.java
===================================================================
--- /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/ServiceRack.java	(revision 30628)
+++ /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/service/ServiceRack.java	(revision 30629)
@@ -447,4 +447,80 @@
 	}
 
+
+	/**
+	 * Returns the appropriate language element from a display elem, display is
+	 * the containing element, name is the name of the element to look for, lang
+	 * is the preferred language, lang_default is the fall back lang, if neither
+	 * lang is found will return the first one it finds
+	 */
+  public String getDisplayText(Element display, String name, String lang, String lang_default) {
+    return getDisplayText(display, name, lang, lang_default, null);
+  }
+
+  public String getDisplayText(Element display, String name, String lang, String lang_default, String dictionary_name) {
+	
+
+		String def = null;
+		String first = null;
+		String key = null;
+		NodeList elems = display.getElementsByTagName(GSXML.DISPLAY_TEXT_ELEM);
+		if (elems.getLength() == 0)
+			return "";
+		for (int i = 0; i < elems.getLength(); i++)
+		{
+			Element e = (Element) elems.item(i);
+			String n = e.getAttribute(GSXML.NAME_ATT);
+			if (name.equals(n))
+			{
+				String l = e.getAttribute(GSXML.LANG_ATT);
+				String k = e.getAttribute(GSXML.KEY_ATT);
+				// if we have a specific lang value, return that
+				if (!l.equals("") && lang.equals(l))
+				{
+					return GSXML.getNodeText(e);
+				}
+				else if (!l.equals("") && lang_default.equals(l))
+				{
+					def = GSXML.getNodeText(e);
+				}
+				else if (!k.equals("")) {
+				  if ( key == null) {
+				  // a key specified. only allowed one spec with key
+				    key = k;
+				  }
+				}
+				// we have no key and we don't match the languages
+				else if (first == null)
+				{
+				  // but we are the first one, so we remember the value
+					first = GSXML.getNodeText(e);
+				}
+			}
+			else
+			{
+				continue;
+			}
+		}
+
+		
+		if (key != null) {
+		  String s = getTextString(key, lang, dictionary_name);
+		  // only use this one if a value was actually found
+		  if (!s.equals( "_"+key +"_")) {
+		    return s;
+		  }
+		}
+
+		if (def != null)
+		{
+			return def;
+		}
+		if (first != null)
+		{
+			return first;
+		}
+		return "";
+	}
+
 	/** overloaded version for no args case */
 	protected String getTextString(String key, String lang)
@@ -478,5 +554,6 @@
 			if (result == null)
 			{ // not found
-				return "_" + key + "_";
+			  //return "_" + key + "_";
+			  return null;
 			}
 			return result;
@@ -513,5 +590,5 @@
 		  // try the ServiceRack properties
 		  // at the moment we look for original_class_name.key, then just key
-		  // if there is lots of inheritance, may want to try down the list of superclasses too...
+		  // if there is lots of inheritance, may want to try down the list of superclasses too...?
 		  class_name = "ServiceRack";
 		  dict = new Dictionary(class_name, lang, this.class_loader);
Index: /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/GSXML.java
===================================================================
--- /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/GSXML.java	(revision 30628)
+++ /main/trunk/greenstone3/src/java/org/greenstone/gsdl3/util/GSXML.java	(revision 30629)
@@ -139,4 +139,5 @@
 	public static final String FROM_ATT = "from";
 	public static final String LANG_ATT = "lang";
+  public static final String KEY_ATT = "key";
 	public static final String HREF_ATT = "href";
 	public static final String TYPE_ATT = "type";
@@ -1261,54 +1262,4 @@
     return att_value;
   }
-	/**
-	 * Returns the appropriate language element from a display elem, display is
-	 * the containing element, name is the name of the element to look for, lang
-	 * is the preferred language, lang_default is the fall back lang if neither
-	 * lang is found, will return the first one it finds
-	 */
-	public static String getDisplayText(Element display, String name, String lang, String lang_default)
-	{
-
-		String def = null;
-		String first = null;
-		NodeList elems = display.getElementsByTagName(DISPLAY_TEXT_ELEM);
-		if (elems.getLength() == 0)
-			return "";
-		for (int i = 0; i < elems.getLength(); i++)
-		{
-			Element e = (Element) elems.item(i);
-			String n = e.getAttribute(NAME_ATT);
-			if (name.equals(n))
-			{
-				String l = e.getAttribute(LANG_ATT);
-				if (lang.equals(l))
-				{
-					return getNodeText(e);
-				}
-				else if (lang_default.equals(l))
-				{
-					def = getNodeText(e);
-				}
-				else if (first == null)
-				{
-					first = getNodeText(e);
-				}
-			}
-			else
-			{
-				continue;
-			}
-		}
-
-		if (def != null)
-		{
-			return def;
-		}
-		if (first != null)
-		{
-			return first;
-		}
-		return "";
-	}
 
 	// replaces < > " ' & in the original with their entities
