[gnome-subtitles] Added initial support for automatic translation, based on a patch from David Krkoska (bug #595084).
- From: Pedro Daniel da Rocha Melo e Castro <pcastro src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-subtitles] Added initial support for automatic translation, based on a patch from David Krkoska (bug #595084).
- Date: Sun, 10 Apr 2011 21:26:42 +0000 (UTC)
commit 082d0a19fd6d17a1fa157e915220fe4dbc960ce2
Author: Pedro Castro <mail pedrocastro org>
Date: Sun Apr 10 22:25:49 2011 +0100
Added initial support for automatic translation, based on a patch from David Krkoska (bug #595084). Currently only 1 subtitle can be translated at a time, and Google Translation is used.
gnome-subtitles.mdp | 4 +
src/Glade/MainWindow.glade | 49 ++++++--
.../Core/Command/TranslatorCommand.cs | 108 ++++++++++++++++
src/GnomeSubtitles/Core/EventHandlers.cs | 10 ++-
src/GnomeSubtitles/Ui/Menus.cs | 8 +-
src/GnomeSubtitles/Ui/WidgetNames.cs | 2 +
src/SubLib/Core/Translator.cs | 133 ++++++++++++++++++++
src/SubLib/Exceptions/TranslatorException.cs | 36 ++++++
8 files changed, 336 insertions(+), 14 deletions(-)
---
diff --git a/gnome-subtitles.mdp b/gnome-subtitles.mdp
index 4a1bed8..e22ffb8 100644
--- a/gnome-subtitles.mdp
+++ b/gnome-subtitles.mdp
@@ -251,6 +251,9 @@
<File subtype="Code" buildaction="Compile" name="src/GnomeSubtitles/Ui/VideoPreview/SubtitleTracker.cs" />
<File subtype="Code" buildaction="Compile" name="src/GnomeSubtitles/Core/Backup.cs" />
<File subtype="Code" buildaction="Compile" name="src/SubLib/IO/SubtitleFormats/SubtitleFormatFABSubtitler.cs" />
+ <File subtype="Code" buildaction="Compile" name="src/GnomeSubtitles/Core/Command/TranslatorCommand.cs" />
+ <File subtype="Code" buildaction="Compile" name="src/SubLib/Exceptions/TranslatorException.cs" />
+ <File subtype="Code" buildaction="Compile" name="src/SubLib/Core/Translator.cs" />
</Contents>
<References>
<ProjectReference type="Gac" localcopy="True" refto="Mono.Posix, Version=2.0.0.0, Culture=neutral, PublicKeyToken=0738eb9f132ed756" />
@@ -261,6 +264,7 @@
<ProjectReference type="Gac" localcopy="True" refto="glade-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
<ProjectReference type="Gac" localcopy="True" refto="gconf-sharp, Version=2.24.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
<ProjectReference type="Gac" localcopy="True" refto="glib-sharp, Version=2.12.0.0, Culture=neutral, PublicKeyToken=35e10195dab3c99f" />
+ <ProjectReference type="Gac" localcopy="True" refto="System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a" />
</References>
<LanguageParameters StartupObject="GnomeSubtitles.Execution.Executable" ApplicationIcon="." ctype="CSharpProjectParameters" />
<DeploymentInformation strategy="File" />
diff --git a/src/Glade/MainWindow.glade b/src/Glade/MainWindow.glade
index 545a245..f38a59f 100644
--- a/src/Glade/MainWindow.glade
+++ b/src/Glade/MainWindow.glade
@@ -1,4 +1,4 @@
-<?xml version="1.0"?>
+<?xml version="1.0" encoding="UTF-8"?>
<glade-interface>
<!-- interface-requires gtk+ 2.16 -->
<!-- interface-naming-policy toplevel-contextual -->
@@ -248,8 +248,8 @@
<property name="use_underline">True</property>
<property name="use_stock">True</property>
<signal name="activate" handler="OnEditRedo"/>
- <accelerator key="Y" signal="activate" modifiers="GDK_CONTROL_MASK"/>
<accelerator key="Z" signal="activate" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/>
+ <accelerator key="Y" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</widget>
</child>
<child>
@@ -544,8 +544,8 @@
<property name="label" translatable="yes">Find Ne_xt</property>
<property name="use_underline">True</property>
<signal name="activate" handler="OnSearchFindNext"/>
- <accelerator key="F3" signal="activate"/>
<accelerator key="g" signal="activate" modifiers="GDK_CONTROL_MASK"/>
+ <accelerator key="F3" signal="activate"/>
</widget>
</child>
<child>
@@ -555,8 +555,8 @@
<property name="label" translatable="yes">Find Pre_vious</property>
<property name="use_underline">True</property>
<signal name="activate" handler="OnSearchFindPrevious"/>
- <accelerator key="F3" signal="activate" modifiers="GDK_SHIFT_MASK"/>
<accelerator key="g" signal="activate" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/>
+ <accelerator key="F3" signal="activate" modifiers="GDK_SHIFT_MASK"/>
</widget>
</child>
<child>
@@ -800,8 +800,8 @@
<property name="use_underline">True</property>
<property name="use_stock">False</property>
<signal name="activate" handler="OnVideoPlayPause"/>
- <accelerator key="F5" signal="activate"/>
<accelerator key="p" signal="activate" modifiers="GDK_CONTROL_MASK"/>
+ <accelerator key="F5" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="videoPlayPauseImage">
<property name="visible">True</property>
@@ -828,8 +828,8 @@
<property name="use_underline">True</property>
<property name="use_stock">False</property>
<signal name="activate" handler="OnVideoRewind"/>
- <accelerator key="F6" signal="activate"/>
<accelerator key="k" signal="activate" modifiers="GDK_CONTROL_MASK"/>
+ <accelerator key="F6" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="videoRewindImage">
<property name="visible">True</property>
@@ -847,8 +847,8 @@
<property name="use_underline">True</property>
<property name="use_stock">False</property>
<signal name="activate" handler="OnVideoForward"/>
- <accelerator key="F7" signal="activate"/>
<accelerator key="l" signal="activate" modifiers="GDK_CONTROL_MASK"/>
+ <accelerator key="F7" signal="activate"/>
<child internal-child="image">
<widget class="GtkImage" id="videoForwardImage">
<property name="visible">True</property>
@@ -888,8 +888,8 @@
<property name="label" translatable="yes">Seek _to Selection</property>
<property name="use_underline">True</property>
<signal name="activate" handler="OnVideoSeekToSelection"/>
- <accelerator key="F4" signal="activate" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/>
<accelerator key="r" signal="activate" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/>
+ <accelerator key="F4" signal="activate" modifiers="GDK_SHIFT_MASK | GDK_CONTROL_MASK"/>
</widget>
</child>
<child>
@@ -899,8 +899,8 @@
<property name="label" translatable="yes">Select Nearest Subtitle</property>
<property name="use_underline">True</property>
<signal name="activate" handler="OnVideoSelectNearestSubtitle"/>
- <accelerator key="r" signal="activate" modifiers="GDK_CONTROL_MASK"/>
<accelerator key="F4" signal="activate" modifiers="GDK_CONTROL_MASK"/>
+ <accelerator key="r" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</widget>
</child>
<child>
@@ -909,8 +909,8 @@
<property name="label" translatable="yes">Auto Select Subtitle</property>
<property name="use_underline">True</property>
<signal name="toggled" handler="OnVideoAutoSelectSubtitles"/>
- <accelerator key="j" signal="activate" modifiers="GDK_CONTROL_MASK"/>
<accelerator key="F3" signal="activate" modifiers="GDK_CONTROL_MASK"/>
+ <accelerator key="j" signal="activate" modifiers="GDK_CONTROL_MASK"/>
</widget>
</child>
<child>
@@ -967,7 +967,7 @@
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
- <property name="label" translatable="yes">Set _Text Language</property>
+ <property name="label" translatable="yes">Set T_ext Language</property>
<property name="use_underline">True</property>
<signal name="activate" handler="OnToolsSetTextLanguage"/>
</widget>
@@ -977,11 +977,36 @@
<property name="visible">True</property>
<property name="sensitive">False</property>
<property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
- <property name="label" translatable="yes">Set Translatio_n Language</property>
+ <property name="label" translatable="yes">Set Translati_on Language</property>
<property name="use_underline">True</property>
<signal name="activate" handler="OnToolsSetTranslationLanguage"/>
</widget>
</child>
+ <child>
+ <widget class="GtkSeparatorMenuItem" id="toolsSeparator1">
+ <property name="visible">True</property>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="toolsTranslateText">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="label" translatable="yes">Translate _Text â?? Translation</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="OnToolsTranslateText"/>
+ </widget>
+ </child>
+ <child>
+ <widget class="GtkMenuItem" id="toolsTranslateTranslation">
+ <property name="visible">True</property>
+ <property name="sensitive">False</property>
+ <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property>
+ <property name="label" translatable="yes">Translate Translatio_n â?? Text</property>
+ <property name="use_underline">True</property>
+ <signal name="activate" handler="OnToolsTranslateTranslation"/>
+ </widget>
+ </child>
</widget>
</child>
</widget>
diff --git a/src/GnomeSubtitles/Core/Command/TranslatorCommand.cs b/src/GnomeSubtitles/Core/Command/TranslatorCommand.cs
new file mode 100644
index 0000000..889c481
--- /dev/null
+++ b/src/GnomeSubtitles/Core/Command/TranslatorCommand.cs
@@ -0,0 +1,108 @@
+/*
+ * This file is part of Gnome Subtitles.
+ * Copyright (C) 2011 Pedro Castro
+ *
+ * Gnome Subtitles is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Gnome Subtitles is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+using GnomeSubtitles.Dialog;
+using GnomeSubtitles.Dialog.Unmanaged;
+using GnomeSubtitles.Ui.Edit;
+using Gtk;
+using Mono.Unix;
+using SubLib;
+using SubLib.Core;
+using SubLib.Core.Domain;
+using SubLib.Exceptions;
+using System;
+
+namespace GnomeSubtitles.Core.Command {
+
+public class TranslatorCommand : FixedSingleSelectionCommand {
+ private string previousValue = null; // initially, it's the former text replaced by translation
+ private bool leftToRight = true; // direction of translation
+ private static string description = Catalog.GetString("Translating");
+
+ public TranslatorCommand (bool leftToRight) : base(description, false, true) {
+ this.leftToRight = leftToRight;
+ }
+
+ /* Public members */
+
+ protected override bool ChangeValues () {
+ /* If previousText is null, it's the first time the command is executed, so do translation.
+ Otherwise, it's undo or redo, so we only need to swap the values */
+ if (previousValue == null)
+ return DoTranslation();
+ else {
+ Subtitle subtitle = Base.Document.Subtitles[Path];
+ if (leftToRight) {
+ string currentValue = subtitle.Translation.Get();
+ subtitle.Translation.Set(this.previousValue);
+ this.previousValue = currentValue;
+ }
+ else {
+ string currentValue = subtitle.Text.Get();
+ subtitle.Text.Set(this.previousValue);
+ this.previousValue = currentValue;
+ }
+ return true;
+ }
+ }
+
+ private bool DoTranslation () {
+ if (Base.Ui.View.Selection.Count != 1) //TODO: for now, only works if 1 subtitle is selected
+ return false;
+
+ /* Show language selection dialogs if no languages are selected */
+ if (!Base.SpellLanguages.HasActiveTextLanguage) {
+ Base.Dialogs.Get(typeof(SetTextLanguageDialog)).Show();
+ if (!Base.SpellLanguages.HasActiveTextLanguage)
+ return false;
+ }
+
+ if (!Base.SpellLanguages.HasActiveTranslationLanguage) {
+ Base.Dialogs.Get(typeof(SetTranslationLanguageDialog)).Show();
+ if (!Base.SpellLanguages.HasActiveTranslationLanguage)
+ return false;
+ }
+
+ try {
+ Subtitle subtitle = Base.Document.Subtitles[Path];
+ if (leftToRight) {
+ this.previousValue = subtitle.Translation.Get();
+ string translatedText = Translator.TranslateText(subtitle.Text.Get(), Base.SpellLanguages.ActiveTextLanguage.ID, Base.SpellLanguages.ActiveTranslationLanguage.ID, Translator.TIMEOUT);
+ subtitle.Translation.Set(translatedText);
+ }
+ else {
+ this.previousValue = subtitle.Text.Get();
+ string translatedText = Translator.TranslateText(subtitle.Translation.Get(), Base.SpellLanguages.ActiveTranslationLanguage.ID, Base.SpellLanguages.ActiveTextLanguage.ID, Translator.TIMEOUT);
+ subtitle.Text.Set(translatedText);
+ }
+
+ //TODO: if only one subtitle selected, set the cursor on the translated text box and select its text. If multiple subtitles translated, select those subtitles.
+ return true;
+ }
+ catch (TranslatorException e) { //TODO know which exceptions are originally thrown. Check if it's possible to have the second error message in the application language.
+ Console.Error.WriteLine(e);
+ BasicErrorDialog errorDialog = new BasicErrorDialog(Catalog.GetString("Could not translate the chosen subtitle."), e.Message);
+ errorDialog.Show();
+ return false;
+ }
+ }
+
+}
+
+}
diff --git a/src/GnomeSubtitles/Core/EventHandlers.cs b/src/GnomeSubtitles/Core/EventHandlers.cs
index f51b264..8261c05 100644
--- a/src/GnomeSubtitles/Core/EventHandlers.cs
+++ b/src/GnomeSubtitles/Core/EventHandlers.cs
@@ -1,6 +1,6 @@
/*
* This file is part of Gnome Subtitles.
- * Copyright (C) 2006-2010 Pedro Castro
+ * Copyright (C) 2006-2011 Pedro Castro
*
* Gnome Subtitles is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -348,6 +348,14 @@ public class EventHandlers {
public void OnToolsSetTranslationLanguage (object o, EventArgs args) {
Base.Dialogs.Get(typeof(SetTranslationLanguageDialog)).Show();
}
+
+ public void OnToolsTranslateText (object o, EventArgs args) {
+ Base.CommandManager.Execute(new TranslatorCommand(true));
+ }
+
+ public void OnToolsTranslateTranslation (object o, EventArgs args) {
+ Base.CommandManager.Execute(new TranslatorCommand(false));
+ }
/* Help Menu */
diff --git a/src/GnomeSubtitles/Ui/Menus.cs b/src/GnomeSubtitles/Ui/Menus.cs
index d1d1c60..d2506a3 100644
--- a/src/GnomeSubtitles/Ui/Menus.cs
+++ b/src/GnomeSubtitles/Ui/Menus.cs
@@ -1,6 +1,6 @@
/*
* This file is part of Gnome Subtitles.
- * Copyright (C) 2006-2010 Pedro Castro
+ * Copyright (C) 2006-2011 Pedro Castro
*
* Gnome Subtitles is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -141,6 +141,8 @@ public class Menus {
/// <param name="sensitivity">Whether the items are set sensitive.</param>
private void SetOneSelectionDependentSensitivity (bool sensitivity) {
SetVideoSelectionDependentSensitivity(sensitivity);
+ SetSensitivity(WidgetNames.ToolsTranslateText, sensitivity && Base.Document.IsTranslationLoaded);
+ SetSensitivity(WidgetNames.ToolsTranslateTranslation, sensitivity && Base.Document.IsTranslationLoaded);
}
private void SetSubtitleCountDependentSensitivity (int count) {
@@ -234,6 +236,10 @@ public class Menus {
SetSensitivity(WidgetNames.FileTranslationSaveAs, sensitivity);
SetSensitivity(WidgetNames.FileTranslationClose, sensitivity);
SetSensitivity(WidgetNames.ToolsSetTranslationLanguage, sensitivity);
+
+ bool oneSubtitleSelected = (Core.Base.Ui.View.Selection.Count == 1);
+ SetSensitivity(WidgetNames.ToolsTranslateText, sensitivity && oneSubtitleSelected);
+ SetSensitivity(WidgetNames.ToolsTranslateTranslation, sensitivity && oneSubtitleSelected);
SetViewVideoSubtitlesSensitivity();
}
diff --git a/src/GnomeSubtitles/Ui/WidgetNames.cs b/src/GnomeSubtitles/Ui/WidgetNames.cs
index ab9d506..f2cea75 100644
--- a/src/GnomeSubtitles/Ui/WidgetNames.cs
+++ b/src/GnomeSubtitles/Ui/WidgetNames.cs
@@ -89,6 +89,8 @@ public class WidgetNames {
public const string ToolsAutocheckSpelling = "toolsAutocheckSpelling";
public const string ToolsSetTextLanguage = "toolsSetTextLanguage";
public const string ToolsSetTranslationLanguage = "toolsSetTranslationLanguage";
+ public const string ToolsTranslateText = "toolsTranslateText";
+ public const string ToolsTranslateTranslation = "toolsTranslateTranslation";
/* Toolbar */
diff --git a/src/SubLib/Core/Translator.cs b/src/SubLib/Core/Translator.cs
new file mode 100644
index 0000000..de8ee35
--- /dev/null
+++ b/src/SubLib/Core/Translator.cs
@@ -0,0 +1,133 @@
+/*
+ * This file is part of SubLib.
+ * Copyright (C) 2011 Pedro Castro
+ *
+ * SubLib is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * SubLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+using SubLib.Core.Domain;
+using SubLib.Exceptions;
+using System;
+using System.Net;
+using System.IO;
+using System.Globalization;
+using System.Text.RegularExpressions;
+using System.Text;
+
+namespace SubLib.Core {
+ /// <summary>Allows translating subtitles from one language to another using Google Translate service.</summary>
+ public class Translator {
+ private const string REQUEST_URL_FORMAT = "http://ajax.googleapis.com/ajax/services/language/translate?v=1.0&{0}langpair={1}|{2}";
+ private const string REQUEST_LINE_FORMAT = "q={0}&";
+
+ private const char SPLIT_CHAR = '\n';
+ private const char CULTURE_REPLACEE = '_';
+ private const char CULTURE_REPLACER = '-';
+
+ private const string JSON_RESPONSE_SUCCESS = "200";
+
+ private const string REGEX_ERROR_MATCH = @"^.*\""responseDetails\"": (.+),.*\""responseStatus\"":.*([0-9][0-9][0-9]).*$";
+ private const string REGEX_RESPONSE_MATCH = @"\""translatedText\"":\""([^\""]*)";
+ private const int REGEX_MATCH_INDEX_ONE_VALUE = 1;
+ private const int REGEX_MATCH_INDEX_TWO_VALUE = 2;
+
+ public const int TIMEOUT = 3000;
+
+
+ /* Public methods */
+
+ /// <summary>Translates given text between two given languages.</summary>
+ public static string TranslateText (string inputText, string fromLanguage, string toLanguage, int timeoutMillis) {
+ // testing emptiness of the string
+ if (inputText.Trim().Length == 0)
+ return String.Empty;
+
+ // splitting input text into single lines; line-breaks cannot be transferred to Google Translate
+ StringBuilder stringBuilder = new StringBuilder();
+ foreach (String split in inputText.Split(SPLIT_CHAR)) {
+ stringBuilder.Append(String.Format(REQUEST_LINE_FORMAT, System.Web.HttpUtility.UrlEncode(split)));
+ }
+
+ try {
+ //TODO 'key' parameter could be added
+ // building request URL
+ string requestUrl = String.Format(REQUEST_URL_FORMAT, stringBuilder.ToString(),
+ CultureInfo.CreateSpecificCulture(fromLanguage.Replace(CULTURE_REPLACEE, CULTURE_REPLACER)).TwoLetterISOLanguageName.ToLowerInvariant(),
+ CultureInfo.CreateSpecificCulture(toLanguage.Replace(CULTURE_REPLACEE, CULTURE_REPLACER)).TwoLetterISOLanguageName.ToLowerInvariant()
+ );
+
+ // translating
+ HttpWebRequest req = HttpWebRequest.Create(requestUrl) as HttpWebRequest;
+ req.Timeout = timeoutMillis;
+ req.Method = WebRequestMethods.Http.Get;
+ HttpWebResponse res = req.GetResponse() as HttpWebResponse;
+
+ // processing response
+ string responseJson = new StreamReader(res.GetResponseStream()).ReadToEnd();
+
+ return ProcessJson(responseJson);
+ }
+ catch (Exception e) {
+ throw new TranslatorException(e.Message);
+ }
+ }
+
+
+ /* Private methods */
+
+ /// <summary>Processes JSON response from Google Translate service.</summary>
+ private static string ProcessJson (string responseJson) {
+ // fixing english-related quote problem
+ responseJson = responseJson.Replace("\\\"", "\\u0026quot;");
+
+ // matching responseStatus
+ StringBuilder stringBuilder = new StringBuilder();
+ Match match = Regex.Match(responseJson, REGEX_ERROR_MATCH, RegexOptions.IgnoreCase | RegexOptions.Compiled);
+ if (match.Success && match.Groups.Count > REGEX_MATCH_INDEX_TWO_VALUE && match.Groups[REGEX_MATCH_INDEX_TWO_VALUE].Value == JSON_RESPONSE_SUCCESS) {
+
+ // matching multi-line translated text and building output
+ bool first = true;
+ MatchCollection matchCollection = Regex.Matches(responseJson, REGEX_RESPONSE_MATCH, RegexOptions.IgnoreCase | RegexOptions.Compiled);
+ foreach (Match textMatch in matchCollection) {
+ if (textMatch.Success && textMatch.Groups.Count > REGEX_MATCH_INDEX_ONE_VALUE) {
+ if (!first)
+ stringBuilder.Append(SPLIT_CHAR);
+
+ stringBuilder.Append(textMatch.Groups[REGEX_MATCH_INDEX_ONE_VALUE].Value);
+ first = false;
+ }
+ }
+
+ // replacing escaped characters that are not decoded automatically
+ stringBuilder = stringBuilder.Replace("\\u0026#39", "'");
+ stringBuilder = stringBuilder.Replace("\\u0026quot;", "\"");
+ stringBuilder = stringBuilder.Replace("\\u0026amp;", "&");
+ stringBuilder = stringBuilder.Replace("\\u0026lt;", "<");
+ stringBuilder = stringBuilder.Replace("\\u0026qt;", ">");
+ stringBuilder = stringBuilder.Replace("\\u0026amp;", "&");
+ stringBuilder = stringBuilder.Replace("\\u0026", "&");
+ stringBuilder = stringBuilder.Replace("\\u003c", "<");
+ stringBuilder = stringBuilder.Replace("\\u003e", ">");
+ stringBuilder = stringBuilder.Replace("\\\\", "\\");
+
+ return System.Web.HttpUtility.UrlDecode(stringBuilder.ToString());
+ }
+ else {
+ throw new Exception((match.Groups.Count > REGEX_MATCH_INDEX_TWO_VALUE ? match.Groups[REGEX_MATCH_INDEX_TWO_VALUE].Value + ": " : String.Empty) + (match.Groups.Count > REGEX_MATCH_INDEX_ONE_VALUE ? match.Groups[REGEX_MATCH_INDEX_ONE_VALUE].Value : String.Empty));
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/src/SubLib/Exceptions/TranslatorException.cs b/src/SubLib/Exceptions/TranslatorException.cs
new file mode 100644
index 0000000..c48c4de
--- /dev/null
+++ b/src/SubLib/Exceptions/TranslatorException.cs
@@ -0,0 +1,36 @@
+/*
+ * This file is part of SubLib.
+ * Copyright (C) 2011 Pedro Castro
+ *
+ * SubLib is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * SubLib is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+using System;
+
+namespace SubLib.Exceptions {
+
+/// <summary>The exception that is thrown when error in any of Translator processes <see cref="Translator" /> occurs.</summary>
+public class TranslatorException : ApplicationException {
+ private static string defaultMessage = "Translator request failed.";
+
+ public TranslatorException (string message) : base(message) {
+ }
+
+ public TranslatorException() : base(defaultMessage) {
+ }
+
+}
+
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]