2023年1月12日木曜日

XLIFFファイル翻訳支援アプリの作成(3) - DeepLの呼び出し

 DeepLから翻訳APIの無料枠が提供されています。このサービスに登録して、DeepL REST APIを呼び出して文字列の翻訳を行う機能を追加します。


DeepL API Freeの登録


開発者向けの登録画面を開き、無料版のアカウントを登録します。もちろんPRO版のアカウントでも、これからの作業に違いはないでしょう。

2023年1月12日時点のスクリーンショットです。契約内容が変更されていることもあるため、必ずご自身で契約内容を確認しましょう。これ以降の手順は省略しますが、無料版でもアカウント登録にあたって、本人確認のためにクレジットカードの登録が要求されます


登録したアカウントにて、DeepLにログインします。

アカウントのページを開き、アカウント・タブのDeepL APIで使用する認証キーを確認し、クリップボードにコピーします。

この認証キーを、Oracle APEXからDeepL APIを呼び出す際のWeb資格証明として使用します。


DeepLでの作業は以上で完了です。


Web資格証明の作成


アプリケーション・ビルダーからワークスペース・ユーティリティを開きます。


ワークスペース・ユーティリティに含まれるWeb資格証明を呼び出します。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資格証明を確認します。



DeepLによる翻訳結果がJSON形式で返却されることが確認できます。


静的アプリケーション・ファイルの作成



DeepLによる翻訳を呼び出す処理は、ページ番号のページTranslateにインライン・ダイアログのリージョン(タイプ静的コンテンツテンプレートとしてInline Dialogを選択したリージョン)を作成して実装します。

翻訳対象の行を対話グリッドで選択し、インライン・ダイアログを開く処理と、インライン・ダイアログ上で翻訳した文字列を対話グリッドに戻しダイアログをクローズする処理をAPEXのAction(apex.actionインターフェース)として実装します。

JavaScriptのコードは静的アプリケーション・ファイルに記述します。

共有コンポーネント静的アプリケーション・ファイルを開きます。


ファイルを新規作成します。ファイルの作成をクリックします。


ファイル名translate-actions.jsとします。作成をクリックします。


ファイルが作成されます。ファイルの内容として、以下のJavaScriptのコードを記述します。


記述後に変更の保存をクリックします。


変更が保存されると、ファイル名で指定されているtranslate-actions.jsに変更された内容が反映されると同時にMinifyされたファイルtranslate-actions.min.jsも作成または更新されます。

参照として表示されている#APP_FILES#translate-actions#MIN#.jsをクリップボードにコピーします。この参照は、ページ・プロパティJavaScriptファイルURLに記載します。


静的アプリケーション・ファイルの一覧より、translate-actions.jstranslate-actions.min.jsが作成されていることが確認できます。


このようにJavaScriptのコードを静的アプリケーション・ファイルに記載すると、APEX 22.1から提供されているセッション・オーバーライドを活用できます。セッション・オーバーライドについては、こちらの記事で紹介しています。

APEXのアプリケーションにJavaScriptのコードを埋め込むと、ページ・デザイナ上でのコード変更は即座にアプリケーションに反映されます。その場合、複数の開発者が同じアプリケーションの開発を行なっている際に支障があります。ページをロックすることにより他の開発者による変更を禁止することはできますが、それでも生産性は下がります。

セッション・オーバーライドを使用すると置換文字列#APP_FILES#を、開発者が使用しているローカルPCのファイルを指定するように変更できるため、他の開発者に影響を与えることなくJavaScriptやCSSのコードを修正できます。


ページの準備



インライン・ダイアログの実装の前に、いくつか設定を行います。

ページ・デザイナにてページ番号のページ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つ、ボタン名をTRANSLATEAPPLYCANCELとして作成します。すべて動作アクション動的アクションで定義を選択します。

ボタンAPPLYCANCELは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呼び出しをデータベース・サーバーから行います。


送信するアイテムとしてコード内で参照しているP3_SOURCE_TEXTP3_SOURCE_LANGP3_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に含まれている翻訳済みのテキストを活用する方法を紹介します。

続く

XLIFFファイル翻訳支援アプリの作成(2) - 翻訳ページの作成

 翻訳作業に使用するページを完成させます。


APEXコレクション名の設定


翻訳元と翻訳済みの文字列は、APEXコレクションに保存した上で対話グリッドから操作します。APEXコレクション名をSQLやPL/SQLに直書きすることを避けるため、置換文字列を設定します。

アプリケーション定義を開き、置換文字列G_TRANSLATE_COLLECTIONに対して、置換値としてTRANSLATEを設定します。

変更の適用をクリックします。

