それでは、翻訳アプリケーションを実装していきましょう。
Visual Studioを起動し、新規プロジェクトを作成します。C#のWPFアプリケーションを作成してみたいと思います。プロジェクト名はTranslatorTextAPIとしています。
続いて参照の追加をします。メニューバーの「プロジェクト」から「参照の追加(R)」をクリックします。
「フレームワーク」から「System.Runtime.Serialization」と「System.Web」にチェックを入れ、OKをクリックします。
画面のxamlは以下の通りです(※画面部分のソースコードの解説は本連載の趣旨から外れるので割愛します)。
<Window x:Class="TranslatorTextAPI.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:TranslatorTextAPI" mc:Ignorable="d" Title="Translator Text API" Height="500" Width="950"> <Grid> <StackPanel HorizontalAlignment="Center" Margin="10,10,10,10"> <StackPanel Orientation="Horizontal" HorizontalAlignment="Center"> <StackPanel> <TextBlock Text="FROM" FontSize="30" /> <ComboBox Name="cmbLanguageFrom" Width="400" Height="30" /> <TextBox Name="tboxTranslationFrom" Width="400" Height="200" TextWrapping="Wrap" /> </StackPanel> <Label Content=">>" Width="80" FontSize="40" VerticalAlignment="Center" HorizontalContentAlignment="Center"/> <StackPanel> <TextBlock Text="TO" FontSize="30" /> <ComboBox Name="cmbLanguageTo" Width="400" Height="30" /> <TextBox Name="tboxTranslationTo" Width="400" Height="200" TextWrapping="Wrap" /> </StackPanel> </StackPanel> <Button Name="btnTranslate" Content="翻 訳" Width="300" Height="50" Click="btnTranslate_Click" Margin="0,20,0,0" /> <TextBlock Name="tblkMessage" Width="800" Height="70" TextWrapping="Wrap" ScrollViewer.CanContentScroll="True" Margin="0,20,0,0" /> </StackPanel> </Grid> </Window>
「MainWindow.xaml.cs」で実際にプログラムから呼び出すところを作成します。
プログラムの流れとしては、以下のようになります。
では、まずアクセスキーを使用してTokenを取得する処理から見ていきましょう。
【1】アクセスキーを使用してTokenを取得する
Tokenの取得方法の詳細については下記URLに情報があります。
Tokenの取得には専用のエンドポイントが用意されています。リクエストメソッドには「POST」を使用します(11行目)。Azureの画面からコピーしたキーを「Ocp-Apim-Subscription-Key」としてヘッダーに追加しています(12行目)。
string GetAccessTokenForTranslation() { try { //取得したTranslator Text API の Key を入れてください string subscriptionKey = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"; WebRequest request = WebRequest.Create("https://api.cognitive.microsoft.com/sts/v1.0/issueToken"); //リクエスト設定 request.Method = "POST"; // メソッドはPOST request.Headers.Add("Ocp-Apim-Subscription-Key", subscriptionKey); request.ContentLength = 0; // リクエストを投げる WebResponse response = request.GetResponse(); Stream responseStream = response.GetResponseStream(); // レスポンスを受け取る StreamReader streamReader = new StreamReader(responseStream); // Tokenを取得した時間を取得 tokenRefreshedTime = DateTime.Now; // レスポンス(Token)を返す return streamReader.ReadToEnd(); } catch(WebException webException) { Stream responseStream = webException.Response.GetResponseStream(); StreamReader streamReader = new StreamReader(responseStream); tblkMessage.Text = streamReader.ReadToEnd(); return null; } catch (Exception exception) { tblkMessage.Text = exception.Message; return null; } }
【2】Tokenを使用して、Translator APIに使用できる言語コードのリストを取得する
続いて、Translator APIで使用できる言語の言語コードを取得します。
string[] GetLanguagesForTranslate(string token) { try { string requestURL = "http://api.microsofttranslator.com/v2/Http.svc/GetLanguagesForTranslate"; // リクエスト設定 WebRequest request = WebRequest.Create(requestURL); request.Method = "GET"; // メソッドはGET request.Headers.Add("Authorization", "Bearer " + token); // レスポンスを受け取る WebResponse webResponse = request.GetResponse(); Stream responseStream = webResponse.GetResponseStream(); // レスポンスのXMLを変換 DataContractSerializer dcs = new DataContractSerializer(typeof(string[])); return (string[])dcs.ReadObject(responseStream); } catch (WebException webException) { Stream responseStream = webException.Response.GetResponseStream(); StreamReader streamReader = new StreamReader(responseStream); tblkMessage.Text = streamReader.ReadToEnd(); return null; } catch (Exception exception) { tblkMessage.Text = exception.Message; return null; } }
Translator APIには使用できる言語コードを取得するAPIと、その言語名を取得するAPIがそれぞれ用意されています。言語コードは実際に翻訳を行うAPIを呼び出す際に使用します。ユーザーに分かりやすいように、言語を選択するコンボボックス内の表記に使用します。
言語コードを取得するAPIのリクエストメソッドは「GET」です(8行目)。リクエストヘッダーに先に取得しておいたTokenを追加してリクエストを投げると(9行目)、レスポンスとして言語コードの配列がXML形式で返ってきます(11〜13行目)。
【3】Tokenを使用して、【2】で取得した言語コードに対応する言語名のリストを取得する
続いて言語名を取得します。
string[] GetLanguageNames(string token, string[] languageCodeArray) { try { string requestURL = "http://api.microsofttranslator.com/v2/Http.svc/GetLanguageNames?locale=ja"; // リクエスト設定 WebRequest request = WebRequest.Create(requestURL); request.Method = "POST"; // メソッドはPOST request.ContentType = "text/xml"; request.Headers.Add("Authorization", "Bearer " + token); // 言語コードの配列をXML化してリクエストのストリームに書き込み DataContractSerializer dcs = new DataContractSerializer(typeof(string[])); Stream stream = request.GetRequestStream(); dcs.WriteObject(stream, languageCodeArray); // レスポンスを受け取る WebResponse webResponse = request.GetResponse(); Stream responseStream = webResponse.GetResponseStream(); // レスポンスの言語名称のXMLを変換 dcs = new DataContractSerializer(typeof(string[])); string[] languageNamesArray = (string[])dcs.ReadObject(responseStream); return languageNamesArray; } catch (WebException webException) { Stream responseStream = webException.Response.GetResponseStream(); StreamReader streamReader = new StreamReader(responseStream); tblkMessage.Text = streamReader.ReadToEnd(); return null; } catch (Exception exception) { tblkMessage.Text = exception.Message; return null; } }
取得方法は【2】の言語コードの取得と非常に似ています。異なる点としては、言語コードを取得するAPIのリクエストメソッドは「POST」になること(9行目)と、言語コードの配列を渡す必要があること(12〜15行目)です。リクエストヘッダーに先に取得しておいたTokenを追加して(11行目)リクエストを投げると、レスポンスとしてリクエストで渡した言語コードに対応する言語名の配列がXML形式で返ってきます(17〜19行目)。
【4】翻訳ボタンをクリックしたら、Tokenを使用して翻訳するテキストをAPIに渡し、翻訳結果を取得する
最後は、翻訳結果を取得する処理です。
string GetTranslatorResult(string token) { try { // 翻訳するテキスト string text = HttpUtility.UrlEncode(tboxTranslationFrom.Text); // 翻訳の言語 string fromLanguage = ((ComboBoxItem)cmbLanguageFrom.SelectedItem).Tag.ToString(); string toLanguage = ((ComboBoxItem)cmbLanguageTo.SelectedItem).Tag.ToString(); string requestURL = "http://api.microsofttranslator.com/v2/Http.svc/Translate"; requestURL += "?text=" + text + "&from=" + fromLanguage + "&to=" + toLanguage; requestURL += "&category=generalnn"; // リクエスト設定 WebRequest request = WebRequest.Create(requestURL); request.Method = "GET"; // メソッドはGET request.Headers["Authorization"] = "Bearer " + token; // レスポンスを受け取る WebResponse webResponse = request.GetResponse(); Stream responseStream = webResponse.GetResponseStream(); // レスポンスのXMLを変換 DataContractSerializer dcs = new DataContractSerializer(typeof(string)); return (string)dcs.ReadObject(responseStream); } catch (WebException webException) { Stream responseStream = webException.Response.GetResponseStream(); StreamReader streamReader = new StreamReader(responseStream); tblkMessage.Text = streamReader.ReadToEnd(); return null; } catch (Exception exception) { MessageBox.Show(exception.Message); return null; } }
APIのリクエストメソッドはGETになります。翻訳するテキストをURLエンコードしたものとFROMとTOの言語コードをURLに追加します。リクエストヘッダーに先に取得しておいたTokenを追加してリクエストを投げると、レスポンスとして翻訳結果のテキストがXML形式で返ってきます。
ここでポイントなのが、リクエストに「category=generalnn」を追加することです(13行目)。
マイクロソフトのTranslator APIは2016年11月にニューラルネットワークによる翻訳の提供を開始したという発表がありました。詳細は下記URLのブログをご参照ください。
API Referenceでは、この「category」というパラメーターについてあまり詳しい説明がありません。オプションのパラメーターでデフォルトは「general」だということが書いてありますが、実はこのデフォルトのままだとニューラルネットワークが使用されず、あまり翻訳精度が高くないようです。
上記のブログの最後に小さく書いてありますが、カテゴリーに「generalnn」を使用すると、ニューラルネットワークが使用できるようになり、各段に翻訳の精度が上がります。
前述の処理にコンストラクタや翻訳ボタンクリック時のイベントを含めると、最終的にはMainWindow.xaml.csは、こちらのようになります(※右クリックしてダウンロードできます)。
どうでしょうか。APIを呼び出すのはそれほど難しいことではないことがお分かりいただけたのではないでしょうか。
Copyright © ITmedia, Inc. All Rights Reserved.