google colab で googletrans

参考にさせていただいた記事はこちら。参考のコードも、ほとんどそのままです。
[\<Pythonでgoogletransを使って翻訳\>](https://qiita.com/optimisuke/items/e44e66c2646e763d1f7b)

### [Googletrans: Free and Unlimited Google translate API for Python](https://py-googletrans.readthedocs.io/en/latest/)

#### google colab で python のパッケージ googletrans をインストールして、英語txtから英語と日本語txt（その他の場合も）に分かちする。

[字幕ファイル（.srtや .sbv）](https://support.google.com/youtube/answer/2734698?hl=ja#zippy=%2C%E5%9F%BA%E6%9C%AC%E7%9A%84%E3%81%AA%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%BD%A2%E5%BC%8F%2C%E9%AB%98%E5%BA%A6%E3%81%AA%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E5%BD%A2%E5%BC%8F)などを google translate にアップロードして翻訳されたものを見ると、タイムコード部分やカウンタインデックスまでランダムに漢字になっていたり、コロン（:）が全角になっていたりします。
そういった部分は翻訳エスケープして、テクスト翻訳後本文に戻すという処理をする必要があります。言語によっては翻訳されて変になってしまうところが違います。例えば、フランス語にすると数字の前にスペースが置かれたりします。

APIを使って、送って値が戻ってくるという手続きで翻訳機能が使えたら、その文字置き換え処理はこちら側でプログラム可能なので、テキスト処理プログラムとかやったことなくても、聞いたことある正規表現で、それはなんとかなりそうですから、どうやんのかなぁと思っておりました。
腰が重かったんですが、なんとかなりそうなので、同様に今現在、気が重たい人に、「ちょっとこれでいけそうだよ、わかんないけどさ」、と右手を出す感じで、ここにメモを残します。

#### google colab で googletrans を実行すると、テキストをアップロードすると、翻訳されたものがダウンロードできるというイメージです。
こんなかんじ: [youtube](https://youtu.be/tEJDsapYFr8)
google のクラウドコンピューターを使って実行するので、 python の実行環境は手元に必要ありません。（google colabではなくローカルのpythonの場合は、この記事の一番下にリンクしているとこ[^1]をー参考にしてください。）


[google colab について](https://research.google.com/colaboratory/faq.html)

インストールするパッケージは tkk 修正パッチ（たぶん。未調査。）が適用されている、`4.0.0-rc1` ではエラーにならなかった。
`pip install googletrans` でインストールされるバージョン `3.0.0` では 

```python
code = unicode(self.RE_TKK.search(r.text).group(1)).replace('var ', '')
AttributeError: 'NoneType' object has no attribute 'group'
```

というエラーになる。（2021.1.27時点です。）
この問題は[ Emacs の googletranlete プログラムでもしばしば問題](https://github.com/atykhonov/google-translate/issues/52)になるのと同様でしょう。[google translate のサービスのトークン](https://translate.google.com/translate?sl=en&tl=ja&u=https://vielhuber.de/en/blog/google-translation-api-hacking/)仕様変更に追従して修正されていくという追いかけになりますから、暫定的に今使えている方法はこれということで、[将来的には必ず変更がある](https://qiita.com/dauuricus/items/78024504e7b4bd030dba)ので、最後にリンクを貼っている Issue を確認してください。そこにその時点で問題となっていることと、有志による解決法など tips が更新されているでしょうから。

google colab　上でバージョンを指定して修正された googletrans をインストールすれば OK 。もしバージョン指定していないパッケージをインストールしている場合は、アンインストールしてから、 google colab で、 googletrans をインストールします。

```python:google-colab_googletrans.ipynb
pip install googletrans==4.0.0-rc1
```

googletrans をインストールできたことを確認して、プログラムを実行します。

ipynb(ipython) \<注意　このプログラムはうまくいきません。\>

```python:google-colab_googletrans.ipynb
from google.colab import files
from googletrans import Translator
import sys

uploaded = files.upload()

filename = ''
for fn in uploaded.keys():
  print('User uploaded file "{name}" with length {length} bytes'.format(
      name=fn, length=len(uploaded[fn])))
  filename = fn

#args= sys.argv
args= [('translate.py'),filename,'>','translated-jp.txt']
if len(args) < 2:
    print('python3 translate.py textfile.txt > dist_textfile.txt')
else:
    print('open '+args[1])
    f = open(args[1])
    lines = f.readlines()
    f.close()

    translator = Translator()
    for line in lines:
        translated = translator.translate(line, dest="ja");
        print(line) # Original
        print(translated.text) # translated
        print()
    print('EOF')
    files.download(filename)
```

github gist(private):
[google-colab_googletrans.py](https://gist.githubusercontent.com/dauuricus/83926ee296f487a8b78e6e156e168a3d/raw/4091a5b25011e72ed723b07e41bb11ea7dc961a5/google-colab_googletrans.py)

ただ、やってみると問題があり、数時間使って検証してみると、翻訳するテクストに空白の行があると、`IndexErorr: list index out of range`になりました。

つまり、翻訳されるテクストが、

```
0:00:00.320,0:00:06.320
welcome all you super amazing hardware addicts 
i am so excited to share this project with you

0:00:06.880,0:00:11.920
after we got that letter in from the listener 
talking about how they put lineage os

0:00:11.920,0:00:17.840
on their fire hd tablet i just had to do 
it and the kids have loved this change
```

このような場合、4 行目の空白行でつまづいて、エラーになります。

```python

0:00:00.320,0:00:06.320

0：00：00.320,0：00：06.320

welcome all you super amazing hardware addicts 

超素晴らしいハードウェア中毒者を歓迎します

i am so excited to share this project with you

このプロジェクトをあなたと共有できることをとてもうれしく思います

---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-23-e8018cddf127> in <module>()
     23     translator = Translator()
     24     for line in lines:
---> 25         translated = translator.translate(line, dest="ja");
     26         print(line) # Original
     27         print(translated.text) # Japanese

1 frames
/usr/local/lib/python3.6/dist-packages/googletrans/client.py in <lambda>(part)
    220         # not sure
    221         should_spacing = parsed[1][0][0][3]
--> 222         translated_parts = list(map(lambda part: TranslatedPart(part[0], part[1] if len(part) >= 2 else []), parsed[1][0][0][5]))
    223         translated = (' ' if should_spacing else '').join(map(lambda part: part.text, translated_parts))
    224 

IndexError: list index out of range
```

でも、こうして空白行を詰めてからアップロードすると

```
0:00:00.320,0:00:06.320
welcome all you super amazing hardware addicts 
i am so excited to share this project with you
0:00:06.880,0:00:11.920
after we got that letter in from the listener 
talking about how they put lineage os
0:00:11.920,0:00:17.840
on their fire hd tablet i just had to do 
it and the kids have loved this change
```

エラーにならないという、なんともシンプルな問題なので、いずれ改善されるような気がします。

`translated`についてはこのように定義されています。

```python
class 
googletrans.models.Translated(src, dest, origin, text, pronunciation, extra_data=None, **kwargs)
```

>Translate result object
Parameters:	
`src` – source language (default: auto)
`dest` – destination language (default: en)
`origin` – original text
`text` – translated text
`pronunciation` – pronunciation


#### （追記）改善。 2021-01-28
改行 `'\n'` と空白 `' '` を取り除く処理はまったく googletrans の問題ではないので、 googletrans に渡す list に改行と空白を含まないように改善しました。

ipynb(ipython)

```python:google-colab_googletrans.ipynb
pip install googletrans==4.0.0-rc1
```

translate.ipynb \<このプログラムはいけそう。\>

```python:google-colab_googletrans.ipynb
from google.colab import files
from googletrans import Translator
import sys

uploaded = files.upload()

filename = ''
for fn in uploaded.keys():
  print('User uploaded file "{name}" with length {length} bytes'.format(
      name=fn, length=len(uploaded[fn])))
  filename = fn

#args= sys.argv
args = [('translate.py'),filename]

if len(args) < 2:
    print('python3 translate.py textfile.txt dist_textfile.txt.')
else:
    print('open '+args[1])
    with open(args[1]) as f:
      line = f.readlines() 
    f.close()
    
    line[:] = [l.strip() for l in line]
    line[:] = [l.rstrip('\n') for l in line]
    line[:] = [l.rstrip('\r') for l in line]
    line[:] = [a for a in line if a != '']
    line[:] = [l.replace('\n',' ') for l in line]
    ##print(line)

    translator = Translator()
    num = 20
    #obj_num = 1
    filename = 'translated.txt'

    backup_stdout = sys.stdout
    
    with open(filename,'w') as f:
        sys.stdout = f # stdout to file

        for count, l in enumerate(line):
            if count +1< num:
                translated = translator.translate(l, dest='ja')
                print(count+1,' ', l) # original text
                print(count+1,' ', translated.text)
            else:
                translated = translator.translate(l, dest='ja')
                print(count+1,' ', l) # original text
                print(count+1,' ', translated.text)        
                del translator
                num = num + 20
                #obj_num = obj_num + 1
                #print("")
                #print("--- translator :", obj_num)
                #print("")
                translator = Translator()        

        sys.stdout = backup_stdout # back
    del translator

    files.download(filename)


##    translator = Translator()
##    f = open(filename, 'w')
##    for l in line:
##      translated = translator.translate(l, dest="japanese");
##      print(l) # Original
##      f.writelines(l)
##      f.write('\n')
##      print(translated.text) # dest lang
##      f.writelines(translated.text)
##      f.write('\n')
##      print()
##      f.write('\n')
##    print('EOF')
##    f.close()
##
##    files.download(filename)
```

[github gist googletrans_with_google_colab.py](https://gist.githubusercontent.com/dauuricus/1c5b0df0f03437b837dd6d15f48a798e/raw/f3e3de1438a5d3627448b86d1f63479e4188e765/googletrans_with_google_colab.py)

Cf. [how to remove newline character from a list in python](https://www.kite.com/python/answers/how-to-remove-newline-character-from-a-list-in-python)

Cf. list comprehension:
https://realpython.com/lessons/writing-your-first-list-comprehension/

tkk エラーの参考:
[stackoverflow.com "googletrans stopped working with error nonetype object has no attribute group"](https://stackoverflow.com/questions/52455774/googletrans-stopped-working-with-error-nonetype-object-has-no-attribute-group)

[py-googletrans/issues/234](https://github.com/ssut/py-googletrans/issues/234#issuecomment-742460612)

googletrans 対応言語リスト

| 対応言語リスト |  |  |  |
| :-: | :-: | :-: | :-: |
|'af': 'afrikaans'|'sq': 'albanian'|'am': 'amharic'|'ar': 'arabic'|
|'hy': 'armenian'|'az': 'azerbaijani'|'eu': 'basque'|'be': 'belarusian'|
|'bn': 'bengali'|'bs': 'bosnian'|'bg': 'bulgarian'|'ca': 'catalan'|
|'ceb': 'cebuano'|'ny': 'chichewa'|'zh-cn': 'chinese (simplified)'|'zh-tw': 'chinese (traditional)'|
|'co': 'corsican'|'hr': 'croatian'|'cs': 'czech'|'da': 'danish'|
|'nl': 'dutch'|**'en': 'english'**|'eo': 'esperanto'|'et': 'estonian'|'tl': 'filipino'|
|'fi': 'finnish'|'fr': 'french'|'fy': 'frisian'|'gl': 'galician'|
|'ka': 'georgian'|'de': 'german'|'el': 'greek'|'gu': 'gujarati'|
|'ht': 'haitian creole'|'ha': 'hausa'|'haw': 'hawaiian'|'iw': 'hebrew'|
|'he': 'hebrew'|'hi': 'hindi'|'hmn': 'hmong'|'hu': 'hungarian'|
|'is': 'icelandic'|'ig': 'igbo'|'id': 'indonesian'|'ga': 'irish'|
|'it': 'italian'|**'ja': 'japanese'**|'jw': 'javanese'|'kn': 'kannada'|
|'kk': 'kazakh'|'km': 'khmer'|'ko': 'korean'|'ku': 'kurdish (kurmanji)'|
|'ky': 'kyrgyz'|'lo': 'lao'|'la': 'latin'|'lv': 'latvian'|
|'lt': 'lithuanian'|'lb': 'luxembourgish'|'mk': 'macedonian'|mg': 'malagasy'|
|'ms': 'malay'|'ml': 'malayalam'|'mt': 'maltese'|'mi': 'maori'|
|'mr': 'marathi'|'mn': 'mongolian'|'my': 'myanmar (burmese)'|'ne': 'nepali'|
|'no': 'norwegian'|'or': 'odia'|'ps': 'pashto'|'fa': 'persian'|
|'pl': 'polish'|'pt': 'portuguese'|'pa': 'punjabi'|'ro': 'romanian'|
|'ru': 'russian'|'sm': 'samoan'|'gd': 'scots gaelic'|'sr': 'serbian'|
|'st': 'sesotho'|'sn': 'shona'|'sd': 'sindhi'|'si': 'sinhala'|
|'sk': 'slovak'|'sl': 'slovenian'|'so': 'somali'|'es': 'spanish'|
|'su': 'sundanese'|'sw': 'swahili'|'sv': 'swedish'|'tg': 'tajik'|
|'ta': 'tamil'|'te': 'telugu'|'th': 'thai'|'tr': 'turkish'|
|'uk': 'ukrainian'|'ur': 'urdu'|'ug': 'uyghur'|'uz': 'uzbek'|
|'vi': 'vietnamese'|'cy': 'welsh'|'xh': 'xhosa'|'yi': 'yiddish'|
|'yo': 'yoruba'a|'zu': 'zulu'|

---
**googletrans , YouTube subtitle , Google Colab**
https://qiita.com/dauuricus/items/863dd4d087b3aff6455d

[^1]: [ローカルのpython（pydroid3で検証）で同様の動作をさせたい場合の参考例。](https://qiita.com/dauuricus/private/60ac47a70fe04763db14)