翻訳に使用するAPEXコレクションの名前はTRANSLATEになります。


ページ・アイテムとボタンの配置


ページ・デザイナでページ番号のページTranslateを開きます。

このページで行う4つの作業を実行するボタンを作成します。ボタン名はそれぞれLOAD_FROM_SOURCESTORE_AS_RESULTLOAD_FROM_RESULTBATCH_TRANSLATEとします。ラベルボタン名から生成されたものを使用します。

作成したボタンを横一列に並べるため、LOAD_FROM_SOURCEを除くボタンのレイアウト新規行の開始OFFにします。


翻訳対象となっている表CWR_XLIFF_FILESの列のIDの値を保持するページ・アイテムを作成します。

ページ・アイテムの識別名前P3_IDタイプとして選択リストを選びます。ラベルXLIFF Nameとします。アプリケーションとしては列IDの値が保存されていれば十分ですが、ユーザーには分かりやすくIDに代えて列Nameの値を表示します。

LOVタイプSQL問合せSQL問合せとして以下を記述します。追加値の表示NULL値の表示は共にOFFです。

select name, id from cwr_xliff_files where id = :P3_ID

ユーザーが設定する値ではないため、読取り専用タイプとして常時を指定します。


XLIFFの属性であるsource_langとtarget_langを画面に表示するために使用する、ページ・アイテムを作成します。

source_langを表示するページ・アイテムは識別名前P3_SOURCE_LANGとします。タイプとして表示のみを選択します。ラベルSource Langとします。

設定ページの送信時に送信OFFにし、ページ・アイテムP3_IDの右隣に配置されるよう、レイアウト新規行の開始OFFにします。


target_langを表示するページ・アイテムP3_TARGET_LANGも同様に作成します。ラベルTarget Langです。


以上でボタンとページ・アイテムの配置は完了です。


対話グリッドの調整



対話グリッドで実施できる作業を、翻訳結果となる文字列の更新に限定します。

対話グリッドTranslateを選択し右ペインで属性を開きます。

編集実行可能な操作から行の追加行の削除チェックを外します。また、ツールバーコントロールにある保存ボタンチェックを外します


対話グリッドの列セレクタ(APEX$ROW_SELECTOR)と行アクション(APEX$ROW_ACTION)は不要なので、構成ビルド・オプションCommented Out(コメント・アウト)します。


APEXコレクションを一意に指定する列はSEQ_IDです。列SEQ_IDを選択し、ソース主キーONにします。


IDを更新することはないため、識別タイプ表示のみとし、ソース問合せのみONにします。


翻訳元となる文字列を保持する列SOURCE_TEXTも更新することはないため、タイプ表示のみに変更し、ソース問合せのみONにします。


以上で対話グリッドの調整は完了です。


対話モード・レポートからリンク



アップロードしたXLIFFファイルの一覧から翻訳作業のページを開くために、リンクを作成します。

ページ番号XLIFF Filesのページを開き、対話モード・レポートの列Nameを選択します。

識別タイプリンクに変更し、リンクの属性を更新します。


ターゲットをクリックし、リンク・ビルダー・ターゲットの画面を開きます。

ターゲットタイプとしてこのアプリケーションのページを選択し、ページ(ページTranslate)を指定します。

アイテムの設定として名前P3_ID#ID#を指定することで、選択したID値をページ・アイテムP3_IDに渡します。

以上でOKをクリックします。




プロセスの作成



対話グリッドに更新した翻訳済み文字列がAPEXコレクションに保存されるように、作成済みのプロセスTranslate - Save Interactive Grid Dataを更新します。

ページ・デザイナにてページ番号のページTranslateを開きます。

左ペインでプロセス・ビューを表示し、プロセスTranslate - Save Interactive Grid Dataを選択します。

設定ターゲット・タイプPL/SQL Codeに変更し、挿入/更新/削除するPL/SQLコードとして以下を記述します。この対話グリッドで許可されている操作は更新のみなので、更新に対応する処理のみ記述します。


失われた更新の防止OFF行のロックNoにします。APEXコレクションとして保持されているデータはAPEXセッションにアクセスが限定されているため、これらの保護は必要ありません。

サーバー側の条件としてボタン押下時STORE_AS_RESULTを指定します。


作成済みの4つのボタンの処理を行うプロセスを、それぞれ作成します。

最初にボタンが行う処理を記述したパッケージCWR_UTILを作成します。パッケージCWR_UTILのコードは以下になります。ボタン名がクリックされたときに、同名のプロシージャが呼び出されるようにします。


パッケージの作成には、SQLワークショップSQLスクリプトなどを使用できます。Autonomous Databaseであれば、この記事による実行も可能です。

