C#: Как извлечь перевод длинного текста из ответа Google Translate?

Есть метод для перевода текста через Google Translate без использования API v2, то есть через обычный WebClient.

Метод принимает аргументы text - исходный текст и to - язык, на который нужно перевести текст. Язык исходного текста задается как "auto", то есть должен определяться автоматически.

public static string Translate(string text, string to)
{
   var url = $"https://translate.googleapis.com/translate_a/single?client=gtx&sl=auto&tl={to}&dt=t&q={HttpUtility.UrlEncode(text)}";
   var webClient = new WebClient { Encoding = Encoding.UTF8 };
   var result = webClient.DownloadString(url);
   try
   {
       result = result.Substring(4, result.IndexOf("\"", 4, StringComparison.Ordinal) - 4);
       return result;
   }
   catch (Exception e)
   {
       Console.WriteLine($"Transalte Error: {e.Message}");
       return null;
   }
}

Проблема:

С простым текстом из нескольких слов все работает отлично, но если задать текст из нескольких строк (с содержанием \n) или предложений, то метод возвращает перевод только первого предложения.

Причина:

Это происходит потому что Google Translate возвращает перевод отдельных предложений (или строк (\n)) не в одной строке, а в нескольких.

Например, при вызове метода с такими входным данными

string text = @"Нижняя сторона крыльев менее яркая, но более пёстрая. Она коричневато-бурая, с разнообразными красноватыми и белыми пятнами и серыми разводами. Снизу на передних крыльях повторяется рисунок верхней стороны, который дополняется голубыми кольцами в центральной ячейке. Нижняя сторона задних крыльев коричневатая, с замысловатым мраморовидным рисунком, образованным за счет тёмных штрихов и извилистых линий. Также у переднего края заднего крыла находится светлое пятно";
Translate(text, "en");

Метод вернет только первое предложение

"The underside of the wings is less bright, but more variegated. "

А результат будет таким:

[[["The underside of the wings is less bright, but more variegated. ","Нижняя сторона крыльев менее яркая, но более пёстрая.",null,null,3,null,null,[[]],[[["d79f3353813f458ef00a8442f9b7b2b6","ru_en_2022q1.md"]]]],["It is brownish-brown, with a variety of reddish and white spots and gray stains. ","Она коричневато-бурая, с разнообразными красноватыми и белыми пятнами и серыми разводами.",null,null,3,null,null,[[]],[[["d79f3353813f458ef00a8442f9b7b2b6","ru_en_2022q1.md"]]]],["From below on the forewings, the pattern of the upper side is repeated, which is complemented by blue rings in the central cell. ","Снизу на передних крыльях повторяется рисунок верхней стороны, который дополняется голубыми кольцами в центральной ячейке.",null,null,3,null,null,[[]],[[["d79f3353813f458ef00a8442f9b7b2b6","ru_en_2022q1.md"]]]],["The underside of the hindwings is brownish, with an intricate marble-like pattern formed by dark strokes and sinuous lines. ","Нижняя сторона задних крыльев коричневатая, с замысловатым мраморовидным рисунком, образованным за счет тёмных штрихов и извилистых линий.",null,null,3,null,null,[[]],[[["d79f3353813f458ef00a8442f9b7b2b6","ru_en_2022q1.md"]]]],["There is also a light spot at the anterior edge of the hind wing.","Также у переднего края заднего крыла находится светлое пятно",null,null,3,null,null,[[]],[[["d79f3353813f458ef00a8442f9b7b2b6","ru_en_2022q1.md"]]]]],null,"ru",null,null,null,1,[],[["ru"],null,[1],["ru"]]]

В то время как текст из одного предложения метод вернет корректно, потому что есть всего одно предложение.

Попытки решения:

Я пробовал заменять символы переноса строки и возврата каретки на \n->\\n и \r->\\r, а затем в получившемся тексте возвращать их обратно и это работало, но как мне кажется, это не совсем правильное решение. Тем более, что текст с точками (из нескольких предложений) все равно возвращается в виде одного предложения и точки так будет заменять некорректно.

В Python по этому объекту можно было бы просто пробежаться циклом for как по списку и получить нужные данные, но в C# из-за строгой типизации я даже не представляю как десериализовать этот объект.

Может быть есть еще какой-то способ?


Ответы (1 шт):

Автор решения: denisnumb

Благодаря @EvgeniyZ получилось такое решение:

Поскольку JSON-ответ от Google Translate проблемно десериализовать стандартными методами от System.Json.Text, решением стал конвертер черезNewtonsoft.Json:

// здесь result - это полный ответ от Google Translate
var json = Newtonsoft.Json.JsonConvert.DeserializeObject<object[][][]>(result, new Newtonsoft.Json.JsonSerializerSettings
{
  Error = (_, e) => { e.ErrorContext.Handled = true; }
});

// здесь берем элемент с индексом 1, то есть строку с переведенным текстом
// а затем выполняем вход отдельных предложений в строку через пробел
// с заменой `\n ` на `\n`, чтобы текст в новой строке не начинался с пробела
result = string.Join(" ", json[0].SelectMany(x => x.Skip(0)?.Take(1)).Cast<string>()).Replace("\\n", "\n").Replace("\n ", "\n");
→ Ссылка