📌
選択範囲の英語をDenoを使って、みんなの自動翻訳@TexTra®のWeb APIで翻訳してみる
みんなの自動翻訳@TexTra®のWeb API
みんなの自動翻訳@TexTra®は、国立研究開発法人情報通信研究機構(NICT)が開発した自動翻訳サイトです。Web APIは、OAuthでアクセス認可を受ける形態で実装されています。ユーザ登録するとWeb APIでアクセスするためのアクセスキーなどが取得できます。
DenoでWeb APIにて翻訳
Node.js版プログラムソースコードはは公式で公開されていますが、学習のためDeno版に書き換えています。
利用例としては、Linux デスクトップのターミナル上でNu Shellのhelp save
の表示結果のSave a string to foo.txt in the current directory
をマウスで選択しておきます。この状態でNu Shell上で下記コマンド実行します。まずxselにより選択部分が標準出力に出力され、その内容の有効部分を選択して、今回のWeb API実行プログラムのrequest_textra.ts
を動かします。request_textra.ts
は翻訳結果を標準出力に出力します。
❯ xsel -o | last 1 | $in.0 | deno run --allow-env --allow-net request_textra.ts
カレントディレクトリのfoo.jsonにレコードを保存する
ソースコード
Web API詳細で得られる、API Key
, API secret
およびユーザIDを環境変数に登録しておきます。Nu shellの場合,env.nuに登録しておきます。
let-env TEXTRA_API_KEY = "API Keyをここにペースト"
let-env TEXTRA_API_SECRET = "API secretをここにペースト"
let-env TEXTRA_LOGIN_NAME = "ユーザIDをここにペースト"
ソースコードは次のとおりです。とりあえず、動作しますが、何分初心者なんで参考までに。
// deno run --allow-env --allow-net
const env = Deno.env.toObject();
const decoder = new TextDecoder();
const url = "https://mt-auto-minhon-mlt.ucri.jgn-x.jp"; // 基底URL (https://xxx.jpまでを入力)
const key = env.TEXTRA_API_KEY; // API key
const secret = env.TEXTRA_API_SECRET; // API secret
const name = env.TEXTRA_LOGIN_NAME; // ログインID
const api_name = "mt"; // API名 (https://xxx.jp/api/mt/generalNT_ja_en/ の場合は、"mt")
const api_param = "generalNT_en_ja"; // API値 (https://xxx.jp/api/mt/generalNT_ja_en/ の場合は、"generalNT_ja_en")
let access_token = null;
/** fallbak text */
const input_text =
"Deno (/ˈdiːnoʊ/, pronounced dee-no) is a JavaScript, TypeScript, and WebAssembly runtime with secure defaults and a great developer experience.";
let input_text_stdin = '';
for await (const chunk of Deno.stdin.readable) {
const text = decoder.decode(chunk);
input_text_stdin += text;
}
function request_token_endpoint(): Promise<Response> {
// RFC 6749 (The OAuth 2.0 Authorization Framework)
// https://darutk.medium.com/diagrams-and-movies-of-all-the-oauth-2-0-flows-194f3c3ade85
// (1) Request To Token Endpoint
const form_token_endpoint = new FormData();
form_token_endpoint.append("grant_type", "client_credentials");
/** Set API Key */
form_token_endpoint.append("client_id", key);
/** Set API secret */
form_token_endpoint.append("client_secret", secret);
/** Set Access token url */
form_token_endpoint.append("urlAccessToken", url + "/oauth2/token.php");
return fetch(url + "/oauth2/token.php", {
method: "POST",
body: form_token_endpoint,
});
}
request_token_endpoint().then((response) => {
if ((response) && (response.body)) {
return response.body.getReader().read();
} else {
return Promise.reject(
new Error(`Rresponse data from token endpointer is nil.`),
);
}
}).then((body_data) => {
if (body_data) {
const r = decoder.decode((body_data).value);
access_token = JSON.parse(r).access_token;
// // (2) Call API
const form_api = new FormData();
form_api.append("access_token", access_token);
form_api.append("key", key);
form_api.append("api_name", api_name);
form_api.append("api_param", api_param);
form_api.append("name", name);
form_api.append("type", "json");
form_api.append("text", input_text_stdin.trim() || input_text);
return fetch(url + "/api/", {
method: "POST",
body: form_api,
});
} else {
return Promise.reject(new Error(`API response body data is empty.`));
}
}).then((response) => {
if ((response) && (response.body)) {
return response.body.getReader().read();
} else {
return Promise.reject(new Error(`API response body data is empty.`));
}
}).then((body_data) => {
if (body_data) {
const r = decoder.decode((body_data).value);
const api_result = JSON.parse(r).resultset.result.text;
console.log(api_result);
}
}).catch((e) => {
console.log("Error:", e);
});
Tips
なぜか、fetch()
で以下のようにheaders
をつけるとうまく動作しなかった。bodyプロパティにFormDataを使うと"Content-Type
がmultipart/form-data
になるでしょうかね?いろいろ調べたんですが、わかりませんでした。
const response = await fetch("http://localhost:8080", {
method: "POST",
headers: { "Content-Type": "multipart/form-data" },
body: form
});
Discussion