プロセスを作成し、識別名前Load From Sourceとします。タイプとしてAPIの呼出しを選択します。

設定パッケージとしてCWR_UTILを選択し、プロシージャまたはファンクションとしてLOAD_FROM_SOURCEを選択します。サーバー側の条件ボタン押下時LOAD_FROM_SOURCEを選択し、このボタンが押された時に実行されるようにします。


パラメータのp_idp_source_langp_target_langには、(p_またはP3_を除いた名前が一致するため)デフォルトでページ・アイテムP3_IDP3_SOURCE_LANGP3_TARGET_LANGが設定されます。

パラメータp_collection_nameタイプAPIデフォルトになっているので(APIのデフォルトはTRANSLATEになっているため、実際はこのままでも動作します)、タイプアイテムに変更し、アイテムとして置換文字列として設定されているG_TRANSLATE_COLLECTIONを指定します。


同様の手順でプロセスStore As Resultを作成します。パラメータp_collection_nameも同じくアイテムとしてG_TRANSLATE_COLLECTIONを指定します。

プロセスStore As ResultはプロセスTranslate - Save Interactive Grid Dataより下に配置します。表CWR_XLIFF_FILESの列XLIFF_RESULTに翻訳済みのデータを保存する前に、対話グリッドの更新データがAPEXコレクションに保存されている必要があります。


プロセスLoad From Resultも同様に作成します。


最後にプロセスBatch Translateを作成します。


以上でプロセスの作成は完了です。


翻訳テスト



一括翻訳をテストするために以下のINSERT文を実行し、表CWR_MESSAGESにデータを用意します。

SQLワークショップSQLスクリプトなどを使用して実行します。


実行が正常に完了していると、Messagesのページより挿入された翻訳を確認することができます。


以上でテストの準備ができました。

最初の記事に添付されているworld-diner.xlfををダウンロードし、XLIFF Filesの画面でアップロードします。


XLIFFファイルをアップロードしたら、Nameをクリックして翻訳ページ(Translate)を開きます。


ボタンLoad From Sourceをクリックして、表CWR_XLIFF_FILESの列XLIFF_SOURCEとして保存されているXLIFFファイルの内容をAPEXコレクションにロードします。


Target Textをひとつひとつ手入力で更新することもでできますが、ここではボタンBatch Translateをクリックして、表CWR_MESSAGESの内容を使って一括翻訳します。


翻訳結果がAPEXコレクションに反映されます。ボタンStore As Resultをクリックし、表CWR_XLIFF_FILESの列XLIFF_RESULTにXLIFFファイルとして保存します。


XLIFF Filesの画面に戻るとXLIFF Resultとして、ファイルのダウンロードができるようになっています。これをクリックして翻訳済みのXLIFFファイルをダウンロードして内容を確認します。


ダウンロードされたファイルの名前はworld-diner_ja_en.xlfになります。ファイルを開いて内容が翻訳されていることを確認します。

以上で翻訳作業を行うページは完成です。

次の記事で、DeepLを使った翻訳を追加します。

続く

XLIFFファイル翻訳支援アプリの作成(1) - 準備

 Oracle APEXによるアプリケーション作成の利点として、多言語への対応が容易であることが挙げられます。以前にOracle APEXのアプリケーションの翻訳手順を紹介しているのですが、その記事を更新するにあたって、APEXが生成するXLIFFファイルの翻訳を支援するアプリケーションを作成してみました。

作成するアプリケーションは以下のように動作します。それぞれの文字列を翻訳するにあたって、DeepLによる翻訳APIを呼び出しています。また、あらかじめデータベースに翻訳結果が用意されていれば、一括で翻訳することも可能です。


テストのために作成したXLIFFファイルは以下になります。このファイルをアプリケーションにアップロードしています。

翻訳されたXLIFFファイルは以下になります。

最初に雛形となるAPEXアプリケーションの作成から始めます。


表の作成


クイックSQLの以下のモデルより、翻訳前と翻訳後のXLIFFファイルを保存する表CWR_XLIFF_FILESおよび、翻訳に使用する文字列を保存する表CWR_MESSAGESを作成します。

# prefix: cwr
xliff_files
    name vc255 /nn
    source_lang vc50
    target_lang vc50
    xliff_result file
    xliff_source file

messages
  name vc255
  message_language vc50
  message_text vc4000

SQLワークショップユーティリティよりクイックSQLを実行します。左ペインに上記のモデルを記述し、SQLの生成SQLスクリプトの保存レビューおよび実行を順次実行します。

