summaryrefslogtreecommitdiff
path: root/src/plugins/translation/src/com
diff options
context:
space:
mode:
Diffstat (limited to 'src/plugins/translation/src/com')
-rw-r--r--src/plugins/translation/src/com/motorola/studio/android/json/JSONArray.java92
-rw-r--r--src/plugins/translation/src/com/motorola/studio/android/json/JSONBoolean.java77
-rw-r--r--src/plugins/translation/src/com/motorola/studio/android/json/JSONNull.java58
-rw-r--r--src/plugins/translation/src/com/motorola/studio/android/json/JSONNumber.java65
-rw-r--r--src/plugins/translation/src/com/motorola/studio/android/json/JSONObject.java95
-rw-r--r--src/plugins/translation/src/com/motorola/studio/android/json/JSONPair.java109
-rw-r--r--src/plugins/translation/src/com/motorola/studio/android/json/JSONString.java94
-rw-r--r--src/plugins/translation/src/com/motorola/studio/android/json/JSONValue.java28
-rw-r--r--src/plugins/translation/src/com/motorola/studio/android/json/JSONValueParser.java74
-rw-r--r--src/plugins/translation/src/com/motorola/studio/android/json/Jason.java84
-rw-r--r--src/plugins/translation/src/com/motorola/studio/android/localization/translators/GoogleTranslator.java946
-rw-r--r--src/plugins/translation/src/com/motorola/studio/android/localization/translators/GoogleTranslatorConstants.java115
-rw-r--r--src/plugins/translation/src/com/motorola/studio/android/localization/translators/TranslationPlugin.java77
-rw-r--r--src/plugins/translation/src/com/motorola/studio/android/localization/translators/i18n/TranslateNLS.java58
-rw-r--r--src/plugins/translation/src/com/motorola/studio/android/localization/translators/i18n/translateNLS.properties15
-rw-r--r--src/plugins/translation/src/com/motorola/studio/android/localization/translators/preferences/ui/TranslationPreferencePage.java196
16 files changed, 2183 insertions, 0 deletions
diff --git a/src/plugins/translation/src/com/motorola/studio/android/json/JSONArray.java b/src/plugins/translation/src/com/motorola/studio/android/json/JSONArray.java
new file mode 100644
index 0000000..91d2491
--- /dev/null
+++ b/src/plugins/translation/src/com/motorola/studio/android/json/JSONArray.java
@@ -0,0 +1,92 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.motorola.studio.android.json;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Stack;
+
+public class JSONArray extends JSONValue
+{
+ private final List<JSONValue> value;
+
+ public JSONArray(List<JSONValue> value)
+ {
+ this.value = value;
+ }
+
+ @Override
+ public List<JSONValue> getValue()
+ {
+ return value;
+ }
+
+ static JSONValue parseValues(List<Character> json)
+ {
+ Stack<Character> stack = new Stack<Character>();
+ List<JSONValue> values = new ArrayList<JSONValue>();
+ boolean parsed = false;
+ while (!parsed)
+ {
+ Character next = json.get(0);
+ if (next == '[')
+ {
+ json.remove(0);
+ stack.push('[');
+ }
+ else if (next == ']')
+ {
+ json.remove(0);
+ if (stack.pop() != '[')
+ {
+ throw new IllegalArgumentException();
+ }
+ else
+ {
+ parsed = true;
+ }
+ }
+ else if (next == ' ' || next == '\r' || next == '\n' || next == ',')
+ {
+ json.remove(0);
+ }
+ else
+ {
+ values.add(JSONValueParser.parse(json));
+ }
+ }
+ return new JSONArray(values);
+ }
+
+ @Override
+ public String toString()
+ {
+ String string = "[";
+ Iterator<JSONValue> objectIterator = value.iterator();
+ while (objectIterator.hasNext())
+ {
+ string += objectIterator.next().toString();
+ if (objectIterator.hasNext())
+ {
+ string += ",";
+ }
+ }
+ string += "]";
+
+ return string;
+ }
+}
diff --git a/src/plugins/translation/src/com/motorola/studio/android/json/JSONBoolean.java b/src/plugins/translation/src/com/motorola/studio/android/json/JSONBoolean.java
new file mode 100644
index 0000000..4332471
--- /dev/null
+++ b/src/plugins/translation/src/com/motorola/studio/android/json/JSONBoolean.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.motorola.studio.android.json;
+
+import java.util.List;
+
+public class JSONBoolean extends JSONValue
+{
+ public final boolean value;
+
+ public JSONBoolean(boolean value)
+ {
+ this.value = value;
+ }
+
+ @Override
+ public Object getValue()
+ {
+ return value;
+ }
+
+ static JSONValue parseValues(List<Character> json)
+ {
+ boolean parsed = false;
+ boolean value = false;
+
+ while (!parsed)
+ {
+ Character next = json.get(0);
+
+ if (next == 't' && json.get(1) == 'r' && json.get(2) == 'u' && json.get(3) == 'e')
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ json.remove(0);
+ }
+ parsed = true;
+ value = true;
+ }
+ else if (next == 'f' && json.get(1) == 'a' && json.get(2) == 'l' && json.get(3) == 's'
+ && json.get(4) == 'e')
+ {
+ for (int i = 0; i < 5; i++)
+ {
+ json.remove(0);
+ }
+ parsed = true;
+ }
+ else
+ {
+ throw new IllegalArgumentException();
+ }
+
+ }
+ return new JSONBoolean(value);
+ }
+
+ @Override
+ public String toString()
+ {
+ return Boolean.toString(value);
+ }
+
+}
diff --git a/src/plugins/translation/src/com/motorola/studio/android/json/JSONNull.java b/src/plugins/translation/src/com/motorola/studio/android/json/JSONNull.java
new file mode 100644
index 0000000..792bce3
--- /dev/null
+++ b/src/plugins/translation/src/com/motorola/studio/android/json/JSONNull.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.motorola.studio.android.json;
+
+import java.util.List;
+
+public class JSONNull extends JSONValue
+{
+ @Override
+ public Object getValue()
+ {
+ return null;
+ }
+
+ static JSONValue parseValues(List<Character> json)
+ {
+ boolean parsed = false;
+
+ while (!parsed)
+ {
+ Character next = json.get(0);
+
+ if (next == 'n' && json.get(1) == 'u' && json.get(2) == 'l' && json.get(3) == 'l')
+ {
+ for (int i = 0; i < 4; i++)
+ {
+ json.remove(0);
+ }
+ parsed = true;
+ }
+ else
+ {
+ throw new IllegalArgumentException();
+ }
+
+ }
+ return new JSONNull();
+ }
+
+ @Override
+ public String toString()
+ {
+ return "null";
+ }
+}
diff --git a/src/plugins/translation/src/com/motorola/studio/android/json/JSONNumber.java b/src/plugins/translation/src/com/motorola/studio/android/json/JSONNumber.java
new file mode 100644
index 0000000..d10c9ca
--- /dev/null
+++ b/src/plugins/translation/src/com/motorola/studio/android/json/JSONNumber.java
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.motorola.studio.android.json;
+
+import java.util.List;
+
+public class JSONNumber extends JSONValue
+{
+
+ private final int value;
+
+ public JSONNumber(int value)
+ {
+ this.value = value;
+ }
+
+ @Override
+ public Object getValue()
+ {
+ return value;
+ }
+
+ static JSONValue parseValues(List<Character> json)
+ {
+ boolean parsed = false;
+ StringBuilder number = new StringBuilder();
+
+ while (!parsed)
+ {
+ Character next = json.get(0);
+ if (next >= 48 && next <= 57)
+ {
+ json.remove(0);
+ number.append(next);
+ }
+ else
+ {
+ parsed = true;
+ }
+ }
+
+ return new JSONNumber(Integer.parseInt(number.toString()));
+
+ }
+
+ @Override
+ public String toString()
+ {
+ return Integer.toString(value);
+ }
+
+}
diff --git a/src/plugins/translation/src/com/motorola/studio/android/json/JSONObject.java b/src/plugins/translation/src/com/motorola/studio/android/json/JSONObject.java
new file mode 100644
index 0000000..5b64abe
--- /dev/null
+++ b/src/plugins/translation/src/com/motorola/studio/android/json/JSONObject.java
@@ -0,0 +1,95 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.motorola.studio.android.json;
+
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.Stack;
+
+public class JSONObject extends JSONValue
+{
+ private final Set<JSONPair> value;
+
+ public JSONObject(Set<JSONPair> value)
+ {
+ this.value = value;
+ }
+
+ @Override
+ public Set<JSONPair> getValue()
+ {
+ return value;
+ }
+
+ static JSONValue parseValues(List<Character> json)
+ {
+ Stack<Character> stack = new Stack<Character>();
+ Set<JSONPair> values = new HashSet<JSONPair>();
+ boolean parsed = false;
+ while (!parsed)
+ {
+ Character next = json.get(0);
+
+ if (next == '{')
+ {
+ json.remove(0);
+ stack.push('{');
+ }
+ else if (next == '}')
+ {
+ json.remove(0);
+ if (stack.pop() != '{')
+ {
+ throw new IllegalArgumentException();
+ }
+ else
+ {
+ parsed = true;
+ }
+ }
+ else if (next == ' ' || next == '\r' || next == '\n' || next == ',')
+ {
+ json.remove(0);
+ }
+ else if (next == '"')
+ {
+ values.add(JSONPair.parse(json));
+ }
+ }
+ return new JSONObject(values);
+ }
+
+ @Override
+ public String toString()
+ {
+ String string = "{";
+ Iterator<JSONPair> objectIterator = value.iterator();
+ while (objectIterator.hasNext())
+ {
+ string += objectIterator.next().toString();
+ if (objectIterator.hasNext())
+ {
+ string += ",";
+ }
+ }
+ string += "}";
+
+ return string;
+ }
+
+}
diff --git a/src/plugins/translation/src/com/motorola/studio/android/json/JSONPair.java b/src/plugins/translation/src/com/motorola/studio/android/json/JSONPair.java
new file mode 100644
index 0000000..2a6424b
--- /dev/null
+++ b/src/plugins/translation/src/com/motorola/studio/android/json/JSONPair.java
@@ -0,0 +1,109 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.motorola.studio.android.json;
+
+import java.util.List;
+
+public class JSONPair
+{
+ private final String name;
+
+ private final JSONValue value;
+
+ public JSONPair(String name, JSONValue value)
+ {
+ this.name = name;
+ this.value = value;
+ }
+
+ public String getName()
+ {
+ return name;
+ }
+
+ public JSONValue getValue()
+ {
+ return value;
+ }
+
+ public static JSONPair parse(List<Character> json)
+ {
+ String name = null;
+ JSONValue value = null;
+ boolean parsed = false;
+ while (!parsed)
+ {
+ Character next = json.get(0);
+ if (next == '"')
+ {
+ name = parseName(json);
+ }
+ else if ((next == ' ') || (next == '\r') || (next == '\n'))
+ {
+ json.remove(0);
+ }
+ else if (next == ':')
+ {
+ json.remove(0);
+ value = JSONValueParser.parse(json);
+ parsed = true;
+ }
+ }
+
+ return new JSONPair(name, value);
+ }
+
+ private static String parseName(List<Character> json)
+ {
+ String name = null;
+ StringBuilder nameBuilder = new StringBuilder();
+ boolean specialChar = false;
+ Character next;
+ json.remove(0);
+ while (name == null)
+ {
+ next = json.remove(0);
+ if ((next == '"'))
+ {
+ if (specialChar)
+ {
+ specialChar = false;
+ }
+ else
+ {
+ name = nameBuilder.toString();
+ }
+ }
+ else if (next == '\\')
+ {
+ specialChar = true;
+ }
+ else
+ {
+ specialChar = false;
+ nameBuilder.append(next);
+ }
+ }
+ return name;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "\"" + name + "\":" + value.toString();
+ }
+
+}
diff --git a/src/plugins/translation/src/com/motorola/studio/android/json/JSONString.java b/src/plugins/translation/src/com/motorola/studio/android/json/JSONString.java
new file mode 100644
index 0000000..c341bba
--- /dev/null
+++ b/src/plugins/translation/src/com/motorola/studio/android/json/JSONString.java
@@ -0,0 +1,94 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.motorola.studio.android.json;
+
+import java.util.List;
+
+public class JSONString extends JSONValue
+{
+ private final String value;
+
+ public JSONString(String value)
+ {
+ this.value = value;
+ }
+
+ @Override
+ public String getValue()
+ {
+ return value;
+ }
+
+ public static JSONValue parseValues(List<Character> json)
+ {
+ String value = null;
+ boolean parsed = false;
+ while (!parsed)
+ {
+ Character next = json.get(0);
+ if (next == '"')
+ {
+
+ value = parseName(json);
+ parsed = true;
+ }
+ }
+
+ return new JSONString(value);
+ }
+
+ private static String parseName(List<Character> json)
+ {
+ String name = null;
+ StringBuilder nameBuilder = new StringBuilder();
+ boolean specialChar = false;
+ Character next;
+ json.remove(0);
+ while (name == null)
+ {
+ next = json.remove(0);
+ if (next == '"')
+ {
+ if (specialChar)
+ {
+ specialChar = false;
+ nameBuilder.append(next);
+ }
+ else
+ {
+ name = nameBuilder.toString();
+ }
+ }
+ else if (next == '\\')
+ {
+ specialChar = true;
+ }
+ else
+ {
+ specialChar = false;
+ nameBuilder.append(next);
+ }
+ }
+ return name;
+ }
+
+ @Override
+ public String toString()
+ {
+ return "\"" + value + "\"";
+ }
+
+}
diff --git a/src/plugins/translation/src/com/motorola/studio/android/json/JSONValue.java b/src/plugins/translation/src/com/motorola/studio/android/json/JSONValue.java
new file mode 100644
index 0000000..4738177
--- /dev/null
+++ b/src/plugins/translation/src/com/motorola/studio/android/json/JSONValue.java
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.motorola.studio.android.json;
+
+import java.util.List;
+
+public abstract class JSONValue
+{
+ public abstract Object getValue();
+
+ static JSONValue parse(List<Character> json)
+ {
+ return null;
+ }
+}
diff --git a/src/plugins/translation/src/com/motorola/studio/android/json/JSONValueParser.java b/src/plugins/translation/src/com/motorola/studio/android/json/JSONValueParser.java
new file mode 100644
index 0000000..816d90c
--- /dev/null
+++ b/src/plugins/translation/src/com/motorola/studio/android/json/JSONValueParser.java
@@ -0,0 +1,74 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.motorola.studio.android.json;
+
+import java.util.List;
+
+public class JSONValueParser
+{
+ private JSONValueParser()
+ {
+ };
+
+ static JSONValue parse(List<Character> json)
+ {
+ JSONValue value = null;
+
+ boolean parsed = false;
+
+ while (!parsed)
+ {
+ Character next = json.get(0);
+
+ if (next == '{')
+ {
+ value = JSONObject.parse(json);
+ parsed = true;
+ }
+ else if (next == '[')
+ {
+ value = JSONArray.parse(json);
+ parsed = true;
+ }
+ else if (next == '"')
+ {
+ value = JSONString.parse(json);
+ parsed = true;
+ }
+ else if (next == 'n')
+ {
+ value = JSONNull.parse(json);
+ parsed = true;
+ }
+ else if (next == 't' || next == 'f')
+ {
+ value = JSONBoolean.parse(json);
+ parsed = true;
+ }
+ else if (next >= 48 && next <= 57)
+ {
+ value = JSONNumber.parse(json);
+ parsed = true;
+ }
+ else if (next == ' ' || next == '\r' || next == '\n')
+ {
+ json.remove(0);
+ }
+
+ }
+ return value;
+ }
+}
diff --git a/src/plugins/translation/src/com/motorola/studio/android/json/Jason.java b/src/plugins/translation/src/com/motorola/studio/android/json/Jason.java
new file mode 100644
index 0000000..0b0b039
--- /dev/null
+++ b/src/plugins/translation/src/com/motorola/studio/android/json/Jason.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.motorola.studio.android.json;
+
+import java.util.ArrayList;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * This class is responsible to parse a JSON string into objects
+ * Visit {@link http://www.json.org/} for more information
+ *
+ */
+public class Jason
+{
+ private final Set<JSONObject> objects;
+
+ public Jason(String value)
+ {
+ objects = new HashSet<JSONObject>();
+ stip(value);
+ }
+
+ public Set<JSONObject> getJSON()
+ {
+ return objects;
+ }
+
+ private void stip(String value)
+ {
+ List<Character> json = new ArrayList<Character>();
+ for (char c : value.toCharArray())
+ {
+ json.add(c);
+ }
+
+ while (json.size() > 0)
+ {
+ Character next = json.get(0);
+
+ if (next == '{')
+ {
+ JSONObject object = (JSONObject) JSONObject.parse(json);
+ objects.add(object);
+ }
+ else if ((next == ' ') || (next == '\r') || (next == '\n') || (next == ','))
+ {
+ json.remove(0);
+ }
+ }
+ }
+
+ @Override
+ public String toString()
+ {
+ String string = "";
+ Iterator<JSONObject> objectIterator = objects.iterator();
+ while (objectIterator.hasNext())
+ {
+ string += objectIterator.next().toString();
+ if (objectIterator.hasNext())
+ {
+ string += ",";
+ }
+ }
+ return string;
+ }
+}
diff --git a/src/plugins/translation/src/com/motorola/studio/android/localization/translators/GoogleTranslator.java b/src/plugins/translation/src/com/motorola/studio/android/localization/translators/GoogleTranslator.java
new file mode 100644
index 0000000..4e6c0a5
--- /dev/null
+++ b/src/plugins/translation/src/com/motorola/studio/android/localization/translators/GoogleTranslator.java
@@ -0,0 +1,946 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.motorola.studio.android.localization.translators;
+
+import java.io.IOException;
+import java.io.UnsupportedEncodingException;
+import java.net.Authenticator;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLEncoder;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import org.apache.commons.httpclient.Credentials;
+import org.apache.commons.httpclient.DefaultHttpMethodRetryHandler;
+import org.apache.commons.httpclient.HttpClient;
+import org.apache.commons.httpclient.HttpException;
+import org.apache.commons.httpclient.HttpStatus;
+import org.apache.commons.httpclient.UsernamePasswordCredentials;
+import org.apache.commons.httpclient.auth.AuthScope;
+import org.apache.commons.httpclient.methods.GetMethod;
+import org.apache.commons.httpclient.params.HttpMethodParams;
+import org.eclipse.core.internal.net.ProxyManager;
+import org.eclipse.core.net.proxy.IProxyData;
+import org.eclipse.core.net.proxy.IProxyService;
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.osgi.util.NLS;
+import org.eclipse.sequoyah.localization.tools.datamodel.node.TranslationResult;
+import org.eclipse.sequoyah.localization.tools.extensions.classes.ITranslator;
+import org.eclipse.sequoyah.localization.tools.extensions.implementation.generic.ITranslateDialog;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Link;
+
+import com.motorola.studio.android.common.log.StudioLogger;
+import com.motorola.studio.android.common.proxy.ProxyAuthenticator;
+import com.motorola.studio.android.common.utilities.EclipseUtils;
+import com.motorola.studio.android.json.JSONArray;
+import com.motorola.studio.android.json.JSONObject;
+import com.motorola.studio.android.json.JSONPair;
+import com.motorola.studio.android.json.JSONString;
+import com.motorola.studio.android.json.JSONValue;
+import com.motorola.studio.android.json.Jason;
+import com.motorola.studio.android.localization.translators.i18n.TranslateNLS;
+
+/**
+ * Uses the Google translator web service (via executing a http request and
+ * parsing the answer) in order to translate a text string.
+ *
+ * Google v2 supports only one source and one destination per request, but support many words.
+ *
+ */
+@SuppressWarnings("restriction")
+public final class GoogleTranslator extends ITranslator implements GoogleTranslatorConstants
+{
+
+ /**
+ * Translate all words from some source language to destination language.
+ * This method handles any needed splits in original request due to API limitations.
+ * @param words the words being translated
+ * @param fromLanguage the origin language
+ * @param toLanguage the destination language
+ * @param monitor progress monitor
+ * @return a list of translation results
+ * @throws Exception
+ */
+ public List<TranslationResult> translate(List<String> words, String fromLanguage,
+ String toLanguage, IProgressMonitor monitor) throws Exception
+ {
+ List<TranslationResult> translationResults = new ArrayList<TranslationResult>();
+ int characterCount = 0;
+ int MAX_REQUEST_SIZE = getMaxQuerySize(fromLanguage, toLanguage);
+
+ int maxRequestSize = MAX_REQUEST_SIZE;
+ List<String> wordsToTranslate = new ArrayList<String>();
+
+ Iterator<String> wordsIterator = words.iterator();
+ int counter = 0;
+
+ while (wordsIterator.hasNext())
+ {
+ maxRequestSize -= STRING_PAR.length();
+ String word = wordsIterator.next();
+ /* try to add some more words to the request.
+ * If there is no more room left to request, execute the translation and continue afterwards
+ */
+ if (characterCount + word.length() < maxRequestSize)
+ {
+ wordsToTranslate.add(word);
+ characterCount += word.length();
+ }
+ else
+ {
+ URL translationURL =
+ createTranslationURL(wordsToTranslate, fromLanguage, toLanguage);
+ String httpRequestResponseBody = executeHttpGetRequest(translationURL);
+
+ List<String> responses = parseTranslationResponse(httpRequestResponseBody);
+
+ for (int i = 0; i < wordsToTranslate.size(); i++)
+ {
+ translationResults.add(new TranslationResult(words.get(counter++), this,
+ responses.get(i), fromLanguage, toLanguage, Calendar.getInstance()
+ .getTime(), true));
+ }
+ characterCount = 0;
+ maxRequestSize = MAX_REQUEST_SIZE;
+ wordsToTranslate.clear();
+ wordsToTranslate.add(word);
+ }
+ }
+
+ /*
+ * execute the request with remaining sentences
+ */
+ if (!wordsToTranslate.isEmpty())
+ {
+ URL translationURL = createTranslationURL(wordsToTranslate, fromLanguage, toLanguage);
+ String httpRequestResponseBody = executeHttpGetRequest(translationURL);
+ List<String> responses = parseTranslationResponse(httpRequestResponseBody);
+
+ for (int i = 0; i < wordsToTranslate.size(); i++)
+ {
+ translationResults.add(new TranslationResult(words.get(counter++), this, responses
+ .get(i), fromLanguage, toLanguage, Calendar.getInstance().getTime(), true));
+ }
+ }
+
+ return translationResults;
+ }
+
+ /**
+ * Translates a string.
+ *
+ * @param text The String to be translated.
+ * @param from Original language.
+ * @param to Target language.
+ * @return The translated String.
+ * @throws Exception on errors.
+ */
+ @Override
+ public TranslationResult translate(final String text, String from, String to) throws Exception
+ {
+ TranslationResult translationResult;
+
+ if (text != null && !text.equals("") && text.length() < getMaxQuerySize(from, to)) //$NON-NLS-1$
+ {
+ String httpResult = ""; //$NON-NLS-1$
+ URL url = null;
+
+ // Creates the URL to be used as request
+ try
+ {
+ List<String> sentences = new ArrayList<String>();
+ sentences.add(text);
+ url = createTranslationURL(sentences, from, to);
+ httpResult = executeHttpGetRequest(url);
+ translationResult =
+ new TranslationResult(text, this, parseTranslationResponse(httpResult).get(
+ 0), from, to, Calendar.getInstance().getTime(), true);
+ }
+ catch (UnsupportedEncodingException e)
+ {
+ throw new HttpException(TranslateNLS.GoogleTranslator_Error_UnsupportedEncoding
+ + ENCODING_TYPE);
+ }
+
+ }
+ else if (text.length() >= getMaxQuerySize(from, to))
+ {
+ throw new Exception(TranslateNLS.GoogleTranslator_Error_QueryTooBig);
+ }
+ else
+ {
+ translationResult = new TranslationResult(text, this, text, from, to, new Date(), true);
+ }
+
+ try
+ {
+ String descriptionToLog =
+ StudioLogger.KEY_TRANSLATION_PROVIDER + StudioLogger.VALUE_GOOGLE
+ + StudioLogger.SEPARATOR + StudioLogger.KEY_TRANSLATION_FROM_LANG
+ + from + StudioLogger.SEPARATOR + StudioLogger.KEY_TRANSLATION_TO_LANG
+ + to;
+ StudioLogger.collectUsageData(StudioLogger.WHAT_LOCALIZATION_AUTOMATICTRANSLATION,
+ StudioLogger.KIND_LOCALIZATION, descriptionToLog, TranslationPlugin.PLUGIN_ID,
+ TranslationPlugin.getDefault().getBundle().getVersion().toString());
+ }
+ catch (Throwable t)
+ {
+ // Do nothing, usage data collection is for statistics and should not prevent tool from work
+ }
+
+ return translationResult;
+
+ }
+
+ /**
+ * Translate a single word from one language to several other
+ * @param sentences sentence being translated
+ * @param fromLanguage source language
+ * @param toLanguages target languages
+ */
+ @Override
+ public List<TranslationResult> translate(String sentence, String fromLanguage,
+ List<String> toLanguages) throws Exception
+ {
+ List<TranslationResult> translationResults = new ArrayList<TranslationResult>();
+
+ // Lets start with some checkings, one can never be too careful
+ if (fromLanguage == null || toLanguages == null || toLanguages.isEmpty())
+ {
+ // We must have a FROM and a TO languages
+ throw new IllegalArgumentException(
+ TranslateNLS.GoogleTranslator_Error_ToAndFromLanguagesAreEmpty);
+ }
+ else if (sentence == null || sentence.equals("")) //$NON-NLS-1$
+ {
+ // We must have something to be translated
+ sentence = ""; //$NON-NLS-1$
+ if (toLanguages.size() == 1)
+ {
+ translationResults.add(new TranslationResult("", this, "", fromLanguage, //$NON-NLS-1$ //$NON-NLS-2$
+ toLanguages.get(0), new Date(), true));
+ }
+ }
+ else if (sentence.length() >= getMaxQuerySize(fromLanguage, toLanguages.get(0)))
+ {
+ throw new Exception(TranslateNLS.GoogleTranslator_Error_QueryTooBig);
+ }
+ /*
+ * Delegate the translation to another method
+ */
+ else
+ {
+ for (String toLanguage : toLanguages)
+ {
+ translationResults.add(translate(sentence, fromLanguage, toLanguage));
+ }
+ }
+
+ try
+ {
+ // Collecting usage data for statistic purposes
+ String descriptionToLog =
+ StudioLogger.KEY_TRANSLATION_PROVIDER + StudioLogger.VALUE_GOOGLE
+ + StudioLogger.SEPARATOR + StudioLogger.KEY_TRANSLATION_FROM_LANG
+ + fromLanguage + StudioLogger.SEPARATOR
+ + StudioLogger.KEY_TRANSLATION_TO_LANG + "several languages"; //$NON-NLS-1$
+
+ StudioLogger.collectUsageData(StudioLogger.WHAT_LOCALIZATION_AUTOMATICTRANSLATION,
+ StudioLogger.KIND_LOCALIZATION, descriptionToLog, TranslationPlugin.PLUGIN_ID,
+ TranslationPlugin.getDefault().getBundle().getVersion().toString());
+ }
+ catch (Throwable t)
+ {
+ // Do nothing, usage data collection is for statistics and should not prevent tool from work
+ }
+
+ return translationResults;
+ }
+
+ /**
+ * Translate a list of sentences from one language to another
+ * @param sentences sentences being translated
+ * @param fromLanguage source language
+ * @param toLanguage target language
+ * @param monitor progress monitor
+ */
+ @Override
+ public List<TranslationResult> translateAll(List<String> sentences, String fromLanguage,
+ String toLanguage, IProgressMonitor monitor) throws Exception
+ {
+ // The result (duhh)
+ List<TranslationResult> translationResults = new ArrayList<TranslationResult>();
+
+ // Lets start with some checkings, one can never be too carefull
+ if (fromLanguage == null || toLanguage == null)
+ {
+ // We must have a FROM and a TO languages
+ throw new IllegalArgumentException(
+ TranslateNLS.GoogleTranslator_Error_ToAndFromLanguagesAreEmpty);
+ }
+ else if (sentences == null || sentences.size() == 0)
+ {
+ // We must have something to be translated
+ throw new IllegalArgumentException(TranslateNLS.GoogleTranslator_Error_NoAvailableData);
+ }
+ else
+ {
+ translationResults.addAll(translate(sentences, fromLanguage, toLanguage, monitor));
+ }
+
+ try
+ {
+ // Collecting usage data for statistic purposes
+ String descriptionToLog =
+ StudioLogger.KEY_TRANSLATION_PROVIDER + StudioLogger.VALUE_GOOGLE
+ + StudioLogger.SEPARATOR + StudioLogger.KEY_TRANSLATION_FROM_LANG
+ + fromLanguage + StudioLogger.SEPARATOR
+ + StudioLogger.KEY_TRANSLATION_TO_LANG + toLanguage;
+
+ StudioLogger.collectUsageData(StudioLogger.WHAT_LOCALIZATION_AUTOMATICTRANSLATION,
+ StudioLogger.KIND_LOCALIZATION, descriptionToLog, TranslationPlugin.PLUGIN_ID,
+ TranslationPlugin.getDefault().getBundle().getVersion().toString());
+ }
+ catch (Throwable t)
+ {
+ // Do nothing, usage data collection is for statistics and should not prevent tool from work
+ }
+
+ return translationResults;
+ }
+
+ /**
+ * Translates a list of strings from a list of given languages to other given languages (given by a list, or course),
+ * using google Ajax API's for that.
+ *
+ * The three lists have the same number of elements.
+ *
+ * This comment feels like the "Three Swatch watch switching witches watched switched Swatch watch witches switch",
+ * but I'll let it here anyway.
+ */
+ @Override
+ public List<TranslationResult> translateAll(List<String> words, List<String> fromLanguage,
+ List<String> toLanguage, IProgressMonitor monitor) throws Exception
+ {
+ // The result (duhh)
+ List<TranslationResult> translationResults = new ArrayList<TranslationResult>();
+
+ // Lets start with some checkings, one can never be too carefull
+ if (fromLanguage == null || toLanguage == null)
+ {
+ // We must have a FROM and a TO languages
+ throw new IllegalArgumentException(
+ TranslateNLS.GoogleTranslator_Error_ToAndFromLanguagesAreEmpty);
+ }
+ else if (words == null || words.size() == 0)
+ {
+ // We must have something to be translated
+ throw new IllegalArgumentException(TranslateNLS.GoogleTranslator_Error_NoAvailableData);
+ }
+ else
+ {
+ translationResults.addAll(groupAndTranslate(words, fromLanguage, toLanguage, monitor));
+ }
+
+ try
+ {
+ // Collecting usage data for statistic purposes
+ String descriptionToLog =
+ StudioLogger.KEY_TRANSLATION_PROVIDER + StudioLogger.VALUE_GOOGLE
+ + StudioLogger.SEPARATOR + StudioLogger.KEY_TRANSLATION_FROM_LANG
+ + fromLanguage + StudioLogger.SEPARATOR
+ + StudioLogger.KEY_TRANSLATION_TO_LANG + toLanguage;
+
+ StudioLogger.collectUsageData(StudioLogger.WHAT_LOCALIZATION_AUTOMATICTRANSLATION,
+ StudioLogger.KIND_LOCALIZATION, descriptionToLog, TranslationPlugin.PLUGIN_ID,
+ TranslationPlugin.getDefault().getBundle().getVersion().toString());
+ }
+ catch (Throwable t)
+ {
+ // Do nothing, usage data collection is for statistics and should not prevent tool from work
+ }
+
+ return translationResults;
+ }
+
+ private List<TranslationResult> groupAndTranslate(List<String> words,
+ List<String> fromLanguage, List<String> toLanguage, IProgressMonitor monitor)
+ throws Exception
+ {
+
+ List<TranslationResult> results = new ArrayList<TranslationResult>();
+ /*
+ * Get all words with same source and same destination and group them to make translation more efficient
+ * Notice that this implementation relies on input condition that all lists have the same size and all elements with same index makes one request
+ */
+
+ class StringItem
+ {
+ private String sentence = "";
+
+ private int orderNumber = -1;
+
+ public StringItem(String sentence, int orderNumber)
+ {
+ this.sentence = sentence;
+ this.orderNumber = orderNumber;
+ }
+
+ public Integer getOrderNumber()
+ {
+ return orderNumber;
+ }
+
+ public String getSentence()
+ {
+ return sentence;
+ }
+
+ @Override
+ public String toString()
+ {
+ return orderNumber + "|" + sentence;
+ }
+ }
+
+ /*
+ * This map holds a list of group of stringitems being translated. These items have the same from and to languages
+ * Using linkedHashMap to keep insertionOrder
+ */
+ Map<String, List<StringItem>> sameSourceDestMap =
+ new LinkedHashMap<String, List<StringItem>>();
+ Map<Integer, TranslationResult> translations = new HashMap<Integer, TranslationResult>();
+
+ // group things with same from and to languages
+ for (int i = 0; i < words.size(); i++)
+ {
+ /*
+ * Check if one of the words are big enough to not be translated
+ */
+ if (words.get(i).length() >= getMaxQuerySize(fromLanguage.get(i), toLanguage.get(i))
+ - STRING_PAR.length() - 1)
+ {
+ throw new Exception(TranslateNLS.GoogleTranslator_Error_QueryTooBig);
+ }
+
+ String key = fromLanguage.get(i) + "|" + toLanguage.get(i);
+ List<StringItem> itemsToTranslate = sameSourceDestMap.get(key);
+ if (itemsToTranslate == null)
+ {
+ itemsToTranslate = new ArrayList<StringItem>();
+ sameSourceDestMap.put(key, itemsToTranslate);
+ }
+ itemsToTranslate.add(new StringItem(words.get(i), i));
+ }
+
+ for (String key : sameSourceDestMap.keySet())
+ {
+ List<StringItem> itemsToTranslate = sameSourceDestMap.get(key);
+ List<String> items = new ArrayList<String>();
+ for (StringItem item : itemsToTranslate)
+ {
+ items.add(item.getSentence());
+ }
+ List<TranslationResult> tempResults =
+ translate(items, key.split("\\|")[0], key.split("\\|")[1], monitor);
+ for (int i = 0; i < itemsToTranslate.size(); i++)
+ {
+ translations.put(itemsToTranslate.get(i).getOrderNumber(), tempResults.get(i));
+ }
+
+ }
+
+ for (int i = 0; i < words.size(); i++)
+ {
+ results.add(translations.get(i));
+ }
+
+ return results;
+ }
+
+ private int getMaxQuerySize(String fromLanguage, String toLanguage)
+ {
+ return MAX_QUERY_SIZE - TRANSLATE_URL_WITHOUT_PARAMS.length() - API_KEY_PARAM.length()
+ - getApiKey().length() - SOURCE_PAR.length() - fromLanguage.length()
+ - TARGET_PARAM.length() - toLanguage.length();
+ }
+
+ /**
+ * Parse the translation response of the http request
+ * @param httpRequestResponseBody the response body
+ * @param sourceLanguage the source language
+ * @param destinationLanguage the destination language
+ * @return a list of String objects for the strings translated for source/destination languages pair
+ */
+ private List<String> parseTranslationResponse(String httpRequestResponseBody)
+ {
+ JSONPair translationSection = getTranslationSection(httpRequestResponseBody);
+
+ return getTranslations(translationSection);
+ }
+
+ /*
+ * {
+ "data": {
+ "translations": [
+ {
+ "translatedText": "bla bla bla"
+ },
+ {
+ "translatedText": "foo bar"
+ }
+ ]
+ }
+ }
+ */
+ private JSONPair getTranslationSection(String httpRequestResponseBody)
+ {
+ Jason ripper = new Jason(httpRequestResponseBody);
+ JSONPair translationsSection = null;
+ Iterator<JSONObject> jsonIterator = ripper.getJSON().iterator();
+ while (translationsSection == null && jsonIterator.hasNext())
+ {
+ translationsSection = findPair(jsonIterator.next(), TRANSLATIONS_SECTION);
+ }
+
+ return translationsSection;
+ }
+
+ private static JSONPair findPair(JSONValue origin, String name)
+ {
+ JSONPair pair = null;
+ if (origin instanceof JSONObject)
+ {
+ JSONObject object = (JSONObject) origin;
+ Iterator<JSONPair> pairs = object.getValue().iterator();
+ while (pair == null && pairs.hasNext())
+ {
+ JSONPair jsonPair = pairs.next();
+ if (jsonPair.getName().equals(name))
+ {
+ pair = jsonPair;
+ }
+ else
+ {
+ pair = findPair(jsonPair.getValue(), name);
+ }
+
+ }
+ }
+
+ return pair;
+ }
+
+ private List<String> getTranslations(JSONPair translationSection)
+ {
+ List<String> translations = new ArrayList<String>();
+ if (translationSection.getValue() instanceof JSONArray)
+ {
+ JSONArray translationsArray = (JSONArray) translationSection.getValue();
+ for (JSONValue translationObject : translationsArray.getValue())
+ {
+ translations.add(getTranslation(translationObject));
+ }
+ }
+
+ return translations;
+ }
+
+ /**
+ * @param translationObject
+ * {
+ * "translatedText": "Hallo Welt"
+ * }
+ * @return pure translation
+ * Hallo Welt
+ */
+ private String getTranslation(JSONValue translationObject)
+ {
+ String translation = null;
+ if (translationObject instanceof JSONObject)
+ {
+ JSONObject jsonObject = (JSONObject) translationObject;
+ translation =
+ ((JSONString) jsonObject.getValue().iterator().next().getValue()).getValue();
+ }
+ return translation != null ? fixHTMLTags(translation) : null;
+ }
+
+ private URL createTranslationURL(List<String> wordsToTranslate, String fromLanguage,
+ String toLanguage) throws UnsupportedEncodingException
+ {
+ URL translationURL = null;
+
+ // We need to unescape the ' (apostrophe) before sending it to translation
+ String regex = "\\\\'"; //$NON-NLS-1$
+ Pattern pattern = Pattern.compile(regex);
+
+ StringBuilder urlBuilder = new StringBuilder(TRANSLATE_URL_WITHOUT_PARAMS);
+ urlBuilder.append(URL_PARAMETERS.replace("#FROM#", fromLanguage)
+ .replace("#TO#", toLanguage).replace("#API_KEY#", getApiKey()));
+
+ for (String word : wordsToTranslate)
+ {
+ String wordToTranslate = pattern.matcher(word).replaceAll("'");
+ urlBuilder.append(STRING_PAR);
+ urlBuilder.append(URLEncoder.encode(wordToTranslate, ENCODING_TYPE));
+ }
+
+ try
+ {
+ translationURL = new URL(urlBuilder.toString());
+ }
+ catch (MalformedURLException e)
+ {
+ StudioLogger.error(getClass(), "Unable to create translation URL", e);
+ }
+
+ return translationURL;
+ }
+
+ /**
+ * The Android localization files text must accept three HTML tags: i, b and u.
+ * Nevertheless, google translator returns the close part of this tags with
+ * a extra-space that makes the sintax wrong. This method will try to fix it.
+ * @param originalText
+ * @return the text with the tags fixed
+ */
+ private static String fixHTMLTags(String originalText)
+ {
+ String result = ""; //$NON-NLS-1$
+ if (originalText != null)
+ {
+ result = originalText;
+ }
+ result = originalText.replaceAll("</ b>", "</b>"); //$NON-NLS-1$ //$NON-NLS-2$
+ result = originalText.replaceAll("</ i>", "</i>"); //$NON-NLS-1$ //$NON-NLS-2$
+ result = originalText.replaceAll("</ u>", "</u>"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ result = originalText.replaceAll("</ B>", "</B>"); //$NON-NLS-1$ //$NON-NLS-2$
+ result = originalText.replaceAll("</ I>", "</I>"); //$NON-NLS-1$ //$NON-NLS-2$
+ result = originalText.replaceAll("</ U>", "</U>"); //$NON-NLS-1$ //$NON-NLS-2$
+
+ result = originalText.replaceAll(" \\\\ n ", " \\\\n "); //$NON-NLS-1$ //$NON-NLS-2$
+
+ return result;
+ }
+
+ /**
+ * Creates an HTTP request with the URL, execute it as a get, and returns
+ * the a string with the result.
+ *
+ * @param url
+ * URL to be executed.
+ * @return String with the URL execution result.
+ * @throws IOException
+ * If an exception occurs on transport
+ * @throws HttpException
+ * If an exception occurs on the protocol
+ * @throws Exception
+ * on error.
+ */
+ protected static String executeHttpGetRequest(final URL url) throws HttpException
+ {
+
+ // Checking query size due to google policies
+ if (url.toString().length() > MAX_QUERY_SIZE)
+ {
+ throw new HttpException(TranslateNLS.GoogleTranslator_Error_QueryTooBig);
+ }
+
+ // Try to retrieve proxy configuration to use if necessary
+ IProxyService proxyService = ProxyManager.getProxyManager();
+ IProxyData proxyData = null;
+ if (proxyService.isProxiesEnabled() || proxyService.isSystemProxiesEnabled())
+ {
+ Authenticator.setDefault(new ProxyAuthenticator());
+ String urlStr = url.toString();
+ if (urlStr.startsWith("https"))
+ {
+ proxyData = proxyService.getProxyData(IProxyData.HTTPS_PROXY_TYPE);
+ StudioLogger.debug(GoogleTranslator.class, "Using https proxy"); //$NON-NLS-1$
+ }
+ else if (urlStr.startsWith("http"))
+ {
+ proxyData = proxyService.getProxyData(IProxyData.HTTP_PROXY_TYPE);
+ StudioLogger.debug(GoogleTranslator.class, "Using http proxy"); //$NON-NLS-1$
+ }
+ else
+ {
+ StudioLogger.debug(GoogleTranslator.class, "Not using any proxy"); //$NON-NLS-1$
+ }
+ }
+
+ // Creates the http client and the method to be executed
+ HttpClient client = null;
+ client = new HttpClient();
+
+ // If there is proxy data, work with it
+ if (proxyData != null)
+ {
+ if (proxyData.getHost() != null)
+ {
+ // Sets proxy host and port, if any
+ client.getHostConfiguration().setProxy(proxyData.getHost(), proxyData.getPort());
+ }
+
+ if (proxyData.getUserId() != null && proxyData.getUserId().trim().length() > 0)
+ {
+ // Sets proxy user and password, if any
+ Credentials cred =
+ new UsernamePasswordCredentials(proxyData.getUserId(),
+ proxyData.getPassword() == null ? "" : proxyData.getPassword()); //$NON-NLS-1$
+ client.getState().setProxyCredentials(AuthScope.ANY, cred);
+ }
+ }
+
+ // Creating the method to be executed, the URL at this point is enough
+ // because it is complete
+ GetMethod method = new GetMethod(url.toString());
+
+ // Set method to be retried three times in case of error
+ method.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
+ new DefaultHttpMethodRetryHandler(RETRIES, false));
+
+ method.setRequestHeader(REFERER_HEADER, REFERER_SITE);
+
+ // Set the connection timeout
+ client.getHttpConnectionManager().getParams().setConnectionTimeout(new Integer(TIMEOUT));
+
+ String result = ""; //$NON-NLS-1$
+ try
+ {
+ // Execute the method.
+ int statusCode;
+ try
+ {
+ statusCode = client.executeMethod(method);
+ result = method.getResponseBodyAsString(MAX_SIZE);
+ }
+ catch (IOException e)
+ {
+ throw new HttpException(TranslateNLS.GoogleTranslator_Error_CannotConnectToServer
+ + e.getMessage());
+ }
+
+ checkStatusCode(statusCode, result);
+
+ // Unescape any possible unicode char
+ result = unescapeUnicode(result);
+
+ // Unescape any possible HTML sequence
+ result = unescapeHTML(result);
+
+ }
+
+ finally
+ {
+ // Release the connection.
+ method.releaseConnection();
+ }
+
+ return result;
+ }
+
+ private static void checkStatusCode(int statusCode, String response) throws HttpException
+ {
+ switch (statusCode)
+ {
+ case HttpStatus.SC_OK:
+ //do nothing
+ break;
+ case HttpStatus.SC_BAD_REQUEST:
+ throw new HttpException(NLS.bind(
+ TranslateNLS.GoogleTranslator_ErrorMessageExecutingRequest,
+ getErrorMessage(response)));
+
+ case HttpStatus.SC_REQUEST_URI_TOO_LONG:
+ throw new HttpException(TranslateNLS.GoogleTranslator_Error_QueryTooBig);
+
+ case HttpStatus.SC_FORBIDDEN:
+ throw new HttpException(NLS.bind(
+ TranslateNLS.GoogleTranslator_ErrorMessageNoValidTranslationReturned,
+ getErrorMessage(response)));
+
+ default:
+ throw new HttpException(NLS.bind(
+ TranslateNLS.GoogleTranslator_Error_HTTPRequestError, new Object[]
+ {
+ statusCode, getErrorMessage(response)
+ }));
+
+ }
+ }
+
+ /**
+ * According to APIv2, the error message is in the end of the response
+ * {
+ "error": {
+ "errors": [
+ {
+ "domain": "global",
+ "reason": "invalid",
+ "message": "Invalid Value"
+ }
+ ],
+ "code": 400,
+ "message": "Invalid Value"
+ }
+ }
+ * @param response the method response body
+ * @return the error message
+ */
+ private static String getErrorMessage(String response)
+ {
+ Jason ripper = new Jason(response);
+ JSONPair translationsSection = null;
+ Iterator<JSONObject> jsonIterator = ripper.getJSON().iterator();
+ while (translationsSection == null && jsonIterator.hasNext())
+ {
+ translationsSection = findPair(jsonIterator.next(), MESSAGE_TEXT);
+ }
+
+ return translationsSection != null ? ((JSONString) translationsSection.getValue())
+ .getValue() : null;
+ }
+
+ /**
+ * Unescape any HTML sequence that exists inside the string. For example,
+ * the sequence &#39; will be changed to the ' symbol
+ *
+ * @param source
+ * original text
+ * @return the result
+ */
+ private static String unescapeHTML(String source)
+ {
+ Pattern p = Pattern.compile("&#([0-9]+);"); //$NON-NLS-1$
+ String result = source;
+ Matcher m = p.matcher(result);
+ while (m.find())
+ {
+ char c = (char) Integer.parseInt(m.group(1));
+ if (c == "'".charAt(0)) //$NON-NLS-1$
+ {
+ // Apostrophes must be escaped by preceding it with a backslash (\) on the XML file
+ result = result.replaceAll(m.group(0), "\\\\'"); //$NON-NLS-1$
+ }
+ else
+ {
+ result = result.replaceAll(m.group(0), "" + c); //$NON-NLS-1$
+ }
+ }
+
+ return result;
+ }
+
+ /**
+ * Unescape any Unicode sequence that exists inside the string.
+ *
+ * For example, the sequence \u0000 will be changed to the symbol
+ * correnponded to the 0000 unicode value.
+ *
+ * @param source
+ * original text
+ * @return the result
+ */
+ private static String unescapeUnicode(String source)
+ {
+ int i = 0, len = source.length();
+ char c;
+ StringBuffer buffer = new StringBuffer(len);
+ while (i < len)
+ {
+ c = source.charAt(i++);
+ if (c == '\\')
+ {
+ if (i < len)
+ {
+ c = source.charAt(i++);
+ if (c == 'u')
+ {
+ c = (char) Integer.parseInt(source.substring(i, i + 4), 16);
+ i += 4;
+ }
+ }
+ }
+ buffer.append(c);
+ }
+ return buffer.toString();
+ }
+
+ private static String getApiKey()
+ {
+ String apiKey = GoogleTranslatorConstants.API_KEY;
+ IPreferenceStore prefStore = TranslationPlugin.getDefault().getPreferenceStore();
+ if (!prefStore.isDefault(GoogleTranslatorConstants.API_KEY_VALUE_PREFERENCE))
+ {
+ apiKey = prefStore.getString(GoogleTranslatorConstants.API_KEY_VALUE_PREFERENCE);
+ if (apiKey == null)
+ {
+ apiKey = GoogleTranslatorConstants.API_KEY;
+ }
+ }
+
+ return apiKey;
+ }
+
+ @Override
+ public Composite createCustomArea(Composite parent, final ITranslateDialog dialog)
+ {
+ Composite mainComposite = new Composite(parent, SWT.NONE);
+ mainComposite.setLayout(new GridLayout(1, false));
+
+ final Link prefPageLink = new Link(mainComposite, SWT.NONE);
+ prefPageLink.setText(TranslateNLS.GoogleTranslator_ChangeAPIkeyLabel);
+ prefPageLink.setLayoutData(new GridData(SWT.RIGHT, SWT.CENTER, true, true, 1, 1));
+ prefPageLink.addSelectionListener(new SelectionAdapter()
+ {
+ @Override
+ public void widgetSelected(SelectionEvent e)
+ {
+ EclipseUtils.openPreference(prefPageLink.getShell(),
+ "com.motorola.studio.android.localization.translators.preferencepage"); //$NON-NLS-1$
+ dialog.validate();
+ }
+ });
+ mainComposite.setLayoutData(new GridData(SWT.RIGHT, SWT.BOTTOM, false, false));
+ return mainComposite;
+ }
+
+ @Override
+ public String canTranslate(String fromLanguage, String[] toLanguages)
+ {
+ return getApiKey() == null || GoogleTranslatorConstants.API_KEY.equals(getApiKey())
+ ? TranslateNLS.GoogleTranslator_ErrorNoAPIkeySet : null;
+ }
+} \ No newline at end of file
diff --git a/src/plugins/translation/src/com/motorola/studio/android/localization/translators/GoogleTranslatorConstants.java b/src/plugins/translation/src/com/motorola/studio/android/localization/translators/GoogleTranslatorConstants.java
new file mode 100644
index 0000000..b6730c9
--- /dev/null
+++ b/src/plugins/translation/src/com/motorola/studio/android/localization/translators/GoogleTranslatorConstants.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.motorola.studio.android.localization.translators;
+
+import org.eclipse.sequoyah.localization.tools.extensions.implementation.generic.TranslatorConstants;
+
+/**
+ * Constants used by the GoogleTranslator class
+ * and its users.
+ */
+public interface GoogleTranslatorConstants extends TranslatorConstants
+{
+
+ //API Key to identify MOTODEV site
+ static final String API_KEY =
+ "ABQIAAAAzLP1ONRdncTVQSc4T1g2MRT7zv61Fj6qXODo5OU8i7eIwTs2GRQjZ2moI_dkzMckcgUZys7M9wAMvQ";
+
+ public static final String API_KEY_VALUE_PREFERENCE = "google.translator.apikey";
+
+ // Encoding type
+ public static final String ENCODING_TYPE = "UTF-8";
+
+ /**
+ * Parameter used to create URL
+ */
+ public static final String SOURCE_PAR = "&source=";
+
+ /**
+ * Parameter used to create URL
+ */
+ public static final String STRING_PAR = "&q=";
+
+ /**
+ * Parameter used to create URL
+ */
+ public static final String TARGET_PARAM = "&target=";
+
+ /**
+ * Parameter used to create URL
+ */
+ public static final String API_KEY_PARAM = "&key=";
+
+ /**
+ * The base URL to access the translation service.
+ * the #FROM# and #TO# parts are replaced on execution time.
+ */
+ public static final String URL_PARAMETERS = API_KEY_PARAM + "#API_KEY#" + SOURCE_PAR + "#FROM#"
+ + TARGET_PARAM + "#TO#";
+
+ /**
+ * The base URL to access the translation service, without the parameters.
+ * The parameters are created on real time when needed.
+ */
+ public static final String TRANSLATE_URL_WITHOUT_PARAMS =
+ "https://www.googleapis.com/language/translate/v2?prettyprint=false";
+
+ /**
+ * The base URL to access the translation service.
+ * the #FROM# and #TO# parts are replaced on execution time.
+ */
+ public static final String BASE_TRANSLATE_URL = TRANSLATE_URL_WITHOUT_PARAMS + URL_PARAMETERS;
+
+ /**
+ * Text that appears just before the translated text begins
+ * on a typical answer from the web server
+ */
+ public static final String TRANSLATED_TEXT_KEY = "translatedText";
+
+ /**
+ * Text defining the translation section of response
+ */
+ public static final String TRANSLATIONS_SECTION = "translations";
+
+ /**
+ * Text defining the error section of response
+ */
+ public static final String ERROR_SECTION = "error";
+
+ /**
+ * Text defining the message section of response
+ */
+ public static final String MESSAGE_TEXT = "message";
+
+ //Max string size
+ public static int MAX_SIZE = 100000;
+
+ //Max string size
+ public static int MAX_QUERY_SIZE = 2000; // google rules!! Do not change without VT
+
+ //Number of retries for the http request when there are connection problems
+ public static final int RETRIES = 0;
+
+ //Timeout in miliseconds for the http queries
+ public static final int TIMEOUT = 4000;
+
+ //HTTP Header constant to set the referer
+ public static final String REFERER_HEADER = "Referer";
+
+ // Site to be used as a referer site
+ public static final String REFERER_SITE = "http://developer.motorola.com";
+
+}
diff --git a/src/plugins/translation/src/com/motorola/studio/android/localization/translators/TranslationPlugin.java b/src/plugins/translation/src/com/motorola/studio/android/localization/translators/TranslationPlugin.java
new file mode 100644
index 0000000..f97b55d
--- /dev/null
+++ b/src/plugins/translation/src/com/motorola/studio/android/localization/translators/TranslationPlugin.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.motorola.studio.android.localization.translators;
+
+import org.eclipse.ui.plugin.AbstractUIPlugin;
+import org.osgi.framework.BundleContext;
+
+import com.motorola.studio.android.common.log.StudioLogger;
+
+public class TranslationPlugin extends AbstractUIPlugin
+{
+
+ /**
+ * The plug-in ID
+ */
+ public static final String PLUGIN_ID = "com.motorola.studio.android.translation";
+
+ // The shared instance
+ private static TranslationPlugin plugin;
+
+ public TranslationPlugin()
+ {
+ plugin = this;
+ }
+
+ /**
+ * Returns the shared instance
+ *
+ * @return the shared instance
+ */
+ public static TranslationPlugin getDefault()
+ {
+ return plugin;
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#start(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void start(BundleContext context) throws Exception
+ {
+ StudioLogger.debug(TranslationPlugin.class,
+ "Starting MOTODEV Studio for Android Translation Plugin...");
+
+ super.start(context);
+
+ StudioLogger.debug(TranslationPlugin.class,
+ "MOTODEV Studio for Android Translation Plugin started.");
+ }
+
+ /*
+ * (non-Javadoc)
+ * @see org.eclipse.ui.plugin.AbstractUIPlugin#stop(org.osgi.framework.BundleContext)
+ */
+ @Override
+ public void stop(BundleContext context) throws Exception
+ {
+ plugin = null;
+ super.stop(context);
+ }
+
+}
diff --git a/src/plugins/translation/src/com/motorola/studio/android/localization/translators/i18n/TranslateNLS.java b/src/plugins/translation/src/com/motorola/studio/android/localization/translators/i18n/TranslateNLS.java
new file mode 100644
index 0000000..32dc8fa
--- /dev/null
+++ b/src/plugins/translation/src/com/motorola/studio/android/localization/translators/i18n/TranslateNLS.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.motorola.studio.android.localization.translators.i18n;
+
+import org.eclipse.osgi.util.NLS;
+
+public class TranslateNLS extends NLS
+{
+ static
+ {
+ NLS.initializeMessages(
+ "com.motorola.studio.android.localization.translators.i18n.translateNLS", //$NON-NLS-1$
+ TranslateNLS.class);
+ }
+
+ public static String GoogleTranslator_ChangeAPIkeyLabel;
+
+ public static String GoogleTranslator_Error_CannotConnectToServer;
+
+ public static String GoogleTranslator_Error_HTTPRequestError;
+
+ public static String GoogleTranslator_Error_NoAvailableData;
+
+ public static String GoogleTranslator_Error_QueryTooBig;
+
+ public static String GoogleTranslator_Error_ToAndFromLanguagesAreEmpty;
+
+ public static String GoogleTranslator_Error_UnsupportedEncoding;
+
+ public static String GoogleTranslator_ErrorMessageExecutingRequest;
+
+ public static String GoogleTranslator_ErrorMessageNoValidTranslationReturned;
+
+ public static String GoogleTranslator_ErrorNoAPIkeySet;
+
+ public static String AndroidPreferencePage_googleApiKey_GroupLabel;
+
+ public static String AndroidPreferencePage_googleApiKey_Label;
+
+ public static String AndroidPreferencePage_googleApiKey_Note;
+
+ public static String AndroidPreferencePage_googleApiKey_Tooltip;
+
+}
diff --git a/src/plugins/translation/src/com/motorola/studio/android/localization/translators/i18n/translateNLS.properties b/src/plugins/translation/src/com/motorola/studio/android/localization/translators/i18n/translateNLS.properties
new file mode 100644
index 0000000..5eb661f
--- /dev/null
+++ b/src/plugins/translation/src/com/motorola/studio/android/localization/translators/i18n/translateNLS.properties
@@ -0,0 +1,15 @@
+GoogleTranslator_ChangeAPIkeyLabel=<a>Change your API key</a>
+GoogleTranslator_Error_CannotConnectToServer=Cannot connect to HTTP server:
+GoogleTranslator_Error_HTTPRequestError=Answer for the HTTP request was not OK. Error code: {0}. Error message: {1}.
+GoogleTranslator_Error_NoAvailableData=List of words to be translated cannot be empty
+GoogleTranslator_Error_QueryTooBig=Cannot execute query; query text is too long
+GoogleTranslator_Error_ToAndFromLanguagesAreEmpty='To' and 'From' languages cannot be empty
+GoogleTranslator_Error_UnsupportedEncoding=Unsupported encoding type:
+GoogleTranslator_ErrorMessageExecutingRequest=An error occurred trying to execute your translation request: {0}
+GoogleTranslator_ErrorMessageNoValidTranslationReturned=The translation service did not return a valid translation. The daily limit for accessing the Google Translate API may have been reached or your API key is wrong.\nService response message is: {0}
+GoogleTranslator_ErrorNoAPIkeySet=You must enter your own API key
+
+AndroidPreferencePage_googleApiKey_GroupLabel=Google Translate API
+AndroidPreferencePage_googleApiKey_Label=API Key:
+AndroidPreferencePage_googleApiKey_Note=Note: to obtain your own API key, go to the Google APIs Console at <a>{0}</a>
+AndroidPreferencePage_googleApiKey_Tooltip=Supply the API key to be used to access the Google Translate API \ No newline at end of file
diff --git a/src/plugins/translation/src/com/motorola/studio/android/localization/translators/preferences/ui/TranslationPreferencePage.java b/src/plugins/translation/src/com/motorola/studio/android/localization/translators/preferences/ui/TranslationPreferencePage.java
new file mode 100644
index 0000000..95904c0
--- /dev/null
+++ b/src/plugins/translation/src/com/motorola/studio/android/localization/translators/preferences/ui/TranslationPreferencePage.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.motorola.studio.android.localization.translators.preferences.ui;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import org.eclipse.core.runtime.preferences.IEclipsePreferences;
+import org.eclipse.core.runtime.preferences.InstanceScope;
+import org.eclipse.jface.preference.IPreferenceStore;
+import org.eclipse.jface.preference.PreferencePage;
+import org.eclipse.swt.SWT;
+import org.eclipse.swt.events.ModifyEvent;
+import org.eclipse.swt.events.ModifyListener;
+import org.eclipse.swt.events.SelectionAdapter;
+import org.eclipse.swt.events.SelectionEvent;
+import org.eclipse.swt.layout.GridData;
+import org.eclipse.swt.layout.GridLayout;
+import org.eclipse.swt.widgets.Composite;
+import org.eclipse.swt.widgets.Control;
+import org.eclipse.swt.widgets.Group;
+import org.eclipse.swt.widgets.Label;
+import org.eclipse.swt.widgets.Link;
+import org.eclipse.swt.widgets.Text;
+import org.eclipse.ui.IWorkbench;
+import org.eclipse.ui.IWorkbenchPreferencePage;
+import org.eclipse.ui.PartInitException;
+import org.eclipse.ui.PlatformUI;
+import org.eclipse.ui.browser.IWebBrowser;
+import org.eclipse.ui.browser.IWorkbenchBrowserSupport;
+import org.osgi.service.prefs.BackingStoreException;
+
+import com.motorola.studio.android.common.log.StudioLogger;
+import com.motorola.studio.android.localization.translators.GoogleTranslatorConstants;
+import com.motorola.studio.android.localization.translators.TranslationPlugin;
+import com.motorola.studio.android.localization.translators.i18n.TranslateNLS;
+
+public class TranslationPreferencePage extends PreferencePage implements IWorkbenchPreferencePage
+{
+ private final String GOOGLE_APIS_CONSOLE_LINK = "http://code.google.com/apis/console/"; //$NON-NLS-1$
+
+ private Text apiKeyText;
+
+ private String apiKeyValue;
+
+ public void init(IWorkbench workbench)
+ {
+ noDefaultAndApplyButton();
+ }
+
+ @Override
+ public boolean performOk()
+ {
+ InstanceScope scope = (InstanceScope) InstanceScope.INSTANCE;
+ IEclipsePreferences prefs = scope.getNode(TranslationPlugin.PLUGIN_ID);
+ if (apiKeyValue.trim().length() == 0)
+ {
+ prefs.remove(GoogleTranslatorConstants.API_KEY_VALUE_PREFERENCE);
+ }
+ else
+ {
+ prefs.put(GoogleTranslatorConstants.API_KEY_VALUE_PREFERENCE, apiKeyValue.trim());
+ }
+
+ try
+ {
+ prefs.flush();
+ }
+ catch (BackingStoreException e)
+ {
+ //do nothing
+ }
+
+ return super.performOk();
+ }
+
+ @Override
+ protected Control createContents(Composite parent)
+ {
+ Composite entryTable = new Composite(parent, SWT.NULL);
+ GridData data = new GridData(SWT.FILL, SWT.TOP, true, false);
+ entryTable.setLayoutData(data);
+
+ GridLayout layout = new GridLayout();
+ entryTable.setLayout(layout);
+
+ layout = new GridLayout(2, false);
+
+ layout = new GridLayout(2, false);
+ Group translatorAPIGroup = new Group(entryTable, SWT.NONE);
+ translatorAPIGroup.setLayout(layout);
+ translatorAPIGroup.setLayoutData(new GridData(SWT.FILL, SWT.TOP, true, false));
+ translatorAPIGroup.setText(TranslateNLS.AndroidPreferencePage_googleApiKey_GroupLabel);
+
+ Link noteLabel = new Link(translatorAPIGroup, SWT.WRAP);
+ noteLabel.setText(TranslateNLS.bind(TranslateNLS.AndroidPreferencePage_googleApiKey_Note,
+ GOOGLE_APIS_CONSOLE_LINK));
+ data = new GridData(SWT.FILL, SWT.CENTER, true, false, 2, 1);
+ data.widthHint = 450;
+ noteLabel.setLayoutData(data);
+
+ noteLabel.addSelectionListener(new SelectionAdapter()
+ {
+ /* (non-Javadoc)
+ * @see org.eclipse.swt.events.SelectionAdapter#widgetSelected(org.eclipse.swt.events.SelectionEvent)
+ */
+ @Override
+ public void widgetSelected(SelectionEvent e)
+ {
+ IWorkbenchBrowserSupport browserSupport =
+ PlatformUI.getWorkbench().getBrowserSupport();
+
+ /*
+ * open the browser
+ */
+ IWebBrowser browser;
+ try
+ {
+ browser =
+ browserSupport.createBrowser(IWorkbenchBrowserSupport.LOCATION_BAR
+ | IWorkbenchBrowserSupport.NAVIGATION_BAR
+ | IWorkbenchBrowserSupport.AS_EXTERNAL, "MOTODEV", null, null); //$NON-NLS-1$
+
+ browser.openURL(new URL(GOOGLE_APIS_CONSOLE_LINK));
+ }
+ catch (PartInitException ex)
+ {
+ StudioLogger.error("Error opening the Google APIs Console link: " //$NON-NLS-1$
+ + ex.getMessage());
+ }
+ catch (MalformedURLException ex)
+ {
+ StudioLogger.error("Error opening the Google APIs Console link: " //$NON-NLS-1$
+ + ex.getMessage());
+ }
+ }
+ });
+
+ Label apiKeyLabel = new Label(translatorAPIGroup, SWT.NONE);
+ apiKeyLabel.setText(TranslateNLS.AndroidPreferencePage_googleApiKey_Label);
+ data = new GridData(SWT.LEFT, SWT.CENTER, false, false, 1, 1);
+ apiKeyLabel.setLayoutData(data);
+
+ apiKeyText = new Text(translatorAPIGroup, SWT.BORDER);
+ apiKeyValue = getApiKey();
+ apiKeyText.setText(apiKeyValue);
+ apiKeyText.setToolTipText(TranslateNLS.AndroidPreferencePage_googleApiKey_Tooltip);
+ data = new GridData(SWT.FILL, SWT.CENTER, true, false, 1, 1);
+ apiKeyText.setLayoutData(data);
+ apiKeyText.addModifyListener(new ModifyListener()
+ {
+ public void modifyText(ModifyEvent e)
+ {
+ apiKeyValue = apiKeyText.getText();
+
+ }
+ });
+
+ return entryTable;
+ }
+
+ /**
+ * get the apikey
+ * @return the apikey or an empty string for the default one
+ */
+ private static String getApiKey()
+ {
+ String apiKey = ""; //$NON-NLS-1$
+ IPreferenceStore prefStore = TranslationPlugin.getDefault().getPreferenceStore();
+ if (!prefStore.isDefault(GoogleTranslatorConstants.API_KEY_VALUE_PREFERENCE))
+ {
+ apiKey = prefStore.getString(GoogleTranslatorConstants.API_KEY_VALUE_PREFERENCE);
+ if (apiKey == null)
+ {
+ apiKey = ""; //$NON-NLS-1$
+ }
+ }
+
+ return apiKey;
+ }
+
+}