[C#]使用Microsoft Translator Soap API實作翻譯功能
要使用Microsoft Translator Soap API實作翻譯功能,首先我們必須要有Bing的開發者ID,可至Bing Developer網站申請。可點選『註冊以使用 Bing 搜尋 API 並建立 AppID』或是透過『建立您的 AppID』開始進行申請。
接著按下『Add』按鈕新增一個應用程式。
填寫要申請的應用程式相關資訊。
都填好後系統會給予申請的應用程式一個Application ID,後續的開發會時常的需要帶入這個Application ID。
有了Application ID後,在方案總管上按下右鍵,在彈出的滑鼠右鍵快顯選單中選取Add Service Reference, Visual Studio會帶出Add Service Reference對話方塊,在Address欄位中填入http://api.microsofttranslator.com/V2/Soap.svc後按下OK,這樣就完成了引用的動作,可以直接在程式中使用到Soap API現成的類別。
接下來進入程式開發的階段,整個Microsoft Translator Soap API在使用上,最重要的類別就是LanguageServiceClient,必須建立一個LanguageServiceClient物件實體並對其操作,以完成我們想要的功能,像是偵測要翻譯的字串訊息是屬於哪種語言、如何取得可使用的語言清單、針對翻譯的內容發音、以及最重要的翻譯動作。
在偵測翻譯的字串訊息是屬於哪種語言上,我們可透過現成的API去偵測,將Application ID與要偵測的字串帶入。
http://api.microsofttranslator.com/V2/Http.svc/Detect?appId=[APP ID]&text=[字串訊息]
該API會回傳入下XML。
因此在程式的撰寫上我們可以用WebRequest與WebResponse去取得網頁的內容,並擷取回傳的XML中我們感興趣的部分,就像是下面這樣:
string GetDetectedLanguage(string text)
{
const string DEFAULT_DETECTED_LANG = "en";
if (String.IsNullOrEmpty(text))
return DEFAULT_DETECTED_LANG;
const string DETECT_API_URI_PATTERN = "http://api.microsofttranslator.com/V2/Http.svc/Detect?appId={0}&text={1}";
const string MATCH_PATTERN = "<[^<>]*>([^<>]*)<[^<>]*>";
WebRequest req = WebRequest.Create(String.Format(DETECT_API_URI_PATTERN, APP_ID, text));
WebResponse resp = req.GetResponse();
string local = DEFAULT_DETECTED_LANG;
using (StreamReader reader = new StreamReader(resp.GetResponseStream()))
{
local = reader.ReadToEnd();
local = Regex.Match(local, MATCH_PATTERN).Groups[1].Value;
}
return local;
}
在發音方面,可透過LanguageServiceClient.GetLanguagesForSpeak與LanguageServiceClient.Speak這兩個方法來實現。LanguageServiceClient.GetLanguagesForSpeak方法可以取得所有能支援發音的語言,可以用來列表發音的語系。LanguageServiceClient.Speak則是能取得發音檔的位置,帶入要發音的字串與期望的發音語系等資訊就可以了。抓出來的發音檔位置是一串網址,可直接透過MediaPlayer的Com元件下去撥放。
string GetSpeakUri(LanguageServiceClient client, string text)
{
string[] langs = client.GetLanguagesForSpeak(APP_ID);
string lang = (cbTranslateTo.SelectedValue == null)? "en": cbTranslateTo.SelectedValue.ToString();
if (!langs.Contains(lang))
lang = "en";
return client.Speak(APP_ID, tbxSource.Text, lang, "audio/wav", string.Empty);
}
而在取得能支援翻譯的語系方面,可使用LanguageServiceClient.GetLanguagesForTranslate與LanguageServiceClient.GetLanguageNames,LanguageServiceClient.GetLanguagesForTranslate可取得語系的代碼,LanguageServiceClient.GetLanguageNames則是可取得語系的名稱。若只是要以特定語系顯示能支援的語系名稱,只要像下面這樣就可以了:
string lang = "en";
string[] langs = Client.GetLanguagesForTranslate(APP_ID);
string[] names = Client.GetLanguageNames(APP_ID, lang, langs);
這樣支援的語系名稱都會以英文的方式顯現,像是ja就會以Japan來顯示、en會以English。若是要以對應的語系來顯示支援的語系名稱,讓ja顯示日語、en顯示English,可以像下面這樣撰寫:
void UpdateTranslationLanguages()
{
string local = GetDetectedLanguage(tbxSource.Text);
string[] langs = Client.GetLanguagesForTranslate(APP_ID);
var langNames = (from lang in langs.AsParallel()
select new { Name = Client.GetLanguageNames(APP_ID, lang, new string[] { lang })[0], Value = lang }).ToList();
cbTranslateTo.DisplayMember = "Name";
cbTranslateTo.ValueMember = "Value";
cbTranslateTo.DataSource = langNames;
if (cbTranslateTo.Items.Count > 0)
cbTranslateTo.Text = Client.GetLanguageNames(APP_ID, local, new string[] { local }).FirstOrDefault();
}
最後要提的是最重要的翻譯功能,直接叫用LanguageServiceClient.Translate就可以了,帶入的參數不外乎就是Application ID、要翻譯的訊息、要翻譯的訊息是何語系、要翻譯的語系...等。
tbxTarget.Text = Client.Translate(APP_ID, tbxSource.Text, local, cbTranslateTo.SelectedValue.ToString(), "text/html", "general");
這邊筆者試做了個程式來展示API的功能,設計界面如下,期望該小程式能由使用者決定要翻譯的語系,能正常的翻譯到期望的語系,並具備發音的功能。
完整的範例程式如下(Application ID部分請自行補上):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
using AxWMPLib;
using TranslateAPIDemo.TranslatorService;
namespace TranslateAPIDemo
{
public partial class Form1 : Form
{
#region Const
private const string APP_ID = "";
#endregion
#region Var
private LanguageServiceClient _client;
#endregion
#region Property
public LanguageServiceClient Client
{
get
{
if (_client == null)
_client = new LanguageServiceClient();
return _client;
}
}
#endregion
public Form1()
{
InitializeComponent();
}
string GetDetectedLanguage(string text)
{
const string DEFAULT_DETECTED_LANG = "en";
if (String.IsNullOrEmpty(text))
return DEFAULT_DETECTED_LANG;
const string DETECT_API_URI_PATTERN = "http://api.microsofttranslator.com/V2/Http.svc/Detect?appId={0}&text={1}";
const string MATCH_PATTERN = "<[^<>]*>([^<>]*)<[^<>]*>";
WebRequest req = WebRequest.Create(String.Format(DETECT_API_URI_PATTERN, APP_ID, text));
WebResponse resp = req.GetResponse();
string local = DEFAULT_DETECTED_LANG;
using (StreamReader reader = new StreamReader(resp.GetResponseStream()))
{
local = reader.ReadToEnd();
local = Regex.Match(local, MATCH_PATTERN).Groups[1].Value;
}
return local;
}
string GetSpeakUri(LanguageServiceClient client, string text)
{
string[] langs = client.GetLanguagesForSpeak(APP_ID);
string lang = (cbTranslateTo.SelectedValue == null)? "en": cbTranslateTo.SelectedValue.ToString();
if (!langs.Contains(lang))
lang = "en";
return client.Speak(APP_ID, tbxSource.Text, lang, "audio/wav", string.Empty);
}
void UpdateTranslationLanguages()
{
string local = GetDetectedLanguage(tbxSource.Text);
string[] langs = Client.GetLanguagesForTranslate(APP_ID);
var langNames = (from lang in langs.AsParallel()
select new { Name = Client.GetLanguageNames(APP_ID, lang, new string[] { lang })[0], Value = lang }).ToList();
cbTranslateTo.DisplayMember = "Name";
cbTranslateTo.ValueMember = "Value";
cbTranslateTo.DataSource = langNames;
if (cbTranslateTo.Items.Count > 0)
cbTranslateTo.Text = Client.GetLanguageNames(APP_ID, local, new string[] { local }).FirstOrDefault();
}
private void button1_Click(object sender, EventArgs e)
{
string local = GetDetectedLanguage(tbxSource.Text);
string speakUri = GetSpeakUri(Client, tbxSource.Text);
if (speakUri.Length > 0)
{
axWindowsMediaPlayer1.URL = speakUri;
axWindowsMediaPlayer1.Ctlcontrols.play();
}
if (cbTranslateTo.SelectedValue != null)
tbxTarget.Text = Client.Translate(APP_ID, tbxSource.Text, local, cbTranslateTo.SelectedValue.ToString(), "text/html", "general");
}
private void Form1_Load(object sender, EventArgs e)
{
UpdateTranslationLanguages();
}
}
}