diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index cbb5a40cfa0ea4e8d6f5e78ec888cf076b6e074d..5c963025cb473990b2c5c1394d23bd54c40af065 100644
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -59,7 +59,7 @@ LLFilePicker LLFilePicker::sInstance;
 #define RAW_FILTER L"RAW files (*.raw)\0*.raw\0"
 #define MODEL_FILTER L"Model files (*.dae)\0*.dae\0"
 #define SCRIPT_FILTER L"Script files (*.lsl)\0*.lsl\0"
-#define DICTIONARY_FILTER L"Dictionary files (*.dic)\0*.dic\0"
+#define DICTIONARY_FILTER L"Dictionary files (*.dic; *.xcu)\0*.dic;*.xcu\0"
 #endif
 
 //
@@ -651,7 +651,9 @@ Boolean LLFilePicker::navOpenFilterProc(AEDesc *theItem, void *info, void *callB
 						else if (filter == FFLOAD_DICTIONARY)
 						{
 							if (fileInfo.filetype != 'DIC ' &&
-								(fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("dic"), kCFCompareCaseInsensitive) != kCFCompareEqualTo)) )
+								fileInfo.filetype != 'XCU ' &&
+								(fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("dic"), kCFCompareCaseInsensitive) != kCFCompareEqualTo) &&
+								 fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("xcu"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))
 							{
 								result = false;
 							}
@@ -1251,7 +1253,7 @@ static std::string add_script_filter_to_gtkchooser(GtkWindow *picker)
 static std::string add_dictionary_filter_to_gtkchooser(GtkWindow *picker)
 {
 	return add_simple_mime_filter_to_gtkchooser(picker,  "text/plain",
-							LLTrans::getString("dictionary_files") + " (*.dic)");
+							LLTrans::getString("dictionary_files") + " (*.dic; *.xcu)");
 }
 
 BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const std::string& filename )
diff --git a/indra/newview/llfloaterspellchecksettings.cpp b/indra/newview/llfloaterspellchecksettings.cpp
index d7fbc94631b8ab0678d44c7a09f604c6c67d816a..c62577bc94ee9b9d61b08d88969f03d4266249c4 100644
--- a/indra/newview/llfloaterspellchecksettings.cpp
+++ b/indra/newview/llfloaterspellchecksettings.cpp
@@ -264,7 +264,18 @@ void LLFloaterSpellCheckerImport::onBtnBrowse()
 		return;
 	}
 
-	const std::string filepath = file_picker.getFirstFile();
+	std::string filepath = file_picker.getFirstFile();
+
+	const std::string extension = gDirUtilp->getExtension(filepath);
+	if ("xcu" == extension)
+	{
+		filepath = parseXcuFile(filepath);
+		if (filepath.empty())
+		{
+			return;
+		}
+	}
+
 	getChild<LLUICtrl>("dictionary_path")->setValue(filepath);
 	
 	mDictionaryDir = gDirUtilp->getDirName(filepath);
@@ -398,3 +409,77 @@ bool LLFloaterSpellCheckerImport::copyFile(const std::string from, const std::st
 	fclose(in);
 	return copied;
 }
+
+std::string LLFloaterSpellCheckerImport::parseXcuFile(const std::string& file_path) const
+{
+	LLXMLNodePtr xml_root;
+	if ( (!LLUICtrlFactory::getLayeredXMLNode(file_path, xml_root)) || (xml_root.isNull()) )
+	{
+		return LLStringUtil::null;
+	}
+
+	// Bury down to the "Dictionaries" parent node
+	LLXMLNode* dict_node = NULL;
+	for (LLXMLNode* outer_node = xml_root->getFirstChild(); outer_node && !dict_node; outer_node = outer_node->getNextSibling())
+	{
+		std::string temp;
+		if ( (outer_node->getAttributeString("oor:name", temp)) && ("ServiceManager" == temp) )
+		{
+			for (LLXMLNode* inner_node = outer_node->getFirstChild(); inner_node && !dict_node; inner_node = inner_node->getNextSibling())
+			{
+				if ( (inner_node->getAttributeString("oor:name", temp)) && ("Dictionaries" == temp) )
+				{
+					dict_node = inner_node;
+					break;
+				}
+			}
+		}
+	}
+
+	if (dict_node)
+	{
+		// Iterate over all child nodes until we find one that has a <value>DICT_SPELL</value> node
+		for (LLXMLNode* outer_node = dict_node->getFirstChild(); outer_node; outer_node = outer_node->getNextSibling())
+		{
+			std::string temp;
+			LLXMLNodePtr location_node, format_node;
+			for (LLXMLNode* inner_node = outer_node->getFirstChild(); inner_node; inner_node = inner_node->getNextSibling())
+			{
+				if (inner_node->getAttributeString("oor:name", temp))
+				{
+					if ("Locations" == temp)
+					{
+						inner_node->getChild("value", location_node, false);
+					}
+					else if ("Format" == temp)
+					{
+						inner_node->getChild("value", format_node, false);
+					}
+				}
+			}
+			if ( (format_node.isNull()) || ("DICT_SPELL" != format_node->getValue()) || (location_node.isNull()) )
+			{
+				continue;
+			}
+
+			// Found a list of file locations, return the .dic (if present)
+			std::list<std::string> location_list;
+			boost::split(location_list, location_node->getValue(), boost::is_any_of(std::string(" ")));
+			for (std::list<std::string>::iterator it = location_list.begin(); it != location_list.end(); ++it)
+			{
+				std::string& location = *it;
+				if ("\\" != gDirUtilp->getDirDelimiter())
+					LLStringUtil::replaceString(location, "\\", gDirUtilp->getDirDelimiter());
+				else
+					LLStringUtil::replaceString(location, "/", gDirUtilp->getDirDelimiter());
+				LLStringUtil::replaceString(location, "%origin%", gDirUtilp->getDirName(file_path));
+				if ("dic" == gDirUtilp->getExtension(location))
+				{
+					return location;
+				}
+			}
+		}
+	}
+
+	return LLStringUtil::null;
+}
diff --git a/indra/newview/llfloaterspellchecksettings.h b/indra/newview/llfloaterspellchecksettings.h
index 8c4ac22bc6770b286603c9923c865d31726e94e6..eded3a9133d0c8b751c34d3af31c878c80289ce3 100644
--- a/indra/newview/llfloaterspellchecksettings.h
+++ b/indra/newview/llfloaterspellchecksettings.h
@@ -59,6 +59,7 @@ class LLFloaterSpellCheckerImport : public LLFloater
 	void onBtnCancel();
 	void onBtnOK();
 	bool copyFile(const std::string from, const std::string to);
+	std::string parseXcuFile(const std::string& file_path) const;
 
 	std::string mDictionaryDir;
 	std::string mDictionaryBasename;