Adobe PDFサービスとDeepLで実現しよう！ 効率的な英文ドキュメントの読み合わせ

# はじめに

英文ドキュメントに日々触れているという方は多いのではないでしょうか。それらの英文ドキュメントを自分で読むだけでなく、チーム内で読み合わせをする機会もかなりあるかと思います。母国語以外の言語で書かれた長文を読むのは結構ツラいこともあるので、何とか効率化できないか、と悩まれている方もいらっしゃるかもしれません。

この記事では、英文ドキュメントをチーム内で読み合わせをするようなシーンを想定し、元のドキュメントとその翻訳を結合したドキュメントを自動生成して読み合わせを効率化するためのアイデアについて解説しています。キーワードは「効率化」です。

# ユースケース：英文ドキュメントの読み合わせ

すでに述べたように、想定しているユースケースは英文ドキュメントの読み合わせです。チームのメンバーは英文ドキュメントを翻訳してからアップロードしてチーム内の他のメンバーに共有します (「アップロード先」についてはあとで説明します)。他のメンバーは、ドキュメントにコメントをつけたりそれを共有したりすることで読み合わせを進めます。以下の図は、この流れを説明したイメージです。

![英文ドキュメントの読み合わせ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2393004/65a405df-e0a8-dd2e-e915-9a7746bc273d.png "英文ドキュメントの読み合わせ")

## 課題

PDFなどのデジタルドキュメントを使えば複写や郵送といった物理的な制約がなく、メンバーはいつでもどこでもどんなデバイスからでも読み合わせができることは改めて説明する必要はないでしょう。しかしながら、効率化の観点からは、このユースケースは２つの課題を含んでいます。

### 翻訳における課題

最近のニュース記事 [^1] では、若い研究者の方が英語の論文を読むのにかかる時間は日本語の論文に比べて91%も長いという調査結果を伝えています。これは裏を返せば、英語の論文が自動的に高品質な日本語に翻訳されれば91%のかなりの部分を短縮できる余地があるとも言えます。元の論文と翻訳がセットになっていればドキュメントとして扱いやすく、読む作業はさらに効率化できるはずです。そしてもちろん、これは研究者が英語の論文を読む場合だけでなく、私たちが英語のドキュメントを読むときにも当てはまるでしょう。

[^1]:「英語で科学研究、つらい  論文に時間、国際学会を敬遠」 https://www.47news.jp/9605143.html

### コメントの付与と共有における課題

ドキュメントにコメントをつけてそれを共有することで、注目すべき箇所や要点、意見などを他のメンバーに伝えることが容易になります。ただし、コメントが共有されるたびにドキュメントをダウンロードして開いたり、コメントをつけたドキュメントをアップロードしたりする操作が要求されると、読み合わせが中断されて効率が落ちてしまいます。こうした操作をしなくても、ドキュメントにつけたコメントが他のメンバーから確認できるようにすることが非常に重要です。

次のセクションでは、効率化におけるこれらの課題を解決するアイデアとして、簡単に実現できるソリューションの一例を紹介します。

# ソリューションの概要

## ソリューションのイメージ

ソリューションのイメージは下図のようになります。

![ソリューションイメージ](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2393004/5a6c7b70-1e45-842d-728b-140cf636c47a.png "ソリューションイメージ")

メンバーはPCだけでなく、スマホやタブレットなど様々なデバイスから利用することを想定しています。ワークフローは次のようになります。ドキュメントの形式はPDFとします。

1. メンバーが英文のドキュメントをアップロードする
2. アップロードされたドキュメントは自動的に翻訳され、カバーページおよび元のドキュメントと結合されて、チーム内で共有される
3. メンバーは共有されたドキュメントを閲覧したりコメントしたりして読み合わせを進める

カバーページの内容は、ドキュメントをアップロードしたユーザ名、アップロード日時、コメントとします。

## ソリューションの構成要素

今回はこのようなソリューションを、以下を使用して構築します。

