From f2d61c7371171e0ee1329186116c585aa5de7f52 Mon Sep 17 00:00:00 2001
From: Merov Linden <merov@lindenlab.com>
Date: Wed, 1 Sep 2010 14:41:51 -0700
Subject: VWR-22759 : port of SNOW-667, Automatic language translation of chat
 messages

---
 doc/contributions.txt                              |   6 +
 indra/cmake/FindJsonCpp.cmake                      |  55 +++++++++
 indra/cmake/JsonCpp.cmake                          |  22 ++++
 indra/newview/CMakeLists.txt                       |   5 +
 indra/newview/app_settings/settings.xml            |  22 ++++
 indra/newview/lltranslate.cpp                      | 123 ++++++++++++++++++++
 indra/newview/lltranslate.h                        | 124 +++++++++++++++++++++
 indra/newview/llviewermessage.cpp                  |  62 ++++++++++-
 .../default/xui/da/panel_preferences_chat.xml      |  23 ++++
 .../default/xui/de/panel_preferences_chat.xml      |  23 ++++
 .../skins/default/xui/en/floater_nearby_chat.xml   |  16 ++-
 .../default/xui/en/panel_preferences_chat.xml      | 120 ++++++++++++++++++--
 .../default/xui/es/panel_preferences_chat.xml      |  23 ++++
 .../default/xui/fr/panel_preferences_chat.xml      |  23 ++++
 .../default/xui/it/panel_preferences_chat.xml      |  23 ++++
 .../default/xui/ja/panel_preferences_chat.xml      |  23 ++++
 .../default/xui/pl/panel_preferences_chat.xml      |  23 ++++
 .../default/xui/pt/panel_preferences_chat.xml      |  23 ++++
 install.xml                                        |  47 ++++++++
 19 files changed, 773 insertions(+), 13 deletions(-)
 create mode 100644 indra/cmake/FindJsonCpp.cmake
 create mode 100644 indra/cmake/JsonCpp.cmake
 create mode 100644 indra/newview/lltranslate.cpp
 create mode 100644 indra/newview/lltranslate.h

diff --git a/doc/contributions.txt b/doc/contributions.txt
index a3c139a7a2..492a7283fe 100644
--- a/doc/contributions.txt
+++ b/doc/contributions.txt
@@ -67,6 +67,7 @@ Aleric Inglewood
 	SNOW-766
 Ales Beaumont
 	VWR-9352
+	SNOW-240
 Alissa Sabre
 	VWR-81
 	VWR-83
@@ -517,6 +518,8 @@ princess niven
 	CT-352
 Renault Clio
 	VWR-1976
+resu Ampan
+	SNOW-93
 Ringo Tuxing
 	CT-225
 	CT-226
@@ -578,6 +581,8 @@ Sergen Davies
 	CT-230
 	CT-231
 	CT-321
+Shawn Kaufmat
+	SNOW-240
 SignpostMarv Martin
 	VWR-153
 	VWR-154
@@ -669,6 +674,7 @@ Whoops Babii
 	VWR-631
 	VWR-1640
 	VWR-3340
+	SNOW-667
 	VWR-4800
 	VWR-4802
 	VWR-4804
diff --git a/indra/cmake/FindJsonCpp.cmake b/indra/cmake/FindJsonCpp.cmake
new file mode 100644
index 0000000000..9d16f2aaab
--- /dev/null
+++ b/indra/cmake/FindJsonCpp.cmake
@@ -0,0 +1,55 @@
+# -*- cmake -*-
+
+# - Find JSONCpp
+# Find the JSONCpp includes and library
+# This module defines
+#  JSONCPP_INCLUDE_DIR, where to find json.h, etc.
+#  JSONCPP_LIBRARIES, the libraries needed to use jsoncpp.
+#  JSONCPP_FOUND, If false, do not try to use jsoncpp.
+#  also defined, but not for general use are
+#  JSONCPP_LIBRARY, where to find the jsoncpp library.
+
+FIND_PATH(JSONCPP_INCLUDE_DIR jsoncpp/json.h
+/usr/local/include
+/usr/include
+)
+
+# Get the GCC compiler version
+EXEC_PROGRAM(${CMAKE_CXX_COMPILER}
+            ARGS ${CMAKE_CXX_COMPILER_ARG1} -dumpversion
+            OUTPUT_VARIABLE _gcc_COMPILER_VERSION
+            OUTPUT_STRIP_TRAILING_WHITESPACE
+            )
+
+SET(JSONCPP_NAMES ${JSONCPP_NAMES} libjson_linux-gcc-${_gcc_COMPILER_VERSION}_libmt.so)
+FIND_LIBRARY(JSONCPP_LIBRARY
+  NAMES ${JSONCPP_NAMES}
+  PATHS /usr/lib /usr/local/lib
+  )
+
+IF (JSONCPP_LIBRARY AND JSONCPP_INCLUDE_DIR)
+    SET(JSONCPP_LIBRARIES ${JSONCPP_LIBRARY})
+    SET(JSONCPP_FOUND "YES")
+ELSE (JSONCPP_LIBRARY AND JSONCPP_INCLUDE_DIR)
+  SET(JSONCPP_FOUND "NO")
+ENDIF (JSONCPP_LIBRARY AND JSONCPP_INCLUDE_DIR)
+
+
+IF (JSONCPP_FOUND)
+   IF (NOT JSONCPP_FIND_QUIETLY)
+      MESSAGE(STATUS "Found JSONCpp: ${JSONCPP_LIBRARIES}")
+   ENDIF (NOT JSONCPP_FIND_QUIETLY)
+ELSE (JSONCPP_FOUND)
+   IF (JSONCPP_FIND_REQUIRED)
+      MESSAGE(FATAL_ERROR "Could not find JSONCpp library")
+   ENDIF (JSONCPP_FIND_REQUIRED)
+ENDIF (JSONCPP_FOUND)
+
+# Deprecated declarations.
+SET (NATIVE_JSONCPP_INCLUDE_PATH ${JSONCPP_INCLUDE_DIR} )
+GET_FILENAME_COMPONENT (NATIVE_JSONCPP_LIB_PATH ${JSONCPP_LIBRARY} PATH)
+
+MARK_AS_ADVANCED(
+  JSONCPP_LIBRARY
+  JSONCPP_INCLUDE_DIR
+  )
diff --git a/indra/cmake/JsonCpp.cmake b/indra/cmake/JsonCpp.cmake
new file mode 100644
index 0000000000..7dd565be7c
--- /dev/null
+++ b/indra/cmake/JsonCpp.cmake
@@ -0,0 +1,22 @@
+# -*- cmake -*-
+
+include(Prebuilt)
+
+set(JSONCPP_FIND_QUIETLY ON)
+set(JSONCPP_FIND_REQUIRED ON)
+
+if (STANDALONE)
+  include(FindJsonCpp)
+else (STANDALONE)
+  use_prebuilt_binary(jsoncpp)
+  if (WINDOWS)
+    set(JSONCPP_LIBRARIES 
+      debug json_vc80d
+      optimized json_vc80)
+  elseif (DARWIN)
+    set(JSONCPP_LIBRARIES json_mac-universal-gcc_libmt)
+  elseif (LINUX)
+    set(JSONCPP_LIBRARIES jsoncpp)
+  endif (WINDOWS)
+  set(JSONCPP_INCLUDE_DIRS ${LIBS_PREBUILT_DIR}/include/jsoncpp)
+endif (STANDALONE)
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 630902c48f..34373e9865 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -13,6 +13,7 @@ include(ELFIO)
 include(FMOD)
 include(OPENAL)
 include(FindOpenGL)
