【Unity(C#)】DeepL Translatorの使い方

##はじめに
UnityからDeepL Translatorを使用する方法をメモします。

## DeepL Translator
DeepLの提供する翻訳WebAPIです。

下記リンクより登録に進みAPIキーを取得します。
【参考リンク】：[DeepL Pro](https://www.deepl.com/pro?cta=header-pro)

登録後、下記ダッシュボードの画面からAPIキーを取得可能です。
![DeepLAPIキー.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244071/1e7b8cc8-85a1-2425-6e2e-5422eddd8183.png)

料金は従量課金制ですが、[1月当り500,000文字までは無料](https://www.deepl.com/pro/change-plan?cta=header-prices/#developer)で使えるようです。([GoogleTranslation](https://qiita.com/OKsaiyowa/items/c3b6799c91b26317b4be#google-cloud-translation)と一緒でした)

##バージョン
念のため使ったライブラリ等のバージョンも書いときます。
>Unity 2019.4.8f1
UniTask.2.2.4
UniRx 7.1.0

##コード
Unityから使用するサンプルです。
GIFにおいては使用しているAPIは異なりますが、下記と同様に動作します。
【参考リンク】：[【Unity(C#)】Microsoft Translatorの使い方](https://qiita.com/drafts/c3b6799c91b26317b4be/edit)
![MSTranslatorSample.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/244071/a5c737b8-3a90-986b-6bcf-43d1db525976.gif)


```C#:適当なオブジェクトにアタッチ
using System;
using System.Linq;
using System.Threading;
using Cysharp.Threading.Tasks;
using UniRx;
using UnityEngine;
using UnityEngine.Networking;
using UnityEngine.UI;

/// <summary>
/// DeepLの最小構成サンプル
/// </summary>
public class DeepLTest : MonoBehaviour
{
    [SerializeField] private Dropdown fromLanguageDd;
    [SerializeField] private Dropdown toLanguageDd;
    [SerializeField] private Button translateButton;
    [SerializeField] private InputField inputField;
    [SerializeField] private Text translationText;

    private const string API_KEY = "APIキー";
    private const string ENDPOINT = "https://api-free.deepl.com/v2/translate?auth_key=";

    /// <summary>
    /// レスポンスを格納する構造体
    /// </summary>
    [Serializable]
    public struct TranslateData
    {
        public Translations[] translations;
        
        [Serializable]
        public struct Translations
        {
            public string detected_source_language;
            public string text;
        }
    }
    
    private void Start()
    {
        var token = this.GetCancellationTokenOnDestroy();

        //ドロップダウンメニュー作成
        var languages = Enum.GetNames(typeof(Language));
        fromLanguageDd.ClearOptions();
        fromLanguageDd.AddOptions(languages.ToList());
        toLanguageDd.ClearOptions();
        toLanguageDd.AddOptions(languages.ToList());
        fromLanguageDd.value = (int) fromLanguage;
        toLanguageDd.value = (int) toLanguage;
        
        //翻訳元言語
        fromLanguageDd.OnValueChangedAsObservable()
            .Subscribe(value => { fromLanguage = (Language) value; })
            .AddTo(this);

        //翻訳後言語
        toLanguageDd.OnValueChangedAsObservable()
            .Subscribe(value => { toLanguage = (Language) value; })
            .AddTo(this);
        
        //翻訳ボタン押下
        translateButton.OnClickAsObservable()
            .Subscribe(async _ =>
            {
                //結果が送られてくるまで待ってから表示
                var result = GetTranslation(fromLanguage, toLanguage, inputField.text, token);
                translationText.text = await result;
            })
            .AddTo(this);
    }

    /// <summary>
    /// 設定言語
    /// </summary>
    private enum Language
    {
        JA,
        EN
    }

    private Language fromLanguage = Language.EN;
    private Language toLanguage = Language.JA;

    /// <summary>
    /// 翻訳結果を返す
    /// </summary>
    /// <param name="from">翻訳前の言語設定</param>
    /// <param name="to">翻訳語の言語設定</param>
    /// <param name="speechText">翻訳したい文字列</param>
    /// <param name="ct">CancellationToken</param>
    /// <returns>翻訳結果</returns>
    private async UniTask<string> GetTranslation(Language from, Language to, string speechText, CancellationToken ct)
    {
        //POSTメソッドのリクエストを作成
        var requestInfo = ENDPOINT + API_KEY;
        requestInfo += $"&text={speechText}&source_lang={from}&target_lang={to}";
        var request = UnityWebRequest.Post(requestInfo, "Post");

        //結果受け取り
        var second = TimeSpan.FromSeconds(3);
        var result = await request.SendWebRequest().ToUniTask(cancellationToken: ct).Timeout(second);
        var json = result.downloadHandler.text;
        Debug.Log(json);
        var data = JsonUtility.FromJson<TranslateData>(json);
        return data.translations[0].text;
    }
}
```

リクエストパラーメーターとして渡す言語情報の文字列は下記に載っています。
【参考リンク】：[Translating text](https://www.deepl.com/docs-api/translating-text/request/)

##おわりに
いろいろな翻訳API使ってみての感想ですが、GoogleもMSも申し分なく精度が高いですが、DeepLはやっぱり一番精度が高いなと感じました。