DeepLから翻訳APIの無料枠が提供されています。このサービスに登録して、DeepL REST APIを呼び出して文字列の翻訳を行う機能を追加します。
DeepL API Freeの登録
開発者向けの登録画面を開き、無料版のアカウントを登録します。もちろんPRO版のアカウントでも、これからの作業に違いはないでしょう。
2023年1月12日時点のスクリーンショットです。契約内容が変更されていることもあるため、必ずご自身で契約内容を確認しましょう。これ以降の手順は省略しますが、無料版でもアカウント登録にあたって、本人確認のためにクレジットカードの登録が要求されます。
登録したアカウントにて、DeepLにログインします。
アカウントのページを開き、アカウント・タブのDeepL APIで使用する認証キーを確認し、クリップボードにコピーします。
この認証キーを、Oracle APEXからDeepL APIを呼び出す際のWeb資格証明として使用します。
DeepLでの作業は以上で完了です。
Web資格証明の作成
アプリケーション・ビルダーからワークスペース・ユーティリティを開きます。
作成済みのWeb資格証明が一覧されます。作成をクリックします。
DeepL APIを呼び出す際に使用するWeb資格証明を作成します。
名前はDeepL API Key、静的識別子はDEEPL_API_KEYとします。静的識別子はAPEXアプリケーションのコードに記載しているため、必ずこの値にします。
認証タイプにHTTPヘッダーを選択し、資格証明名にAuthorizationと記載します。DeepLのAPIはHTTPのAuthorizationヘッダーの値を使ってAPIリクエストの認証をしているようです。
資格証明シークレットとして、DeepL-Auth-Keyで始めて、その後にDeepLのアカウント・ページよりコピーした認証キーの値を続けて設定します。
DeepL-Auth-Key 認証キー
URLに対して有効にAPIのエントリポイントを記載します。このURLは無料版とPRO版では異なるはずです。
https://api-free.deepl.com/v2/translate
以上を設定して、作成をクリックします。
Web資格証明が作成されます。
Web資格証明はワークスペースに登録されるため、SQLコマンドからのAPI呼び出しでも使用できます。以下のコードを実行して、作成したWeb資格証明を確認します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
declare | |
l_request clob; | |
l_result clob; | |
begin | |
l_request := 'text=Hello&target_lang=JA'; | |
apex_web_service.clear_request_headers; | |
apex_web_service.set_request_headers('Content-Type','application/x-www-form-urlencoded',p_reset = false); | |
l_result := apex_web_service.make_rest_request( | |
p_url => 'https://api-free.deepl.com/v2/translate' | |
,p_http_method => 'POST' | |
,p_credential_static_id => 'DEEPL_API_KEY' | |
,p_body => l_request | |
); | |
dbms_output.put_line(l_result); | |
end; |
DeepLによる翻訳結果がJSON形式で返却されることが確認できます。
静的アプリケーション・ファイルの作成
DeepLによる翻訳を呼び出す処理は、ページ番号3のページTranslateにインライン・ダイアログのリージョン(タイプが静的コンテンツでテンプレートとしてInline Dialogを選択したリージョン)を作成して実装します。
翻訳対象の行を対話グリッドで選択し、インライン・ダイアログを開く処理と、インライン・ダイアログ上で翻訳した文字列を対話グリッドに戻しダイアログをクローズする処理をAPEXのAction(apex.actionインターフェース)として実装します。
JavaScriptのコードは静的アプリケーション・ファイルに記述します。
共有コンポーネントの静的アプリケーション・ファイルを開きます。
ファイル名はtranslate-actions.jsとします。作成をクリックします。
ファイルが作成されます。ファイルの内容として、以下のJavaScriptのコードを記述します。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
対話グリッドのリージョンの静的IDはIGTRANS、インライン・ダイアログの静的IDはTRANSLATEとする。 | |
*/ | |
const OPEN_TRANSLATE_DIALOG = { | |
name: "open-translate-dialog", | |
action: function( event, element, args ) { | |
let view = apex.region("IGTRANS").call("getCurrentView"), | |
model = view.model; | |
let record = model.getRecord(args.id); | |
apex.item(args.id_item).setValue(args.id); | |
apex.item(args.source_item).setValue(model.getValue(record,"SOURCE_TEXT")); | |
apex.item(args.target_item).setValue(model.getValue(record,"TARGET_TEXT")); | |
apex.theme.openRegion("TRANSLATE"); | |
} | |
}; | |
const CLOSE_TRANSLATE_DIALOG = { | |
name: "close-translate-dialog", | |
action: function( event, element, args ) { | |
let view = apex.region("IGTRANS").call("getCurrentView"), | |
model = view.model; | |
let record = model.getRecord(apex.item(args.id_item).getValue()); | |
model.setValue(record, "TARGET_TEXT", apex.item(args.target_item).getValue()); | |
apex.theme.closeRegion("TRANSLATE"); | |
} | |
}; |
記述後に変更の保存をクリックします。
変更が保存されると、ファイル名で指定されているtranslate-actions.jsに変更された内容が反映されると同時にMinifyされたファイルtranslate-actions.min.jsも作成または更新されます。
参照として表示されている#APP_FILES#translate-actions#MIN#.jsをクリップボードにコピーします。この参照は、ページ・プロパティのJavaScriptのファイルURLに記載します。
静的アプリケーション・ファイルの一覧より、translate-actions.js、translate-actions.min.jsが作成されていることが確認できます。
このようにJavaScriptのコードを静的アプリケーション・ファイルに記載すると、APEX 22.1から提供されているセッション・オーバーライドを活用できます。セッション・オーバーライドについては、こちらの記事で紹介しています。
APEXのアプリケーションにJavaScriptのコードを埋め込むと、ページ・デザイナ上でのコード変更は即座にアプリケーションに反映されます。その場合、複数の開発者が同じアプリケーションの開発を行なっている際に支障があります。ページをロックすることにより他の開発者による変更を禁止することはできますが、それでも生産性は下がります。
セッション・オーバーライドを使用すると置換文字列#APP_FILES#を、開発者が使用しているローカルPCのファイルを指定するように変更できるため、他の開発者に影響を与えることなくJavaScriptやCSSのコードを修正できます。
インライン・ダイアログの実装の前に、いくつか設定を行います。
ページ・デザイナにてページ番号3のページTranslateを開きます。
ページ・プロパティのJavaScriptのファイルURLとして、先ほど作成した静的アプリケーション・ファイルを指定します。
<span class="fa fa-edit" aria-hidden="true"></span>
data-action="#action$close-translate-dialog?id_item=P3_GID&target_item=P3_TARGET_TEXT"
ページの準備
ページ・デザイナにてページ番号3のページTranslateを開きます。
ページ・プロパティのJavaScriptのファイルURLとして、先ほど作成した静的アプリケーション・ファイルを指定します。
#APP_FILES#translate-actions#MIN#.js
続いて、ページ・ロード時に実行に、以下を記述します。静的アプリケーション・ファイルに記載したオブジェクトをAPEXのアクションとして登録します。
apex.actions.add([
OPEN_TRANSLATE_DIALOG
,CLOSE_TRANSLATE_DIALOG
]);
対話グリッドに静的IDとしてIGTRANSを設定します。JavaScriptのコード中で対話グリッドを参照する際に使用しています。
翻訳ダイアログの作成
DeepLを使った翻訳を行うダイアログを作成します。
新規にリージョンを作成します。
識別の名前はDeepL Translateとします。タイプは静的コンテンツです。外観のテンプレートとしてInline Dialogを選択します。
詳細の静的IDとしてTRANSLATEを割り当てます。JavaScriptのコード中でこの静的IDを使ってリージョンを指定しています。リージョン表示セレクタは使用していませんが、インライン・ダイアログのリージョンがリージョン表示セレクタに現れることはあり得ないため、あらかじめOFFにしておきます。
翻訳対象となっている行のIDを保持するページ・アイテムP3_GIDを、インライン・ダイアログのリージョンに作成します。このページ・アイテムには対話グリッドの行のID、つまりAPEXコレクションの列SEQ_IDの値が設定されます。
識別の名前はP3_GID、タイプは非表示とします。JavaScriptのコード中で値を設定するため、設定の保護された値はOFFにします。
翻訳元の文字列を保持するページ・アイテムP3_SOURCE_TEXTを作成します。
識別の名前はP3_SOURCE_TEXT、タイプとしてテキスト領域を選択します。ラベルはSource Textとします。
翻訳済みの文字列を保持するページ・アイテムP3_TARGET_TEXTを作成します。
識別の名前はP3_TARGET_TEXT、タイプとしてテキスト領域を選択します。ラベルはTarget Textとします。
ボタンを3つ、ボタン名をTRANSLATE、APPLY、CANCELとして作成します。すべて動作のアクションは動的アクションで定義を選択します。
ボタンAPPLYとCANCELは3つのボタンを横に並べるために、レイアウトの新規行の開始をOFFにします。
以上で翻訳を行うダイアログは作成できました。
翻訳処理の実装
対話グリッドの列SEQ_IDをクリックすることにより、選択した行を対象として翻訳ダイアログを開くようにします。
対話グリッドの列SEQ_IDを選択します。
識別のタイプをリンクに変更します。
リンクのターゲットをクリックし、リンク・ビルダー・ダーゲットを開きます。
ターゲットのタイプにURLを選択し、URLとして以下を記述します。
#action$open-translate-dialog?id=&SEQ_ID.&id_item=P3_GID&source_item=P3_SOURCE_TEXT&target_item=P3_TARGET_TEXT
APEXアクションとして定義したJavaScriptのコードopen-translate-dialogが実行されます。引数idとして列SEQ_IDの値が渡されます。
リンク・テキストとして以下を記述し、数値の表示から編集アイコンの表示に変更します。
<span class="fa fa-edit" aria-hidden="true"></span>
ボタンTRANSLATEをクリックしたときに実行される動的アクションを作成します。
作成した動的アクションの識別の名前はDeepL Translateとします。
ボタン上で作成した動的アクションのイベントはデフォルトで対象となるボタンのクリックが設定されます。設定の確認だけを行います。
ボタンTRANSLATEをクリックした時に実行されるTRUEアクションを定義します。
識別の名前はCall DeepL APIとし、アクションにサーバー側のコードを実行を選択します。
設定のPL/SQLコードとして以下を記述します。DeepLのAPI呼び出しをデータベース・サーバーから行います。
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
declare | |
l_request clob; | |
l_result clob; | |
l_json json_object_t; | |
l_array json_array_t; | |
l_trans json_object_t; | |
begin | |
/* DeepLに送信する翻訳リクエスト。 | |
* XLIFFに含まれるすべてのsource-langおよびtarget-langの指定が | |
* DeepLのsource_langとtarget_langとして有効かどうかは未確認。 | |
*/ | |
l_request := 'text=' || :P3_SOURCE_TEXT | |
|| '&target_lang=' || :P3_TARGET_LANG | |
|| '&source_lang=' || :P3_SOURCE_LANG; | |
/* DeepLのAPIを呼び出す。Web資格証明はあらかじめDEEPL_API_KEYとして作成しておく。 */ | |
apex_web_service.clear_request_headers; | |
apex_web_service.set_request_headers('Content-Type','application/x-www-form-urlencoded',p_reset = false); | |
l_result := apex_web_service.make_rest_request( | |
p_url => 'https://api-free.deepl.com/v2/translate' | |
,p_http_method => 'POST' | |
,p_credential_static_id => 'DEEPL_API_KEY' | |
,p_body => l_request | |
); | |
-- apex_debug.info('DeepL response = ' || l_result); | |
/* 戻り値のJSON文書より、翻訳済みのtextを取り出し、ページ・アイテムに設定する。 */ | |
l_json := new json_object_t(l_result); | |
l_array := l_json.get_array('translations'); | |
l_trans := treat(l_array.get(0) as json_object_t); | |
:P3_TARGET_TEXT := l_trans.get_string('text'); | |
end; |
送信するアイテムとしてコード内で参照しているP3_SOURCE_TEXT、P3_SOURCE_LANG、P3_TARGET_LANGを指定します。戻すアイテムは翻訳された文字列ほ保持するページ・アイテムP3_TARGET_TEXTを指定します。
デフォルトでOFFになっているはずですが、実行の初期化時に実行がOFFになっていることを確認します。
以上で、ボタンTRANSLATEをクリックすることにより、Source Textの文字列がDeepLで翻訳されて、その結果がTarget Textに設定されるようになりました。
ボタンAPPLYをクリックすることで、翻訳結果を対話グリッドに戻してダイアログを閉じるようにします。
ボタンAPPLYを選択し、詳細のカスタム属性としてdata-actionを指定します。
data-action="#action$close-translate-dialog?id_item=P3_GID&target_item=P3_TARGET_TEXT"
以上でAPEXアクションのclose-translate-diaglogが実行され、Target Textの値が対話グリッドに戻され、インライン・ダイアログが閉じられます。
最後にボタンCANCELに動的アクションを作成します。
識別の名前はClose Dialog as Cancelとします。
TRUEアクションの識別の名前はClose Dialog、アクションとしてリージョンを閉じるを選択します。影響を受ける要素として選択タイプにリージョン、リージョンとしてDeepL Translateを選択します。
ボタンCANCELをクリックすると、単にインライン・ダイアログのリージョンが閉じます。
DeepLによる翻訳機能を実装したのち、Load From Source、Store As Result、Load From Resultのボタンを押した時にORA-1403: データが見つかりません。が発生することがあります。
このエラーが発生したときは、プロセスのパラメータのp_idにアイテムP3_IDが設定されていることを確認してください。後で追加しているP3_GIDに置き換わっていることがありました。
XLIFFファイルの翻訳支援アプリの以上で完成です。
今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/xliff-translate.zip
次の記事では、Oracle APEXに含まれている翻訳済みのテキストを活用する方法を紹介します。
続く