+include(JsonCpp)
 include(LLAudio)
 include(LLCharacter)
 include(LLCommon)
@@ -44,6 +45,7 @@ include(CMakeCopyIfDifferent)
 include_directories(
     ${DBUSGLIB_INCLUDE_DIRS}
     ${ELFIO_INCLUDE_DIR}
+    ${JSONCPP_INCLUDE_DIRS}
     ${LLAUDIO_INCLUDE_DIRS}
     ${LLCHARACTER_INCLUDE_DIRS}
     ${LLCOMMON_INCLUDE_DIRS}
@@ -456,6 +458,7 @@ set(viewer_SOURCE_FILES
     lltracker.cpp
     lltransientdockablefloater.cpp
     lltransientfloatermgr.cpp
+    lltranslate.cpp
     lluilistener.cpp
     lluploaddialog.cpp
     llurl.cpp
@@ -979,6 +982,7 @@ set(viewer_HEADER_FILES
     lltracker.h
     lltransientdockablefloater.h
     lltransientfloatermgr.h
+    lltranslate.h
     lluiconstants.h
     lluilistener.h
     lluploaddialog.h
@@ -1648,6 +1652,7 @@ target_link_libraries(${VIEWER_BINARY_NAME}
     ${OPENGL_LIBRARIES}
     ${FMODWRAPPER_LIBRARY} # must come after LLAudio
     ${OPENGL_LIBRARIES}
+    ${JSONCPP_LIBRARIES}
     ${SDL_LIBRARY}
     ${SMARTHEAP_LIBRARY}
     ${UI_LIBRARIES}
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 9d911777d1..74a9a1e166 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -9825,6 +9825,28 @@
       <key>Value</key>
       <integer>1</integer>
     </map>
+    <key>TranslateLanguage</key>
+    <map>
+      <key>Comment</key>
+      <string>Translate Language specifier</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>String</string>
+      <key>Value</key>
+      <string>default</string>
+    </map>
+    <key>TranslateChat</key>
+    <map>
+      <key>Comment</key>
+      <string>Translate incoming chat messages</string>
+      <key>Persist</key>
+      <integer>1</integer>
+      <key>Type</key>
+      <string>Boolean</string>
+      <key>Value</key>
+      <integer>0</integer>
+    </map>
     <key>TutorialURL</key>
     <map>
       <key>Comment</key>
diff --git a/indra/newview/lltranslate.cpp b/indra/newview/lltranslate.cpp
new file mode 100644
index 0000000000..050e34ade9
--- /dev/null
+++ b/indra/newview/lltranslate.cpp
@@ -0,0 +1,123 @@
+/**
+* @file lltranslate.cpp
+* @brief Functions for translating text via Google Translate.
+*
+* $LicenseInfo:firstyear=2009&license=viewergpl$
+*
+* Copyright (c) 2009-2010, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+
+#include "llviewerprecompiledheaders.h"
+
+#include "lltranslate.h"
+
+#include "llbufferstream.h"
+#include "llui.h"
+#include "llversionviewer.h"
+#include "llviewercontrol.h"
+
+#include "jsoncpp/reader.h"
+
+// These two are concatenated with the language specifiers to form a complete Google Translate URL
+const char* LLTranslate::m_GoogleURL = "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&q=";
+const char* LLTranslate::m_GoogleLangSpec = "&langpair=";
+float LLTranslate::m_GoogleTimeout = 5;
+
+LLSD LLTranslate::m_Header;
+// These constants are for the GET header.
+const char* LLTranslate::m_AcceptHeader = "Accept";
+const char* LLTranslate::m_AcceptType = "text/plain";
+const char* LLTranslate::m_AgentHeader = "User-Agent";
+
+// These constants are in the JSON returned from Google
+const char* LLTranslate::m_GoogleData = "responseData";
+const char* LLTranslate::m_GoogleTranslation = "translatedText";
+const char* LLTranslate::m_GoogleLanguage = "detectedSourceLanguage";
+
+//static
+void LLTranslate::translateMessage(LLHTTPClient::ResponderPtr &result, const std::string &from_lang, const std::string &to_lang, const std::string &mesg)
+{
+	std::string url;
+	getTranslateUrl(url, from_lang, to_lang, mesg);
+
+    std::string user_agent = llformat("%s %d.%d.%d (%d)",
+		LL_CHANNEL,
+		LL_VERSION_MAJOR,
+		LL_VERSION_MINOR,
+		LL_VERSION_PATCH,
+		LL_VERSION_BUILD );
+
+	if (!m_Header.size())
+	{
+		m_Header.insert(m_AcceptHeader, LLSD(m_AcceptType));
+		m_Header.insert(m_AgentHeader, LLSD(user_agent));
+	}
+
+	LLHTTPClient::get(url, result, m_Header, m_GoogleTimeout);
+}
+
+//static
+void LLTranslate::getTranslateUrl(std::string &translate_url, const std::string &from_lang, const std::string &to_lang, const std::string &mesg)
+{
+	std::string escaped_mesg = curl_escape(mesg.c_str(), mesg.size());
+
+	translate_url = m_GoogleURL
+		+ escaped_mesg + m_GoogleLangSpec
+		+ from_lang // 'from' language; empty string for auto
+		+ "%7C" // |
+		+ to_lang; // 'to' language
+}
+
+//static
+bool LLTranslate::parseGoogleTranslate(const std::string& body, std::string &translation, std::string &detected_language)
+{
+	Json::Value root;
+	Json::Reader reader;
+	
+	bool success = reader.parse(body, root);
+	if (!success)
+	{
+		LL_WARNS("Translate") << "Non valid response from Google Translate API: '" << reader.getFormatedErrorMessages() << "'" << LL_ENDL;
+		return false;
+	}
+	
+	translation = 			root[m_GoogleData].get(m_GoogleTranslation, "").asString();
+	detected_language = 	root[m_GoogleData].get(m_GoogleLanguage, "").asString();
+	return true;
+}
+
+//static
+std::string LLTranslate::getTranslateLanguage()
+{
+	std::string language = gSavedSettings.getString("TranslateLanguage");
+	if (language.empty() || language == "default")
+	{
+		language = LLUI::getLanguage();
+	}
+	language = language.substr(0,2);
+	return language;
+}
+
diff --git a/indra/newview/lltranslate.h b/indra/newview/lltranslate.h
new file mode 100644
index 0000000000..0786dc0ca3
--- /dev/null
+++ b/indra/newview/lltranslate.h
@@ -0,0 +1,124 @@
+/**
+* @file lltranslate.h
+* @brief Human language translation class and JSON response receiver.
+*
+* $LicenseInfo:firstyear=2009&license=viewergpl$
+*
+* Copyright (c) 2009-2010, Linden Research, Inc.
+*
+* Second Life Viewer Source Code
+* The source code in this file ("Source Code") is provided by Linden Lab
+* to you under the terms of the GNU General Public License, version 2.0
+* ("GPL"), unless you have obtained a separate licensing agreement
+* ("Other License"), formally executed by you and Linden Lab. Terms of
+* the GPL can be found in doc/GPL-license.txt in this distribution, or
+* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+*
+* There are special exceptions to the terms and conditions of the GPL as
+* it is applied to this Source Code. View the full text of the exception
+* in the file doc/FLOSS-exception.txt in this software distribution, or
+* online at
+* http://secondlifegrid.net/programs/open_source/licensing/flossexception
+*
+* By copying, modifying or distributing this software, you acknowledge
+* that you have read and understood your obligations described above,
+* and agree to abide by those obligations.
+*
+* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+* COMPLETENESS OR PERFORMANCE.
+* $/LicenseInfo$
+*/
+
+#ifndef LL_LLTRANSLATE_H
+#define LL_LLTRANSLATE_H
+
+#include "llhttpclient.h"
+#include "llbufferstream.h"
+
+class LLTranslate
+{
+	LOG_CLASS(LLTranslate);
+public :
+	class TranslationReceiver: public LLHTTPClient::Responder
+	{
+	protected:
+		TranslationReceiver(const std::string &from_lang, const std::string &to_lang)
+			: m_fromLang(from_lang),
+			m_toLang(to_lang)
+		{
+		}
+
+		virtual void handleResponse(const std::string &translation, const std::string &recognized_lang) {};
+		virtual void handleFailure() {};
+
+	public:
+		~TranslationReceiver()
+		{
+		}
+
+		virtual void completedRaw(	U32 status,
+									const std::string& reason,
+									const LLChannelDescriptors& channels,
+									const LLIOPipe::buffer_ptr_t& buffer)
+		{
+			if (200 <= status && status < 300)
+			{
+				LLBufferStream istr(channels, buffer.get());
+				std::stringstream strstrm;
+				strstrm << istr.rdbuf();
+
+				const std::string result = strstrm.str();
+				std::string translation;
+				std::string detected_language;
+
+				if (!parseGoogleTranslate(result, translation, detected_language))
+				{
+					handleFailure();
+					return;
+				}
+				
+				// Fix up the response
+				LLStringUtil::replaceString(translation, "&lt;", "<");
+				LLStringUtil::replaceString(translation, "&gt;",">");
+				LLStringUtil::replaceString(translation, "&quot;","\"");
+				LLStringUtil::replaceString(translation, "&#39;","'");
+				LLStringUtil::replaceString(translation, "&amp;","&");
+				LLStringUtil::replaceString(translation, "&apos;","'");
+
+				handleResponse(translation, detected_language);
+			}
+			else
+			{
+				LL_WARNS("Translate") << "HTTP request for Google Translate failed with status " << status << ", reason: " << reason << LL_ENDL;
+				handleFailure();
+			}
+		}
+
+	protected:
+		const std::string m_toLang;
+		const std::string m_fromLang;
+	};
+
+	static void translateMessage(LLHTTPClient::ResponderPtr &result, const std::string &from_lang, const std::string &to_lang, const std::string &mesg);
+	static float m_GoogleTimeout;
+	static std::string getTranslateLanguage();
+
+private:
+	static void getTranslateUrl(std::string &translate_url, const std::string &from_lang, const std::string &to_lang, const std::string &text);
+	static bool parseGoogleTranslate(const std::string& body, std::string &translation, std::string &detected_language);
+
+	static LLSD m_Header;
+	static const char* m_GoogleURL;
+	static const char* m_GoogleLangSpec;
+	static const char* m_AcceptHeader;
+	static const char* m_AcceptType;
+	static const char* m_AgentHeader;
+	static const char* m_UserAgent;
+
+	static const char* m_GoogleData;
+	static const char* m_GoogleTranslation;
+	static const char* m_GoogleLanguage;
+};
+
+#endif
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index 82bc084f68..85759319a6 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -77,6 +77,7 @@
 #include "llimview.h"
 #include "llspeakers.h"
 #include "lltrans.h"
+#include "lltranslate.h"
 #include "llviewerfoldertype.h"
 #include "lluri.h"
 #include "llviewergenericmessage.h"
@@ -2909,6 +2910,50 @@ void process_decline_callingcard(LLMessageSystem* msg, void**)
 	LLNotificationsUtil::add("CallingCardDeclined");
 }
 
+class ChatTranslationReceiver : public LLTranslate::TranslationReceiver
+{
+public :
+	ChatTranslationReceiver(const std::string &from_lang, const std::string &to_lang, const std::string &mesg,
+							const LLChat &chat, const LLSD &toast_args)
+		: LLTranslate::TranslationReceiver(from_lang, to_lang),
+		m_chat(chat),
+		m_toastArgs(toast_args),
+		m_origMesg(mesg)
+	{
+	}
+
+	static boost::intrusive_ptr<ChatTranslationReceiver> build(const std::string &from_lang, const std::string &to_lang, const std::string &mesg, const LLChat &chat, const LLSD &toast_args)
+	{
+		return boost::intrusive_ptr<ChatTranslationReceiver>(new ChatTranslationReceiver(from_lang, to_lang, mesg, chat, toast_args));
+	}
+
+protected:
+	void handleResponse(const std::string &translation, const std::string &detected_language)
+	{
+		// filter out non-interesting responeses
+		if ( !translation.empty()
+			&& (m_toLang != detected_language)
+			&& (LLStringUtil::compareInsensitive(translation, m_origMesg) != 0) )
+		{
+			m_chat.mText += " (" + translation + ")";
+		}
+
+		LLNotificationsUI::LLNotificationManager::instance().onChat(m_chat, m_toastArgs);
+	}
+
+	void handleFailure()
+	{
+		LLTranslate::TranslationReceiver::handleFailure();
+		m_chat.mText += " (?)";
+
+		LLNotificationsUI::LLNotificationManager::instance().onChat(m_chat, m_toastArgs);
+	}
+
+private:
+	LLChat m_chat;
+	std::string m_origMesg;
+	LLSD m_toastArgs;		
+};
 
 void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
 {
@@ -3112,7 +3157,22 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
 		args["type"] = LLNotificationsUI::NT_NEARBYCHAT;
 		chat.mOwnerID = owner_id;
 
-		LLNotificationsUI::LLNotificationManager::instance().onChat(chat, args);
+		if (gSavedSettings.getBOOL("TranslateChat") && chat.mSourceType != CHAT_SOURCE_SYSTEM)
+		{
+			if (chat.mChatStyle == CHAT_STYLE_IRC)
+			{
+				mesg = mesg.substr(4, std::string::npos);
+			}
+			const std::string from_lang = ""; // leave empty to trigger autodetect
+			const std::string to_lang = LLTranslate::getTranslateLanguage();
+
+			LLHTTPClient::ResponderPtr result = ChatTranslationReceiver::build(from_lang, to_lang, mesg, chat, args);
+			LLTranslate::translateMessage(result, from_lang, to_lang, mesg);
+		}
+		else
+		{
+			LLNotificationsUI::LLNotificationManager::instance().onChat(chat, args);
+		}
 	}
 }
 
diff --git a/indra/newview/skins/default/xui/da/panel_preferences_chat.xml b/indra/newview/skins/default/xui/da/panel_preferences_chat.xml
index 20a376f152..7d17f80268 100644
--- a/indra/newview/skins/default/xui/da/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/da/panel_preferences_chat.xml
@@ -56,4 +56,27 @@
 		<radio_item label="Separate vinduer" name="radio" value="0"/>
 		<radio_item label="Faner" name="radio2" value="1"/>
 	</radio_group>
+	<check_box label="OversÊt Chat" name="translate_chat_checkbox" />
+	<text name="translate_language_text" width="110">
+		Chat Sprog:
+	</text>
+	<combo_box name="translate_language_combobox" width="146">
+		<combo_box.item label="System standard" name="System Default Language"/>
+		<combo_box.item label="English (Engelsk)" name="English"/>
+		<combo_box.item label="Dansk" name="Danish"/>
+		<combo_box.item label="Deutsch (Tysk)" name="German"/>
+		<combo_box.item label="Español (Spansk)" name="Spanish"/>
+		<combo_box.item label="Français (Fransk)" name="French"/>
+		<combo_box.item label="Italiano (Italiensk)" name="Italian" />
+		<combo_box.item label="Magyar (Ungarsk)" name="Hungarian" />
+		<combo_box.item label="Nederlands (Hollandsk)" name="Dutch" />
+		<combo_box.item label="Polski (Polsk)" name="Polish" />
+		<combo_box.item label="Portugués (Portugisisk)" name="Portugese" />
+		<combo_box.item label="РусскОй (Russisk)" name="Russian" />
+		<combo_box.item label="TÌrkçe (Tyrkisk)" name="Turkish" />
+		<combo_box.item label="УкраїМська (Ukrainsk)" name="Ukrainian" />
+		<combo_box.item label="äž­æ–‡ (简䜓) (Kinesisk)" name="Chinese" />
+		<combo_box.item label="日本語 (Japansk)" name="Japanese" />
+		<combo_box.item label="한국얎 (Koreansk)" name="Korean" />
+	</combo_box>
 </panel>
diff --git a/indra/newview/skins/default/xui/de/panel_preferences_chat.xml b/indra/newview/skins/default/xui/de/panel_preferences_chat.xml
index 5c91b34a21..d8039dd380 100644
--- a/indra/newview/skins/default/xui/de/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/de/panel_preferences_chat.xml
@@ -56,4 +56,27 @@
 		<radio_item label="Getrennte Fenster" name="radio" value="0"/>
 		<radio_item label="Registerkarten" name="radio2" value="1"/>
 	</radio_group>
+	<check_box label="Übersetzen Chat" name="translate_chat_checkbox" />
+	<text name="translate_language_text">
+		Chat-Sprache:
+	</text>
+	<combo_box name="translate_language_combobox" width="200">
+		<combo_box.item name="System Default Language" label="Betriebssystem-Einstellung" />
+		<combo_box.item name="English" label="English (Englisch)" />
+		<combo_box.item name="Danish" label="Danks (DÀnisch)" />
+		<combo_box.item name="German" label="Deutsch" />
+		<combo_box.item name="Spanish" label="Español (Spanisch)" />
+		<combo_box.item name="French" label="Français (Französisch)" />
+		<combo_box.item name="Italian" label="Italiano (Italienisch)" />
+		<combo_box.item name="Hungarian" label="Magyar (Ungarisch)" />
+		<combo_box.item name="Dutch" label="Nederlands (NiederlÀndisch)" />
+		<combo_box.item name="Polish" label="Polski (Polnisch)" />
+		<combo_box.item name="Portugese" label="Português (Portugiesisch)" />
+		<combo_box.item name="Russian" label="РусскОй (Russian)" />
+		<combo_box.item name="Turkish" label="TÌrkçe (TÌrkisch)" />
+		<combo_box.item name="Ukrainian" label="УкраїМська (Ukrainisch)" />
+		<combo_box.item name="Chinese" label="äž­æ–‡ (简䜓) (Chinesisch)" />
+		<combo_box.item name="Japanese" label="日本語 (Japanisch)" />
+		<combo_box.item name="Korean" label="한국얎 (Koreanisch)" />
+	</combo_box>
 </panel>
diff --git a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
index 3b26c2ab59..4c5113aa55 100644
--- a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
+++ b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
@@ -14,7 +14,7 @@
  can_dock="true"
  bevel_style="in"
  height="300"
- min_width="150"
+ min_width="235"
  layout="topleft"
  name="nearby_chat"
  help_topic="nearby_chat"
@@ -24,15 +24,25 @@
  save_visibility="true"
  single_instance="true"
  width="320">
+            <check_box
+             bottom_delta="36"
+             control_name="TranslateChat"
+             enabled="true"
+             height="16"
+             label="Translate chat (powered by Google)"
+             layout="topleft"
+             left="5"
+             name="translate_chat_checkbox"
+             width="230" />
   <chat_history
     parse_urls="true"
     bg_readonly_color="ChatHistoryBgColor"
     bg_writeable_color="ChatHistoryBgColor"
     follows="all"
     left="5"
-    top="20"
+    top_delta="17"
     layout="topleft"
-    height="275"
+    height="260"
     name="chat_history"
     parse_highlights="true"
     text_color="ChatHistoryTextColor"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml
index ba967d3e2c..9e53180d1f 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml
@@ -104,7 +104,7 @@
      layout="topleft"
      left="190"
      name="agent"
-     top_pad="-17"
+     top_pad="-15"
      width="44" >
 		<color_swatch.init_callback
 		 function="Pref.getUIColor"
@@ -135,7 +135,7 @@
      layout="topleft"
      left="360"
      name="im"
-     top_pad="-17"
+     top_pad="-15"
      width="44">
 		<color_swatch.init_callback
 		 function="Pref.getUIColor"
@@ -166,7 +166,7 @@
      layout="topleft"
      left="40"
      name="system"
-     top_pad="40"
+     top_pad="22"
      width="44" >
 		<color_swatch.init_callback
 		 function="Pref.getUIColor"
@@ -196,7 +196,7 @@
      layout="topleft"
      left="190"
      name="script_error"
-     top_pad="-17"
+     top_pad="-15"
      width="44">
 		<color_swatch.init_callback
 		 function="Pref.getUIColor"
@@ -226,7 +226,7 @@
      layout="topleft"
      left="360"
      name="objects"
-     top_pad="-17"
+     top_pad="-15"
      width="44" >
 		<color_swatch.init_callback
 		 function="Pref.getUIColor"
@@ -256,7 +256,7 @@
      layout="topleft"
      left="40"
      name="owner"
-     top_pad="40"
+     top_pad="22"
      width="44" >
 		<color_swatch.init_callback
 		 function="Pref.getUIColor"
@@ -286,7 +286,7 @@
      layout="topleft"
      left="190"
      name="links"
-     top_pad="-17"
+     top_pad="-15"
      width="44" >
 		<color_swatch.init_callback
 		 function="Pref.getUIColor"
@@ -316,7 +316,7 @@
      layout="topleft"
      left="30"
      name="play_typing_animation"
-     top_pad="40"
+     top_pad="32"
      width="400" />
     <check_box
      enabled="false"
@@ -343,7 +343,7 @@
      left="30"
      height="20"
      width="170"
-     top_pad="20">
+     top_pad="14">
      Show IMs in:
     </text>
     <text
@@ -386,4 +386,106 @@
       top_pad="5"
       width="150" />
     </radio_group>
+    <check_box
+     control_name="TranslateChat"
+     enabled="true"
+     height="16"
+     label="Use machine translation while chatting (powered by Google)"
+     layout="topleft"
+     left="30"
+     name="translate_chat_checkbox"
+     bottom_delta="40"
+     width="400" />
+    <text
+     bottom_delta="30"
+     name="translate_language_text"
+     follows="left|top"
+     layout="topleft"
+     left_delta="20"
+     height="20"
+     width="110">
+     Translate chat into: 
+    </text>
+    <combo_box
+     allow_text_entry="true"
+     bottom_delta="3"
+     control_name="TranslateLanguage"
+     enabled="true"
+     follows="left|top"
+     height="23"
+     left_delta="110"
+     max_chars="135"
+     mouse_opaque="true"
+     name="translate_language_combobox"
+     width="146">
+        <combo_box.item
+         label="System Default"
+         name="System Default Language"
+         value="default" />
+        <combo_box.item
+         label="English"
+         name="English"
+         value="en" />
+        <!-- After "System Default" and "English", please keep the rest of these combo_box.items in alphabetical order by the first character in the string. -->
+        <combo_box.item
+         label="Dansk (Danish)"
+         name="Danish"
+         value="da" />
+        <combo_box.item
+         label="Deutsch (German)"
+         name="German"
+         value="de" />
+        <combo_box.item
+         label="Español (Spanish)"
+         name="Spanish"
+         value="es" />
+        <combo_box.item
+         label="Français (French)"
+         name="French"
+         value="fr" />
+        <combo_box.item
+         label="Italiano (Italian)"
+         name="Italian"
+         value="it" />
+        <combo_box.item
+         label="Magyar (Hungarian)"
+         name="Hungarian"
+         value="hu" />
+        <combo_box.item
+         label="Nederlands (Dutch)"
+         name="Dutch"
+         value="nl" />
+        <combo_box.item
+         label="Polski (Polish)"
+         name="Polish"
+         value="pl" />
+        <combo_box.item
+         label="Portugués (Portuguese)"
+         name="Portugese"
+         value="pt" />
+        <combo_box.item
+         label="РусскОй (Russian)"
+         name="Russian"
+         value="ru" />
+        <combo_box.item
+         label="TÌrkçe (Turkish)"
+         name="Turkish"
+         value="tr" />
+        <combo_box.item
+         label="УкраїМська (Ukrainian)"
+         name="Ukrainian"
+         value="uk" />
+        <combo_box.item
+         label="äž­æ–‡ (简䜓) (Chinese)"
+         name="Chinese"
+         value="zh" />
+        <combo_box.item
+         label="日本語 (Japanese)"
+         name="Japanese"
+         value="ja" />
+        <combo_box.item
+         label="한국얎 (Korean)"
+         name="Korean"
+         value="ko" />
+    </combo_box>
 </panel>
diff --git a/indra/newview/skins/default/xui/es/panel_preferences_chat.xml b/indra/newview/skins/default/xui/es/panel_preferences_chat.xml
index fc8c908788..14d84e5edf 100644
--- a/indra/newview/skins/default/xui/es/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/es/panel_preferences_chat.xml
@@ -56,4 +56,27 @@
 		<radio_item label="Varias ventanas" name="radio" value="0"/>
 		<radio_item label="Pestañas" name="radio2" value="1"/>
 	</radio_group>
+	<check_box label="Traducir Chat" name="translate_chat_checkbox" />
+	<text name="translate_language_text">
+		Idioma de chat:
+	</text>
+	<combo_box name="translate_language_combobox">
+		<combo_box.item name="System Default Language" label="Predeterminado del sistema" />
+		<combo_box.item name="English" label="English (Inglés)" />
+		<combo_box.item name="Danish" label="Dansk (Danés)" />
+		<combo_box.item name="German" label="Deutsch (Alemán)" />
+		<combo_box.item name="Spanish" label="Español" />
+		<combo_box.item name="French" label="Français (Francés)" />
+		<combo_box.item name="Italian" label="Italiano" />
+		<combo_box.item name="Hungarian" label="Magyar (Húngaro)" />
+		<combo_box.item name="Dutch" label="Nederlands (Neerlandés)" />
+		<combo_box.item name="Polish" label="Polski (Polaco)" />
+		<combo_box.item name="Portugese" label="Portugués (Portugués)" />
+		<combo_box.item name="Russian" label="РусскОй (Ruso)" />
+		<combo_box.item name="Turkish" label="TÌrkçe (Turco)" />
+		<combo_box.item name="Ukrainian" label="УкраїМська (Ucraniano)" />
+		<combo_box.item name="Chinese" label="äž­æ–‡ (简䜓) (Chino)" />
+		<combo_box.item name="Japanese" label="日本語 (Japonés)" />
+		<combo_box.item name="Korean" label="한국얎 (Coreano)" />
+	</combo_box>
 </panel>
diff --git a/indra/newview/skins/default/xui/fr/panel_preferences_chat.xml b/indra/newview/skins/default/xui/fr/panel_preferences_chat.xml
index 76f3319525..cee1a23789 100644
--- a/indra/newview/skins/default/xui/fr/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/fr/panel_preferences_chat.xml
@@ -56,4 +56,27 @@
 		<radio_item label="Plusieurs fenêtres" name="radio" value="0"/>
 		<radio_item label="Onglets" name="radio2" value="1"/>
 	</radio_group>
+		<check_box label="Traduire Chat" name="translate_chat_checkbox" />
+	<text name="translate_language_text">
+		Langue de chat :
+	</text>
+	<combo_box name="translate_language_combobox">
+		<combo_box.item name="System Default Language" label="Choix par défaut" />
+		<combo_box.item name="English" label="English (Anglais" />
+		<combo_box.item name="Danish" label="Dansk (Danois)" />
+		<combo_box.item name="German" label="Deutsch (Allemand)" />
+		<combo_box.item name="Spanish" label="Español (Espagnol)" />
+		<combo_box.item name="French" label="Français" />
+		<combo_box.item name="Italian" label="Italiano (Italien)" />
+		<combo_box.item name="Hungarian" label="Magyar (Hongrois)" />
+		<combo_box.item name="Dutch" label="Nederlands (Néerlandais)" />
+		<combo_box.item name="Polish" label="Polski (Polonais)" />
+		<combo_box.item name="Portugese" label="Portugués (Portugais)" />
+		<combo_box.item name="Russian" label="РусскОй (Russe)" />
+		<combo_box.item name="Turkish" label="TÌrkçe (Turc)" />
+		<combo_box.item name="Ukrainian" label="УкраїМська (Ukrainien)" />
+		<combo_box.item name="Chinese" label="äž­æ–‡ (简䜓) (Chinois)" />
+		<combo_box.item name="Japanese" label="日本語 (Japonais)" />
+		<combo_box.item name="Korean" label="한국얎 (Coréen)" />
+	</combo_box>
 </panel>
diff --git a/indra/newview/skins/default/xui/it/panel_preferences_chat.xml b/indra/newview/skins/default/xui/it/panel_preferences_chat.xml
index fb8ddf607d..4da60dae41 100644
--- a/indra/newview/skins/default/xui/it/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/it/panel_preferences_chat.xml
@@ -56,4 +56,27 @@
 		<radio_item label="Finestre separate" name="radio" value="0"/>
 		<radio_item label="Schede" name="radio2" value="1"/>
 	</radio_group>
+	<check_box label="Traduci Chat" name="translate_chat_checkbox" />
+	<text name="translate_language_text" width="110">
+		Chat Lingua:
+	</text>
+	<combo_box name="translate_language_combobox" width="146">
+		<combo_box.item name="System Default Language" label="Default di sistema" />
+		<combo_box.item name="English" label="English" />
+		<combo_box.item name="Danish" label="Dansk (Danese)" />
+		<combo_box.item name="German" label="Deutsch (Tedesco)" />
+		<combo_box.item name="Spanish" label="Español (Spagnolo)" />
+		<combo_box.item name="French" label="Français (Francese)" />
+		<combo_box.item name="Italian" label="Italiano" />
+		<combo_box.item name="Hungarian" label="Magyar (Ungherese)" />
+		<combo_box.item name="Dutch" label="Nederlands (Olandese)" />
+		<combo_box.item name="Polish" label="Polski (Polacco)" />
+		<combo_box.item name="Portugese" label="Portugués (Portoghese)" />
+		<combo_box.item name="Russian" label="РусскОй (Russo)" />
+		<combo_box.item name="Turkish" label="TÌrkçe (Turco)" />
+		<combo_box.item name="Ukrainian" label="УкраїМська (Ukraino)" />
+		<combo_box.item name="Chinese" label="äž­æ–‡ (简䜓) (Cinese)" />
+		<combo_box.item name="Japanese" label="日本語 (Giapponese)" />
+		<combo_box.item name="Korean" label="한국얎 (Coreano)" />
+	</combo_box>
 </panel>
diff --git a/indra/newview/skins/default/xui/ja/panel_preferences_chat.xml b/indra/newview/skins/default/xui/ja/panel_preferences_chat.xml
index 86f880de09..a053529436 100644
--- a/indra/newview/skins/default/xui/ja/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/ja/panel_preferences_chat.xml
@@ -56,4 +56,27 @@
 		<radio_item label="別々のウィンドウ" name="radio" value="0"/>
 		<radio_item label="タブ" name="radio2" value="1"/>
 	</radio_group>
+		<check_box label="翻蚳チャット" name="translate_chat_checkbox" />
+	<text name="translate_language_text">
+		チャット蚀語:
+	</text>
+	<combo_box name="translate_language_combobox">
+		<combo_box.item name="System Default Language" label="システム・デフォルト" />
+		<combo_box.item name="English" label="English (英語)" />
+		<combo_box.item name="Danish" label="Dansk (デンマヌク語)" />
+		<combo_box.item name="German" label="Deutsch (ドむツ語)" />
+		<combo_box.item name="Spanish" label="Español (スペむン語)" />
+		<combo_box.item name="French" label="Français (フランス語)" />
+		<combo_box.item name="Italian" label="Italiano むタリア語" />
+		<combo_box.item name="Hungarian" label="Magyar (ハンガリヌ語)" />
+		<combo_box.item name="Dutch" label="Nederlands オランダ語" />
+		<combo_box.item name="Polish" label="Polski (ポヌランド語)" />
+		<combo_box.item name="Portugese" label="Português (ポルトガル語)" />
+		<combo_box.item name="Russian" label="РусскОй (ロシア語)" />
+		<combo_box.item name="Turkish" label="TÃŒrkçe トルコ語" />
+		<combo_box.item name="Ukrainian" label="УкраїМська (りクラむナ語)" />
+		<combo_box.item name="Chinese" label="äž­æ–‡ (简䜓) (䞭囜語)" />
+		<combo_box.item name="Japanese" label="日本語" />
+		<combo_box.item name="Korean" label="한국얎 (韓囜語)" />
+	</combo_box>
 </panel>
diff --git a/indra/newview/skins/default/xui/pl/panel_preferences_chat.xml b/indra/newview/skins/default/xui/pl/panel_preferences_chat.xml
index 5805df402c..424fe7b8df 100644
--- a/indra/newview/skins/default/xui/pl/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/pl/panel_preferences_chat.xml
@@ -56,4 +56,27 @@
 		<radio_item label="Osobne okna" name="radio" value="0"/>
 		<radio_item label="Etykiety" name="radio2" value="1"/>
 	</radio_group>
+	<check_box label="Przetłumacz Czat" name="translate_chat_checkbox" />
+	<text name="translate_language_text">
+		Czat Język:
+	</text>
+	<combo_box name="translate_language_combobox">
+		<combo_box.item name="System Default Language" label="Domyślny" />
+		<combo_box.item name="English" label="English (Angielski)" />
+		<combo_box.item name="Danish" label="Dansk (Duński)" />
+		<combo_box.item name="German" label="Deutsch (Niemiecki)" />
+		<combo_box.item name="Spanish" label="Español (Hiszpański)" />
+		<combo_box.item name="French" label="Français (Francuski)" />
+		<combo_box.item name="Italian" label="Italiano (Włoski)" />
+		<combo_box.item name="Hungarian" label="Magyar (Węgierski)" />
+		<combo_box.item name="Dutch" label="Nederlands (Niderlandzki)" />
+		<combo_box.item name="Polish" label="Polski" />
+		<combo_box.item name="Portugese" label="Portugués (Portugalski)" />
+		<combo_box.item name="Russian" label="РусскОй (Rosyjski)" />
+		<combo_box.item name="Turkish" label="TÌrkçe (Turecki)" />
+		<combo_box.item name="Ukrainian" label="УкраїМська (Ukraiński)" />
+		<combo_box.item name="Chinese" label="äž­æ–‡ (简䜓) (Chiński)" />
+		<combo_box.item name="Japanese" label="日本語 (Japoński)" />
+		<combo_box.item name="Korean" label="한국얎 (Koreański)" />
+	</combo_box>
 </panel>
diff --git a/indra/newview/skins/default/xui/pt/panel_preferences_chat.xml b/indra/newview/skins/default/xui/pt/panel_preferences_chat.xml
index 02b0ef35fe..5b0c546406 100644
--- a/indra/newview/skins/default/xui/pt/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/pt/panel_preferences_chat.xml
@@ -56,4 +56,27 @@
 		<radio_item label="Janelas separadas" name="radio" value="0"/>
 		<radio_item label="Guias" name="radio2" value="1"/>
 	</radio_group>
+	<check_box label="Traduzir Chat" name="translate_chat_checkbox" />
+	<text name="translate_language_text">
+		Chat Língua:
+	</text>
+	<combo_box name="translate_language_combobox">
+		<combo_box.item name="System Default Language" label="Padrão do Sistema" />
+		<combo_box.item name="English" label="English (Inglês)" />
+		<combo_box.item name="Danish" label="Dansk (Dinamarquês)" />
+		<combo_box.item name="German" label="Deutsch (Alemão)" />
+		<combo_box.item name="Spanish" label="Español (Espanhol)" />
+		<combo_box.item name="French" label="Français (Francês)" />
+		<combo_box.item name="Italian" label="Italiano" />
+		<combo_box.item name="Hungarian" label="Magyar (Húngaro)" />
+		<combo_box.item name="Dutch" label="Nederlands (Holandês)" />
+		<combo_box.item name="Polish" label="Polski (Polonês)" />
+		<combo_box.item name="Portugese" label="Português" />
+		<combo_box.item name="Russian" label="РусскОй (Russo)" />
+		<combo_box.item name="Turkish" label="TÌrkçe (Turco)" />
+		<combo_box.item name="Ukrainian" label="УкраїМська (Ucraniano)" />
+		<combo_box.item name="Chinese" label="äž­æ–‡ (简䜓) (Chinês)" />
+		<combo_box.item name="Japanese" label="日本語 (Japonês)" />
+		<combo_box.item name="Korean" label="한국얎 (Coreano)" />
+	</combo_box>
 </panel>
diff --git a/install.xml b/install.xml
index a47a732d56..9c37b4bc1e 100644
--- a/install.xml
+++ b/install.xml
@@ -777,6 +777,46 @@
           </map>
         </map>
       </map>
+      <key>jsoncpp</key>
+      <map>
+        <key>copyright</key>
+        <string>json-cpp library released to Public Domain by Baptiste Lepilleur &lt;blep@users.sourceforge.net&gt;</string>
+        <key>description</key>
+        <string>jsoncpp is an implementation of a JSON (http://json.org) reader and writer in C++.</string>
+        <key>license</key>
+        <string>jsoncpp</string>
+        <key>packages</key>
+        <map>
+          <key>darwin</key>
+          <map>
+            <key>md5sum</key>
+            <string>4c6b949778099a63550898f00f3e6a5e</string>
+            <key>url</key>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/jsoncpp-svn-r69-darwin-20090923.tar.bz2</uri>
+          </map>
+          <key>linux</key>
+          <map>
+            <key>md5sum</key>
+            <string>a2a94b8ca1d32f23e3e668d64023514e</string>
+            <key>url</key>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/jsoncpp-svn-r69-linux-20090922.tar.bz2</uri>
+          </map>
+          <key>linux64</key>
+          <map>
+            <key>md5sum</key>
+            <string>a06ab38628ab7b53b8f3326cd942a6a8</string>
+            <key>url</key>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/jsoncpp-svn-r69-linux64-20090922.tar.bz2</uri>
+          </map>
+          <key>windows</key>
+          <map>
+            <key>md5sum</key>
+            <string>caf152cfc730737c124f7612cf68fbd3</string>
+            <key>url</key>
+            <uri>http://s3.amazonaws.com/viewer-source-downloads/install_pkgs/jsoncpp-svn-r69-windows-20090922.tar.bz2</uri>
+          </map>
+        </map>
+      </map>
       <key>kdu</key>
       <map>
         <key>copyright</key>
@@ -1740,6 +1780,13 @@ Cass Everitt - cass@r3.nu
         <key>text</key>
         <string>http://nyctergatis.com/jpeglib/</string>
       </map>
+      <key>jsoncpp</key>
+      <map>
+        <key>text</key>
+        <string>The json-cpp library and this documentation are in Public Domain.  Retrieved from http://jsoncpp.sourceforge.net/ on 2009-09-04.</string>
+        <key>url</key>
+        <string>http://jsoncpp.sourceforge.net</string>
+      </map>
       <key>kdu</key>
       <map>
         <key>text</key>
-- 
cgit v1.2.3