Pythonでパワポスライドを自動翻訳する

python-pptxとGoogleAppsScriptを使うことでパワポを自動で翻訳する。
ここでは事前準備から入力された日本語スライドを英語に自動で翻訳し、出力するまでを述べる。

<blockquote class="twitter-tweet" data-lang="ja"><p lang="ja" dir="ltr">試しにデモムービーを作ってみた　Translate pptx by Google Apps Script and python-pptx <a href="https://t.co/gfJBCJNgCU">https://t.co/gfJBCJNgCU</a> <a href="https://twitter.com/YouTube?ref_src=twsrc%5Etfw">@YouTube</a>さんから</p>&mdash; ハイパー絵に描いた餅クリエイター440 (@code_440) <a href="https://twitter.com/code_440/status/1044354236656508928?ref_src=twsrc%5Etfw">2018年9月24日</a></blockquote>
<script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script>


## あらまし
先日、とある講演会に参加した際に英語のスライドの人や日本語のスライドの人、あるいは混ぜこぜになっている人など様々であった。
確かに一度作ったスライドを翻訳するのはなかなかの手間である。
そこで、Pythonでパワポを操作できるライブラリであるpython-pptxとGoogleの翻訳APIを使えるGoogleAppsScriptを組み合わせることで実現する。

環境はPython 3.5＠windows8.1
## GoogleAppsScriptについて
GoogleAppsScriptはグーグルの提供するGmailやスプレッドシートなどのサービスをスクリプトを通して操作できるサービスである。
今回はGoogleTranslateを使用するが、その方法は下記記事で述べられているので省略する。

[3 分で作る無料の翻訳 API with Google Apps Script](https://qiita.com/tanabee/items/c79c5c28ba0537112922)

この記事に則ってスクリプトを作成し、公開を行うと以下のようなURLが表示される。
`https://script.google.com/macros/s/[api_key]/exec`
※[api_key]は作成者によって異なる。

このURLに行いたい処理のパラメータを書き加えることで翻訳できる。
試しに「こんにちは」という日本語を英語に翻訳する場合は以下のようなURLにしてブラウザに入力すると翻訳された「Hello」が表示される。

`https://script.google.com/macros/s/[api_key]/exec?text=こんにちは&source=ja&target=en`

<img width="960" alt="GoogleAPIScript.png" src="https://qiita-image-store.s3.amazonaws.com/0/211021/67a20e71-e148-5c7e-10b2-67253b54672b.png">

シンプルな表示

## PythonからURLにアクセス
ここではPythonから先ほどのURLにアクセスする方法として以下のサイトを参考にした。

一つは先ほどのGoogleAppsScriptにJavaScriptでアクセスする例。
[日英翻訳スクリプト on コマンドライン](https://qiita.com/cranpun/items/7ed08f855359c9c28a33#_reference-87a5c5f45d997d242a76)

もう一つはGoogleAPIにPythonでアクセスする例。
[Python で、Google の Translation API を使う](https://qiita.com/ekzemplaro/items/8d42765b544a59517626)

上記の例を参考にpythonの`requests`ライブラリを用いる。

`pip install requests`

ここでは後で利用しやすくするため関数として定義している。

```python
def translate(str_in, source="ja", target="en"):
    url="https://script.google.com/macros/s/"
    url += api_key
    url += "/exec?text=" + str_in
    url += "&source=" + source
    url += "&target=" + target
    rr = requests.get(url)

    return rr.text
```
※api_keyは上記GoogleAppsScriptで取得したもの。

## パワポを読み込んで文字列にアクセスする例
python-pptxの使い方については[公式のドキュメント](https://python-pptx.readthedocs.io/en/latest/user/quickstart.html#extract-all-text-from-slides-in-presentation)やそれを簡単に説明させて頂いた拙著などを見ていただければと思う。
拙著：[Pythonでパワポの説明資料（報告書）を生成する](https://qiita.com/code_440/items/22e8539da465686496d3)

python-pptx公式のチュートリアルでスライド中の文字列をすべて抽出する例がある。

`pip install python-pptx`

以下の公式の例では指定したファイルのスライドを全て読み込み、その中からText形式のものを抽出している。

```python
from pptx import Presentation

prs = Presentation(path_to_presentation)

# text_runs will be populated with a list of strings,
# one for each text run in presentation
text_runs = []

for slide in prs.slides:
    for shape in slide.shapes:
        if not shape.has_text_frame:
            continue
        for paragraph in shape.text_frame.paragraphs:
            for run in paragraph.runs:
                text_runs.append(run.text)
```
引用：[python-pptx documentation Getting Started](https://python-pptx.readthedocs.io/en/latest/user/quickstart.html#extract-all-text-from-slides-in-presentation)

## スライド中文字列の抽出と翻訳
上記の例から、文字列を抜き出しつつ、先ほど作成したGoogleAppsScriptのURLにアクセスする関数を使って翻訳するという流れで翻訳を試みる。

以下が作成した例。

```python
import requests
from pptx import Presentation
from time import sleep

if __name__ == '__main__':
    path_to_presentation = "test.pptx"

    prs = Presentation(path_to_presentation)

    print("start")
    for ns, slide in enumerate(prs.slides):
        for nsh, shape in enumerate(slide.shapes):
            if not shape.has_text_frame:
                continue
            for np, paragraph in enumerate(shape.text_frame.paragraphs):
                for rs, run in enumerate(paragraph.runs):
                    str_in = run.text
                    str_out = translate(str_in)
                    prs.slides[ns].shapes[nsh].text_frame.paragraphs[np].runs[rs].text = str_out
                    sleep(1.5)
                    print(np)

    prs.save('test_trans.pptx')
    print("end")
```
※本文中のtranslateは先ほど作成したもの。
また、本例にはエラー処理等は入っていない。また、Googleへの過負荷を避けるためリクエスト毎にSleepで1秒以上のインターバルを開けている。

入力例としてロボット工学三原則や運動の法則の書かれたスライドを用意した。
<img width="960" alt="入力スライド.png" src="https://qiita-image-store.s3.amazonaws.com/0/211021/54f7c135-6486-2a97-1347-ab007fdcd75a.png">

出力の結果、無事に翻訳できている。
翻訳の正しさは議論しない。
<img width="960" alt="翻訳結果.png" src="https://qiita-image-store.s3.amazonaws.com/0/211021/6446620a-c443-1bf9-83a7-fd1bbe876db1.png">


注意点として、フォント、フォントサイズの異なる場合は別の文字列として扱われるので一文として翻訳したい場合はその辺りに注意が必要。

## おわりに
本記事ではパワポスライドを翻訳する方法について述べた。
この例と同様に、WordやExcelを操作するPythonライブラリもあることから、
ドキュメントの多言語化が容易になるものと考えられる。