Windows Translatorで "ArgumentOutOfRangeException: 'to' must be a valid languageというエラーが出るときの対処

  • 0
    Like
  • 0
    Comment
    More than 1 year has passed since last update.

    症状

    Microsoft Translator APIを使おうとしたら、タイトルどおりのエラーメッセージが出た。

    APIに渡すクエリは
    ?text=翻訳したいテキスト&from=ja&to=en
    のようになるのだが、何度ソースをみても&to=enは間違いなく入っている。

    ググると結構はまっている人がいるみたいだが、わかりやすい解決方法はみつからない。
    半日以上かけてなんとか解決したので記録しておく。

    原因:URLエンコードしすぎ

    いろいろ確認すると、

    ?text=hello&from=en&to=ja
    

    と手で入力したときにはエラーがでない。

    コードを見直してみると、クエリ全体をURLエンコードしていた。
    どうやらそれが原因らしく、上記のクエリのエンコードされた後の文字列を確認してみると、

    %3Ftext%3Dhello%26from%3Den%26to%3Dja
    

    みたいになっていた。

    '&'や'='などもエンコードされていて、そりゃエラーがでるよね…。

    URLエンコードは翻訳したいテキストだけすることにしたら解決しました。

    いちおう翻訳部分だけコードを載せておきます。

    アクセストークンは別に用意してください。

    TypeScript
    import qs = require('querystring');
    
    // 略
    
        translate(token, text, from_lang, to_lang, callback) {
            const options = "text=" + qs.escape(text) + // ここだけエンコード
                            "&from=" + from_lang +
                            "&to=" + to_lang +
                            "&oncomplete=callback";
    
            const request_options = {
                host: 'api.microsofttranslator.com',
                path: '/V2/Ajax.svc/Translate?' + options,
                method: 'GET',
                headers: {
                    "Authorization": 'Bearer ' + token
                }
            };
    
            const req = https.request(request_options, function(res) {
                var body = '';
                res.setEncoding('utf8');
    
                res.on('data', function(chunk) {
                    body += chunk;
                });
    
                res.on('end', function() {
                    // body の中身は "callback(translated_text)" という形になっているはず。
                    eval(body); // callback関数に翻訳されたテキストだけ渡す。
                });
    
            });
            req.on('error', function(e) {
                console.log(e.message);
            });
            req.end();
        }
    

    参考

    Microsoft Translator APIを使ってみる