diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h
index 91b706a5beed161a762f75c17b17319e9cde54d5..65e005abfb77a45dc24337b2c3664d11796c59f8 100644
--- a/indra/llcommon/llstring.h
+++ b/indra/llcommon/llstring.h
@@ -232,9 +232,10 @@ class LLStringUtilBase
 	typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t;
 	static void getTokens (std::basic_string<T> input, std::vector<std::basic_string<T> >& tokens);
 	static void formatNumber(std::basic_string<T>& numStr, std::basic_string<T> decimals);
-	static bool formatDatetime(std::basic_string<T>& replacement, std::basic_string<T> token, std::basic_string<T> param, const LLSD& substitutions);
+	static bool formatDatetime(std::basic_string<T>& replacement, std::basic_string<T> token, std::basic_string<T> param, S32 secFromEpoch);
+	static S32 format(std::basic_string<T>& s, const format_map_t& substitutions);
 	static S32 format(std::basic_string<T>& s, const LLSD& substitutions);
-	static S32 format(std::basic_string<T>& s, const format_map_t& fmt_map);
+	static bool simpleReplacement(std::basic_string<T>& replacement, std::basic_string<T> token, const format_map_t& substitutions);
 	static bool simpleReplacement(std::basic_string<T>& replacement, std::basic_string<T> token, const LLSD& substitutions);
 	static void setLocale (std::string inLocale) {sLocale = inLocale;};
 	static std::string getLocale (void) {return sLocale;};
@@ -618,18 +619,76 @@ void LLStringUtilBase<T>::getTokens (std::basic_string<T> input, std::vector<std
 
 // static
 template<class T> 
-S32 LLStringUtilBase<T>::format(std::basic_string<T>& s, const format_map_t& fmt_map)
+S32 LLStringUtilBase<T>::format(std::basic_string<T>& s, const format_map_t& substitutions)
 {
-	LLSD llsdMap;
+	S32 res = 0;
+
+	std::basic_ostringstream<T> output;
+	// match strings like [NAME,number,3]
+	const boost::regex key("\\[((\\s)*([0-9_A-Za-z]+)((\\s)*,(\\s)*[0-9_A-Za-z\\s]*){0,2}(\\s)*)]");
 
-	for (format_map_t::const_iterator iter = fmt_map.begin();
-		 iter != fmt_map.end();
-		 ++iter)
+
+	typename std::basic_string<T>::const_iterator start = s.begin();
+	typename std::basic_string<T>::const_iterator end = s.end();
+	boost::smatch match;
+	
+
+	while (boost::regex_search(start, end, match, key, boost::match_default))
 	{
-		llsdMap[iter->first] = iter->second;
-	}
+		bool found_replacement = false;
+		std::vector<std::basic_string<T> > tokens;
+		std::basic_string<T> replacement;
+
+		getTokens (std::basic_string<T>(match[1].first, match[1].second), tokens);
+
+		if (tokens.size() == 1)
+		{
+			found_replacement = simpleReplacement (replacement, tokens[0], substitutions);
+		}
+		else if (tokens[1] == "number")
+		{
+			std::basic_string<T> param = "0";
+
+			if (tokens.size() > 2) param = tokens[2];
+			found_replacement = simpleReplacement (replacement, tokens[0], substitutions);
+			if (found_replacement) formatNumber (replacement, param);
+		}
+		else if (tokens[1] == "datetime")
+		{
+			std::basic_string<T> param;
+			if (tokens.size() > 2) param = tokens[2];
+			
+			format_map_t::const_iterator iter = substitutions.find("datetime");
+			if (iter != substitutions.end())
+			{
+				S32 secFromEpoch = 0;
+				BOOL r = LLStringUtil::convertToS32(iter->second, secFromEpoch);
+				if (r)
+				{
+					found_replacement = formatDatetime(replacement, tokens[0], param, secFromEpoch);
+				}
+			}
+		}
 
-	return format (s, llsdMap);
+		if (found_replacement)
+		{
+			output << std::basic_string<T>(start, match[0].first) << replacement;
+			res++;
+		}
+		else
+		{
+			// we had no replacement, so leave the string we searched for so that it gets noticed by QA
+			// "hello [NAME_NOT_FOUND]" is output
+			output << std::basic_string<T>(start, match[0].second);
+		}
+		
+		// update search position 
+		start = match[0].second; 
+	}
+	// send the remainder of the string (with no further matches for bracketed names)
+	output << std::basic_string<T>(start, end);
+	s = output.str();
+	return res;
 }
 
 //static