いくつか確認の画面が開くので、それぞれ実行即時実行を実施します。アプリケーションの作成は行いません。

表CWR_XLIFF_FILESおよびCWR_MESSAGESが作成されます。



初期アプリケーションの作成


APEXアプリケーションを作成します。

今回作成するアプリケーションのボタンなどのラベルは、英語で記述することにします。アプリケーション作成ウィザードによって設定されるラベルは、アプリケーション・ビルダーの言語で生成されます。そのため、アプリケーション作成ウィザードを実行する間だけ、環境を英語に切り替えます。

アプリケーション・ビルダーの先頭ページを開き、言語をEnglishに切り替えます。


App BuilderCreateからNew Applicationを実行し、アプリケーション作成ウィザードを起動します。

アプリケーションのName(名前)はXLIFF Translateとします。デフォルトで作成されているページHomeは削除し、対話モード・レポートのページXLIFF Files、対話グリッドのページTranslate、同じく対話グリッドのページMessagesを追加します。

アプリケーション自体は日本語で動作させるため、SettingsLanguageとしてJapanese(ja)を選択します。

ページXLIFF Filesを追加するために、Add Page(ページの追加)をクリックしInteractive Report(対話モード・レポート)を選択します。レポートとフォームで構成される一般的な表の操作画面を、表CWR_XLIFF_FILESに対して作成します。

Page Name(ページ名)はXLIFF Filesとします。Table or View(表またはビュー)、Interactive Report(対話モード・レポート)を選択し、Table or View(表またはビュー)としてCWR_XLIFF_FILESを選択します。Include Form(フォームを含める)にチェックを入れます。

Advanced(詳細)を開き、Set as Home Page(ホームページとして設定)にチェックが入っていることを確認します。

Add Page(ページの追加)をクリックします。


ページTranslateは以下のSELECT文をソースとしてInteractive Grid(対話グリッド)のページとして作成します。翻訳元と翻訳済みの文字列は、APEXコレクションに保存して操作します。

Page NameTranslateSQL Query(SQL問合せ)とAllow Editing(編集を許可)を選択します。必ずしも必要な作業ではありませんが、Set Iconをクリックしてページのアイコンを地球儀(fa-globe)に変更しています。


CWR_MESSAGESを編集する対話グリッドのページを追加します。一般的な編集可能な対話グリッドのページになります。

Page NameMessagesTable or ViewAllow Editingを選択し、Table or ViewとしてCWR_MESSAGESを選択します。


以上の設定を実施し、Create Application(アプリケーションの作成)を実行します。

アプリケーションが作成された後は、開発環境を日本語に切り替えます。



BLOB列の調整


表CWR_XLIFF_FILESに含まれるBLOB列、XLIFF_SOURCEXLIFF_RESULTが適切に扱われるように属性を調整します。

ページ番号XLIFF Filesの対話モード・レポートの列XLIFF_RESULTBLOB属性として以下を設定します。

MIMEタイプ列 - XLIFF_RESULT_MIMETYPE
ファイル名列 - XLIFF_RESULT_FILENAME
最終更新列 - XLIFF_RESULT_LASTUPD
文字セット列 - XLIFF_RESULT_CHARSET


同様に列XLIFF_SOURCEBLOB属性も設定します。

MIMEタイプ列 - XLIFF_SOURCE_MIMETYPE
ファイル名列 - XLIFF_SOURCE_FILENAME
最終更新列 - XLIFF_SOURCE_LASTUPD
文字セット列 - XLIFF_SOURCE_CHARSET


変更を保存し、ページ番号のフォームのページCwr Xliff Filesを開きます。

翻訳元となるXLIFFファイルを保存するページ・アイテムP2_XLIFF_SOURCEを選択し、設定に以下を指定します。

MIMEタイプ列 - XLIFF_SOURCE_MIMETYPE
ファイル名列 - XLIFF_SOURCE_FILENAME
文字セット列 - XLIFF_SOURCE_CHARSET
BLOB最終更新列 - XLIFF_SOURCE_LASTUPD


ページ・アイテムP2_SOURCE_LANGP2_TARGET_LANGおよび列XLIFF_RESULTに関するページ・アイテムはプログラムによって生成され、ユーザーによる入力の対象ではないため、構成ビルド・オプションCommented Out(コメント・アウト)します。

アプリケーション作成ウィザードを英語で実行しているため、ビルド・オプションが英語のCommented Outになっています。アプリケーション作成ウィザードを日本語で実行していると、コメント・アウトと表示されます。


以上で、翻訳対象とするXLIFFファイルをデータベースにアップロードする部分が実装できました。

次の記事で、実際の翻訳作業を行う画面を実装します。

続く