- Adobe Acrobat (Adobe PDFサービス)
- DeepL
- Microsoft Teams
- Microsoft Power Automate

Teamsは前のセクションで触れた「アップロード先」になります。メンバーはTeamsの既定のチームの既定のチャネルにメッセージを投稿することで読み合わせを開始します。読み合わせの対象となる英文ドキュメントは投稿メッセージに添付することとします。上記のステップ 2. はPower Automateのフローを作って自動化することとし、そのために以下のPower Automateコネクタを使います。具体的には、Power Automateのフローが、カバーページ、元のドキュメント、翻訳結果を結合したPDFを添付したメッセージをTeamsの既定のチャネルに自動的に投稿するようにします。

- [Adobe PDFサービス](https://powerautomate.microsoft.com/ja-jp/connectors/details/shared_adobepdftools/adobe-pdf-%E3%82%B5%E3%83%BC%E3%83%93%E3%82%B9/ "Adobe PDFサービス")
- [DeepL](https://powerautomate.microsoft.com/ja-jp/connectors/details/shared_deepl/deepl/ "DeepL")

### Adobe PDFサービス

Adobe PDFサービスは、これまでAcrobatデスクトップアプリなどに実装されていた機能をクラウドサービスとして利用できるようにした製品です。OfficeファイルのPDF変換、PDFの結合、圧縮、パスワード保護、PDFからのコンテンツの抽出など処理が可能です。

今回は、Adobe PDFサービスコネクタに実装されている次の2つのアクションを使用します。

<dl>
<dt>Wordテンプレートからドキュメントを生成する</dt>
<dd>
カバーページを作成するために使用します。このアクションは、事前に作成しておいたWordのテンプレートファイル (.docx) に記述されているタグを、指定したデータで置き換えた内容でPDFを作成します。カバーページには、メッセージの投稿日時、投稿したメンバーの名前、メッセージの本文を含めるようにします。
</dd>
<dt>PDFをマージ</dt>
<dd>
カバーページ、元の英文ドキュメント、翻訳したドキュメントをひとつのPDFに結合します。
</dd>
</dl>

アクションの詳しい説明は、[デベロッパーサイト](https://developer.adobe.com/document-services/docs/overview/pdf-services-api/) をご覧ください。

### DeepL

DeepLコネクタを使えば、DeepLの高品質な翻訳をPower Automateから利用できます。

今回は次の２つのアクションを使用します。

<dl>
<dt>ドキュメントのアップロードと翻訳</dt>
<dd>
ドキュメントをアップロードして、日本語に翻訳します。
</dd>
<dt>翻訳されたドキュメントのダウンロード</dt>
<dd>
翻訳が完了したら、翻訳結果のドキュメントをダウンロードします。
</dd>
</dl>

アクションの詳しい説明は、[DeepL APIのページ](https://www.deepl.com/pro-api?cta=header-pro-api) をご確認ください。

# 実際に作ってみよう

ここからはソリューションの中核、すなわち、Teamsにアップロードされたドキュメントを翻訳してカバーページおよび元のドキュメントと結合してメンバーに共有する部分を、Power Automateのフローで実現する例を紹介します。

今回は、Teamsの「Translation Demo」チームを使うこととし、メンバーが英文のPDFを添付してメッセージを投稿する先のチャネルを「Translation」、カバーページと翻訳結果が結合された結果が返ってくる (Power Automateによってメッセージが自動投稿される) チャネルを「General」とします。

## 事前準備

Adobe PDFサービスとDeepLを使うにはそれぞれのアカウントが必要です。まだサインアップしていない場合は、以下の手順に従ってサインアップしてください。

### Adobe PDFサービス

以下のWebページでAdobe PDFサービスのサインアップ手順やPower Automateコネクタの設定手順を説明しています。Adobe PDFサービスには、無償プラン (Free Tier) が用意されています。

- [Microsoft Power Automate向けAdobe PDFサービスコネクタ](https://helpx.adobe.com/jp/document-cloud/help/pdf-connector-for-microsoft-power-automate.html)
- [Adobe PDF Services](https://learn.microsoft.com/ja-jp/connectors/adobepdftools/) (コネクタのリファレンス)

### DeepL

以下のWebページでDeepL APIのサインアップ手順やPower Automateコネクタの設定手順を説明しています。DeepL APIでは、無償プラン (DeepL API Free) が提供されています。

- [DeepL API](https://www.deepl.com/pro-api?cta=header-pro-api "DeepL API")
- [DeepL (プレビュー)](https://learn.microsoft.com/ja-jp/connectors/deepl/) (コネクタのリファレンス)

## Power Automateのフローの作成

それでは、実際にPower Automateのフローを作成していきましょう。想定するワークフローは以下のようになっています (再掲)。

> 1. メンバーが英文のドキュメントをアップロードする
> 2. アップロードされたドキュメントは自動的に翻訳され、カバーページおよび元のドキュメントと結合されて、チーム内で共有される
> 3. メンバーは共有されたドキュメントを閲覧したりコメントしたりして読み合わせを進める

ドキュメントのアップロードはTeamsに投稿するメッセージに添付することで行い、これが読み合わせの開始になるため、フローはTeamsへの投稿をトリガーとして実行される必要があります。つまりこのフローは、自動化したクラウドフローとして作成します。

今回は簡単のため、メッセージにはPDFファイルをひとつだけ添付するものとします。

:::note info
以下の解説では、フローのステップの名前とコネクタのアクション名をそれぞれ「ステップ」「アクション」と呼んで明確に使い分けていますが、ステップの名前がコネクタのアクション名と同一の場合は、アクション名を明記しない場合があります。
:::

フローの概要は次のようになります。

![flow-overall](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2393004/fb96a55a-07bf-e425-9168-855a04ac9a11.png "フローの概要")

フローの各ステップの詳細について見ていきましょう。

### 新しいフローを作成する

まず「自動化したクラウドフロー」を作成します。フロー名は何でも構いませんが、例えば「TeamsのチャネルにPDFが投稿されたら翻訳する」などとしておきます。フロー全体は長いので、以下では、ステップ毎に解説するようにしています。それぞれを順に追加していくと全体のフローが完成するようになっています。

### 新しいメッセージの詳細と添付ファイルを取得

Teamsに新しいメッセージが投稿されるとそれをトリガーとしてフローを実行するために、最初のステップはMicrosoft Teamsコネクタの「チャネルに新しいメッセージが追加されたとき」というトリガーを使います。チーム名は「Translation Demo」、チャネル名は「Translation」としていますが、これらは適宜変更してください。

次のステップには、同じくMicrosoft Teamsコネクタの「メッセージ詳細を取得する」アクションを追加します。メッセージIDには、トリガーの出力の「メッセージID」を指定します。

![flow-1](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2393004/d7b7114f-191b-59c5-5059-0b3f4c523869.png "新しいメッセージの詳細と添付ファイルを取得")

「添付ファイルリストを設定」ステップは、組み込みの「変数」コネクタの「変数を初期化する」アクションです。変数 `attachments` の値に次の式をセットします。

```
body('メッセージ詳細を取得する')?['attachments']
```

これは「メッセージ詳細を取得する」ステップの出力に含まれる、添付ファイルの情報の配列 (`attachments`) です。以下のような内容になっています。

```json
{
    ...
    "body": {
        ...
        "attachments": [
            {
                "id": "69c0c3ae-b54d-374d-8464-17ff1a4f9f06",
                "contentType": "reference",
                "contentUrl": "https://example.sharepoint.com/sites/MyTeam/Shared Documents/Translation/whitepaper.pdf",
                "name": "whitepaper.pdf",
                ...
            }
        ],
        ...
    },
    ...
}
```

続いて、添付ファイルについてチェックします。今回は、メッセージにはPDFをひとつだけ添付できるという仕様のため、この条件に該当しているかどうかを判定しています。判定には、組み込みコネクタの「条件」アクションを使います。

![check-attachments](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2393004/d66ff96b-3e52-49ae-2d5c-0967b1439417.png "添付ファイルのチェック")

「添付ファイルをチェック」ステップでは、添付ファイルがひとつだけ、かつファイル名の拡張子が「.pdf」かどうかをチェックします。添付ファイルの数は次のようにして確認できます。

```添付ファイルの個数を調べる
length(variables('attachments'))
```

添付ファイルがひとつだけならば、そのファイル名を確認します。ファイル名が「.pdf」で終わっていればPDFであると判断します。

```添付ファイルの名前を調べる
variables('attachments')[0]?['name']
```

もしもこれらの条件の両方を満たさない場合は、フローを終了します (「添付ファイルが1つでない」と「添付ファイルがPDFでない」)。

:::note info
添付ファイルが2個以上の場合、それらを結合してから全体を翻訳したり、個別に翻訳したりすることが考えられます。興味がある方はフローを拡張してこうした処理を追加してみてください。
:::

### メッセージ詳細からカバーページを生成

カバーページは、Adobe PDFサービスを利用して、Wordファイル (テンプレート) 中のタグを指定したデータで置き換えて作成します。タグとは、`{{date}}` のような二重の中括弧で囲まれたワードです。

今回は以下のようなシンプルなテンプレートを作成しました。3つのタグ `{{date}}`、`{{user}}`、`{{message}}` を使用しており、それぞれ、メッセージの投稿日時、投稿者の名前、メッセージ本文に対応しています。

テンプレートは、Translationチャネルの「ファイル」タブを開いて「template」サブフォルダを作り、その中に「cover.docx」という名前で保存しておきます。各チームにはそれぞれ対応するSharePointサイトがあるので、このファイルはパス「/Shared Documents/Translation/template/cover.docx」でアクセスできます。

![cover](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2393004/6c24a8ca-0a72-ee6a-16b6-e628ff12a1e5.png "カバーページのテンプレート")

カバーページを作成するには、SharePointコネクタの「パスによるファイルコンテンツの取得」アクション (ステップの名前は「カバーページのテンプレートのコンテンツを取得」としています) と、Adobe PDFサービスの「Wordテンプレートからドキュメントを生成する」アクションを使います。

ここで、テンプレートのタグ `{{date}}`、`{{user}}`、`{{message}}` と、「メッセージ詳細を取得する」ステップの出力である、投稿日時 (CreatedDateTime)、投稿者の名前 (From User Display Name)、メッセージ本体 (Body PlainTextContent) をマージします。これによりメッセージの情報を含んだカバーページが作成できます。

![flow-2](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2393004/cceecf03-f5c9-389a-d190-b4b1ab9be8cb.png "カバーページの生成")

### 添付ファイルを翻訳

さて、いよいよ添付ファイルの翻訳です。添付ファイル名は後でも参照するので、変数にセットしておきます。変数名は `infile` とし、値は次のようにします。

```添付ファイル名
variables('attachments')[0]?['name']
```

添付ファイルのコンテンツを取得するには、SharePointコネクタの「パスによるファイルコンテンツの取得」アクション (ステップの名前は「添付ファイルのコンテンツを取得」としています) を使います。「Translation Demo」チームに対応しているサイトのアドレスと、添付ファイルのパスを指定します。

```添付ファイルのパス
/Shared Documents/Translation/@{variables('infile')}
```

![flow-3](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2393004/b337dc2b-f3f3-c59e-01e2-db1f66257cd6.png "添付ファイルの取得")

翻訳にはDeepLコネクタを使います。

「Upload and Translate a Document」ステップでは、翻訳先の言語 (Target Language) に「JA」、ファイルのコンテンツ (File) とファイル名 (File (file name)) にそれぞれ、添付ファイルのコンテンツと添付ファイル名をセットします。具体的には、次の式になります。

```ファイルコンテンツ
@body('添付ファイルのコンテンツを取得')
```

```添付ファイル名
@variables('infile')
```

出力の `document_id` と `document_key` を「Download Translated Document」ステップに渡せば、翻訳結果をダウンロードできます。

![flow-4](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2393004/9435f1a7-c87c-5bc5-e923-4cb023564672.png "DeepLによる翻訳")

:::note info
「Upload and Translate a Document」アクションでは翻訳元の言語 (Source Language) を指定できますが、ここでは省略しています。DeepLが自動的に翻訳元の言語を検出してくれるので、このままでも英語以外のドキュメントに対応しています。
:::

### カバーページ、添付ファイル、翻訳結果を結合

これで、カバーページ、添付ファイル、翻訳結果がすべて揃ったので、これらをひとつのPDFに結合します。

![flow-5](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2393004/f77c01a6-2305-099d-3c57-477e72dbade4.png "カバーページ、添付ファイル、翻訳結果の結合")

「出力ファイル名を設定」ステップで、結合したPDFのファイル名を変数 `outfile` にセットします。添付ファイル名の前に「T_」というプレフィックスをつけることにしましょう。値は次のように指定します。

```出力ファイル名の生成
concat('T_',variables('infile'))
```

PDFの結合はAdobe PDFサービスコネクタの「PDFのマージ」アクションを使います。マージされたPDFファイル名は、変数 `outfile` を参照します。

```マージされたPDFファイル名
@variables('outfile')
```

ファイルコンテンツには次の3つをセットします。それぞれ、カバーページ、英文ドキュメント、翻訳したドキュメントに対応しています。

```「Wordテンプレートからドキュメントを生成する」の出力
@outputs('Wordテンプレートからドキュメントを生成する')?['body/fileContent']
```

```「添付ファイルのコンテンツを取得」の出力
@body('添付ファイルのコンテンツを取得')
```

```「Download Translated Document」の出力
@body('Download_Translated_Document')
```

結合したPDFは、SharePointコネクタの「ファイルの作成」アクション (ステップの名前は「出力ファイルの作成」としています) を用いて「/Shared Documents/General/」配下に保存し、Teamsでは「ファイル」タブから参照できるようにしておきます (Translation DemoチームのGeneralチャネル)。このPDFはまた、次で説明する、処理完了後にTeamsに投稿するメッセージに添付します。

### 結合したファイルを投稿

Microsoft Teamsコネクタには添付ファイルつきのメッセージを投稿するアクションがありません。このため、Microsoft Graph APIを使ってメッセージにファイルを添付して投稿します。メッセージの投稿に必要なのは次の7つになります。

- 添付ファイルのURL
- 添付ファイルの名前
- 添付ファイルのETag
- チームID
- チャネルID
- メッセージのタイトル
- メッセージの本文

まず、SharePointコネクタの「ファイルのプロパティの取得」アクション (ステップの名前は「出力ファイルのプロパティの取得」としています) で、結合したPDFへのリンクとファイル名を取得しておきます。

続いて、結合したPDFのETagを取得します。ETagは「出力ファイルの作成」ステップの出力に含まれていますが、添付ファイルを指定するのに必要なのは「\"{」と「},2\"」を取り除いた部分のみです。これは、例えばslice関数を使って取得できます。この値を変数 `etag` にセットしておきます。

```ファイルのETagの例
...
"body": {
    ...
    "ETag": "\"{69c0c3ae-b54d-374d-8464-17ff1a4f9f06},2\"",
    ...
}
...
```

```ETagの取得
slice(body('出力ファイルの作成')?['ETag'],2,indexOf(body('出力ファイルの作成')?['ETag'],'}'))
```

![flow-6](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2393004/e87f38e3-5a2b-bc07-d8d9-9bdaf2692e8e.png "ETagの取得")

メッセージは「Translation Demo」チームの「General」チャネルに投稿します。チームIDは「メッセージ詳細を取得する」ステップの出力に含まれています。チャネルIDは「Translation Demo」チームのチャネル一覧の中から特定します。具体的には、Microsoft Teamsコネクタの「チャネルの一覧表示」アクションでチームを指定してチャネル一覧を取得し、組み込みコネクタの「データ操作」の「アレイのフィルター処理」アクション (ステップの名前は「Generalチャネルを取得」としている) でGeneralチャネルの情報のみを取得します。

```差出人
output('チャネルの一覧表示')?['body/value']
```

```詳細設定モードでの条件指定
@equals(item()?['displayName'],'General')
```

結果は変数 `channelId` にセットしておきます。

```
body('Generalチャネルを取得')[0]?['id']
```

![flow-7](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2393004/8c5b117f-0048-ba16-d6df-5fc702c27f48.png "チャネルIDの取得")

これでようやくメッセージを投稿する準備が整いました。Microsoft Graph APIを、「HTTP with Azure AD」コネクタの「HTTP要求を呼び出します」アクションを使って呼び出します。以下のように設定します。

| 名前 | 値 |
| :-: | :-- |
| 方法 | `POST` |
| 要求のURL | (下記参照) |
| ヘッダー | `"Content-Type": "application/json"` |
| 要求の本文 | (下記参照) |

```要求のURL
https://graph.microsoft.com/v1.0/teams/@{outputs('メッセージ詳細を取得する')?['body/teamId']}/channels/@{variables('channelId')}/messages
```

```要求の本文
{
    "subject": "@{outputs('メッセージ詳細を取得する')?['body/subject']}",
    "body": {
        "contentType": "html",
        "content": "<p>@{outputs('メッセージ詳細を取得する')?['body/body/plainTextContent']}<br>
                    <attachment id=\"@{variables('etag')}\" /></p>"
    },
    "attachments": [
        {
            "id": "@{variables('etag')}",
            "contentType": "reference",
            "contentUrl": "@{outputs('出力ファイルのプロパティの取得')?['body/{Link}']}",
            "name": "@{outputs('出力ファイルのプロパティの取得')?['body/{FilenameWithExtension}']}"
        }
    ],
    "mentions": [],
    "reactions": []
}
```

![flow-8](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2393004/8a4b7218-2bbd-2d7c-bb01-22d204adfab9.png "メッセージの投稿")

おめでとうございます！　これでフローが完成しました。

# 動作イメージ

フローの動作を確認するために、「アップロード先」である「Translation Demo」チームの「Translation」チャネルにメッセージを投稿してみましょう。

下図は、メールに添付された英文のPDFをiPhoneのAcrobatアプリで開いて、Teamsに投稿するときの画面イメージです。PDFのファイル名は「white_paper.pdf」で、Acrobat上で注釈をつけています。

![screen-1](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2393004/27e4cd1d-9bee-c849-ede2-672a44e319c9.png "iPhoneからTeamsに投稿する")

カバーページと翻訳結果が結合されたPDFをTeams上で開いた画面イメージです。コメントをつけると、チームのメンバーに共有されるため、読み合わせを効率的に進めることができます。

![screen-2](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2393004/1e6b0372-6795-b8ef-a5a3-385f1ca11434.png "Teamsで出力ファイルを開く")

![screen-3](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2393004/1b89079e-c0c9-4998-f7b3-0a8be5c985df.png "Teams上で読み合わせ")

# まとめ

この記事では、英文ドキュメントをチーム内で読み合わせをする作業を効率化するために、Adobe Acrobat (PDFサービス)、DeepL、Microsoft Teams、Microsoft Power Automateを組み合わせて使う方法を提案しました。特に、PDF形式の英文ドキュメントを自動で翻訳して、カバーページと元のドキュメントと結合するためのPower Automateのフローの作り方について詳細に解説しました。

## 謝辞

本記事を執筆するにあたり、越後屋ブログ店さまの下記の記事を参考にさせていただきました。

[【Power Automate】複数添付ファイルをTeamsにメンション投稿](https://echigoya-blog.net/powerautomate-teams-attachment/)