@@ -704,7 +763,32 @@ S32 LLStringUtilBase<T>::format(std::basic_string<T>& s, const LLSD& substitutio
 
 // static
 template<class T>
-bool LLStringUtilBase<T>::simpleReplacement(std::basic_string<T> &replacement, std::basic_string<T> token, const LLSD &substitutions)
+bool LLStringUtilBase<T>::simpleReplacement(std::basic_string<T> &replacement, std::basic_string<T> token, const format_map_t& substitutions)
+{
+	// see if we have a replacement for the bracketed string (without the brackets)
+	// test first using has() because if we just look up with operator[] we get back an
+	// empty string even if the value is missing. We want to distinguish between 
+	// missing replacements and deliberately empty replacement strings.
+	format_map_t::const_iterator iter = substitutions.find(token);
+	if (iter != substitutions.end())
+	{
+		replacement = iter->second;
+		return true;
+	}
+	// if not, see if there's one WITH brackets
+	iter = substitutions.find(std::basic_string<T>("[" + token + "]"));
+	if (iter != substitutions.end())
+	{
+		replacement = iter->second;
+		return true;
+	}
+
+	return false;
+}
+
+// static
+template<class T>
+bool LLStringUtilBase<T>::simpleReplacement(std::basic_string<T> &replacement, std::basic_string<T> token, const LLSD& substitutions)
 {
 	// see if we have a replacement for the bracketed string (without the brackets)
 	// test first using has() because if we just look up with operator[] we get back an
@@ -764,10 +848,8 @@ void LLStringUtilBase<T>::formatNumber(std::basic_string<T>& numStr, std::basic_
 // static
 template<class T>
 bool LLStringUtilBase<T>::formatDatetime(std::basic_string<T>& replacement, std::basic_string<T> token,
-										 std::basic_string<T> param, const LLSD& substitutions)
+										 std::basic_string<T> param, S32 secFromEpoch)
 {
-	S32 secFromEpoch = (long) substitutions["datetime"].asInteger();
-
 	if (param == "local")   // local
 	{
 		secFromEpoch -= LLStringOps::getLocalTimeOffset();
diff --git a/indra/llui/lluistring.cpp b/indra/llui/lluistring.cpp
index 7ce0fd7a88d1a75344ce0b29ba47ffd2884109d3..20ff71378e1ce5409d93106a471aa89c916e3d79 100644
--- a/indra/llui/lluistring.cpp
+++ b/indra/llui/lluistring.cpp
@@ -37,6 +37,8 @@
 
 const LLStringUtil::format_map_t LLUIString::sNullArgs;
 
+LLFastTimer::DeclareTimer FTM_UI_STRING("UI String");
+
 
 LLUIString::LLUIString(const std::string& instring, const LLStringUtil::format_map_t& args)
 	: mOrig(instring),
@@ -59,6 +61,8 @@ void LLUIString::setArgList(const LLStringUtil::format_map_t& args)
 
 void LLUIString::setArgs(const LLSD& sd)
 {
+	LLFastTimer timer(FTM_UI_STRING);
+	
 	if (!sd.isMap()) return;
 	for(LLSD::map_const_iterator sd_it = sd.beginMap();
 		sd_it != sd.endMap();
@@ -112,6 +116,8 @@ void LLUIString::clear()
 
 void LLUIString::format()
 {
+	LLFastTimer timer(FTM_UI_STRING);
+	
 	// optimize for empty strings (don't attempt string replacement)
 	if (mOrig.empty())
 	{
diff --git a/indra/newview/skins/default/xui/en/panel_profile.xml b/indra/newview/skins/default/xui/en/panel_profile.xml
index 23c8223e7bd020616b3e27a66185d796086428dc..25ed38f5cc64e7345b744e96e5a094eefde2d1e4 100644
--- a/indra/newview/skins/default/xui/en/panel_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_profile.xml
@@ -104,15 +104,15 @@
              top_delta="0"
              value="Second Life:"
              width="140" />
-            <text
+            <text_editor
              follows="left|top|right"
              height="90"
              layout="topleft"
              name="sl_description_edit"
-             width="130"
+             width="180"
              word_wrap="true">
                 Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum.
-            </text>
+            </text_editor>
         </panel>
         <panel
          follows="left|top"
@@ -142,15 +142,15 @@
              top_delta="0"
              value="Real World:"
              width="140" />
-            <text
+            <text_editor
              follows="left|top|right"
              height="90"
              layout="topleft"
              name="fl_description_edit"
-             width="130"
+             width="180"
              word_wrap="true">
                 Lorem ipsum dolor sit amet, consectetur adlkjpiscing elit moose moose. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet. adipiscing elit. Aenean rigviverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet sorbet ipsum. adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum.
-            </text>
+            </text_editor>
         </panel>
         <link
          follows="left|top|right"