Ansible ドキュメント翻訳メモ

## はじめに

現在 [Ansible](http://www.ansible.com/home) のドキュメントを日本語に翻訳しています。まだほとんどできていない状態ですが、作業のメモを残します。

想定している読者は Ansible に興味がある方はもちろん、ドキュメントの翻訳作業を行ってみたいという方になります。

また、翻訳中の HTML は次のページで公開しています。

- [Ansible ドキュメント](http://www.kyoshida.jp/ansibledoc-ja/index.html)

ソースコードは次の場所にあります。

- [kyoshidajp/ansible](https://github.com/kyoshidajp/ansible/tree/japanization)
- [kyoshidajp/ansible-modules-core](https://github.com/kyoshidajp/ansible-modules-core/tree/japanization)
- [kyoshidajp/ansible-modules-extrax](https://github.com/kyoshidajp/ansible-modules-extras)

## 環境を整える

### 環境

次の環境で作業、動作させています。

<dl>
  <dt><strong>翻訳作業マシン</strong></dt>
  <dd>Mac OS X 10.10.1</dd>
  <dt><strong>公開マシン</strong></dt>
  <dd>Amazon Linux AMI release 2014.09</dd>
</dl>

一部、上記環境でないと動作しない内容もあります。

### ソースコードの取得

まずは翻訳作業マシンにて、ドキュメントを含むソースコードを取得します。

Ansible のソースコードは [GitHub](https://github.com/) 上で管理されているので、GitHub のアカウントを準備します。GitHub にログインした状態で [ansible/ansible](https://github.com/ansible/ansible) にアクセスし、Fork ボタンから自分のリポジトを作成します。

![fork.png](https://qiita-image-store.s3.amazonaws.com/0/36122/714b5b4a-4248-34c2-3bbc-1df32fcd01db.png "fork.png")


次に、これを翻訳作業マシンの適当な作業ディレクトリに clone します。

```
$ git clone https://github.com/kyoshidajp/ansible.git
```

その後、翻訳作業用のブランチを作成して切り替えます。今回は `japanization` という名前にしました。

```
$ git checkout -b japanization devel
```

同様の作業を次のリポジトリに対しても実施します。

- [ansible/ansible-modules-core](https://github.com/ansible/ansible-modules-core)
- [ansible/ansible-modules-extras](https://github.com/ansible/ansible-modules-extras)

### ビルド環境の作成

Ansible のドキュメントをビルドするには、ドキュメンテーションツール [Sphinx](http://sphinx-doc.org/) の実行環境が必要です。

自分の場合、すでにインストールしていましたが、例えば次のようにして setuptools 経由でインストールできます。

```
$ sudo curl https://bootstrap.pypa.io/ez_setup.py -o - | python
$ sudo easy_install sphinx
```

その後、作業ディレクトリでビルドを行います。

```
$ cd ~/ansible
$ make webdocs
```

`docsite/htmlout` に各 HTML ファイルが作成されます。

翻訳作業マシンで次のコマンドを実行すると、デフォルトのウェブブラウザでドキュメントのインデックスページが表示されます。

```
$ open docsite/htmlout/index.html
```

### 構成

Ansible のドキュメントファイル（翻訳対象ファイル）は大きく分けて次の3種類になります。

1. ansible/docsite/rst 以下の rst ファイル
1. モジュールの py ファイル
1. その他

ansible/docsite/rst 以下の rst ファイルは reStructuredText フォーマットです。

モジュールの py ファイルは ansible-module-core, ansible-modules-extras の各種モジュール本体に記述された docstring で、一度 rst に変換されます。

その他は例えば

- ansible/hacking/templates/rst.j2
- ansible/docsite/_themes/srtd/breadcrumbs.html

など、細かいものになります。

### UnicodeDecodeError 対応

ソースコード中に日本語が入ると、環境によってはビルドの際に次のような UnicodeDecodeError が発生する事があります。

```
Traceback (most recent call last):
  File "../hacking/module_formatter.py", line 443, in <module>
    main()
  File "../hacking/module_formatter.py", line 438, in main

... 略 ...

    return self.environment.handle_exception(exc_info, True)
  File "/Library/Python/2.7/site-packages/jinja2/environment.py", line 742, in handle_exception
    reraise(exc_type, exc_value, tb)
  File "../hacking/templates/rst.j2", line 105, in top-level template code
    @{ plainexamples | indent(4, True) }@
  File "/Library/Python/2.7/site-packages/jinja2/filters.py", line 442, in do_indent
    rv = (u'\n' + indention).join(s.splitlines())
UnicodeDecodeError: 'ascii' codec can't decode byte 0xe7 in position 2: ordinal not in range(128)
make: *** [modules2] Error 1
```

これを回避するためにデフォルトエンコーディングを `utf-8` にします。例えば次のページが参考になります。

- [Python - sitecustomize.py を使わず usercustomize.py を使おうね - Qiita](http://qiita.com/tukiyo3/items/06c0821e5002eb73d43f)

### 翻訳開始

テキストエディタで対象ファイルを編集して、翻訳作業を開始します。自分の場合、エディタは [Atom](https://atom.io/) が気になっていたので使っていますが、メモ帳以上の活用が出来ていません。

編集済みファイルが未コミットだと左にあるツリーアイコンが変わって分かりやすいです。

![atom.png](https://qiita-image-store.s3.amazonaws.com/0/36122/922681f8-c948-f88e-ab3a-10745eacf6a0.png "atom.png")

ただ、[GitHub for Mac](https://mac.github.com/) などの GitHub クライアントを使えばそのあたりのヒストリや変更点などの確認機能がカバーされているので、要するにエディタは何でもいいと思います。

翻訳に特化したものではオープンソースの [OmegaT](http://www.omegat.org/en/omegat.html) がありますが、まだ使った事はありません。

### エディタで保存したタイミングでビルドとプレビューを行う

翻訳作業マシンにて、実際に翻訳を開始するフェーズに入ると

1. ビルドコマンドを実行
1. コマンドが成功したのを確認して、ブラウザでプレビュー
1. 編集して 1. に戻る

のサイクルを繰り返します。毎回手作業で行うのも面倒なので、[Guard](https://github.com/guard/guard) と AppleScript を利用して自動化します。

まずはコマンドラインから Google Chrome でドキュメントのリロード（またはロード）を行う AppleScript を作成します。

`file_url` の値はオープンした（またはする）HTML ファイルのディレクトリで、適当なものに変更します。

```applescript:reaload.scpt
tell application "Google Chrome"
    activate
    set file_url to "file:///Users/kyoshida/ansible/docsite/htmlout/"

    if (count every window) = 0 then
        make new window
    end if

    set found to false
    set theTabIndex to -1
    repeat with theWindow in every window
        set theTabIndex to 0
        repeat with theTab in every tab of theWindow
            set theTabIndex to theTabIndex + 1
            if theTab's URL starts with file_url then
                set found to true
                exit
            end if
        end repeat

        if found then
            exit repeat
        end if
    end repeat

    if found then
        tell theTab to reload
        set theWindow's active tab index to theTabIndex
        set index of theWindow to 1
    else
        set index_url to {file_url, "index.html"} as text
        tell window 1 to make new tab with properties {URL:index_url}
    end if
end tell
```

Firefox や Safari ユーザであれば次のページが参考になるかもしれません。

- [Auto Reload :: Add-ons for Firefox](https://addons.mozilla.org/ja/firefox/addon/auto-reload/)
- [Andrew Griffin : Digital Designer — Auto Refresh Safari Extension](http://agriffindesign.com/downloads/autorefresh/)
- [AppleScript: How to reload a Safari window with... | Apple Support Communities](https://discussions.apple.com/thread/5747713?tstart=0)

次に Guard を gem でインストールし、初期コマンドを実行します。

```
$ bundle exec guard init
```

カレントディレクトリに `Guardfile` が作成されるので、次の様な内容にします。

```ruby:Guardfile
guard :shell do
  watch(/(.*).[rst|py]/) {|m| `cd ~/ansible/docsite && make htmldocs && cd ~/guard/ && osascript reload.scpt` }
```

最後に監視対象のファイルが存在するディレクトリを `-w` オプションで指定して実行します。

```
$ bundle exec guard -w ansible/docsite/rst ansible-modules-core ansible-modules-extras
```

これでファイルを保存したタイミングでビルドを実行し、ビルドが成功すればプレビューを行うようになります。

ちなみにモジュールを含めたビルドを行うと時間がかかります（自分の環境では数十秒）。保存からプレビューの時間を短縮するために、ビルド時に一部の rst を削除したり、気になったタイミングでプレビューするために、cron に登録しておいて一定時間ごとにビルドするという方法もあると思います。

### GitHub に push したタイミングでビルドとデプロイを行う

公開マシンでの反映処理は次の流れになります。

1. GitHub から最新のソースを取得
1. ビルド
1. ビルドが成功すれば公開ディレクトリへ転送

これも手作業で行うのは面倒です。Jenkins と GitHub の GitHub plugin を利用して、git push したタイミングで自動的に行われるようにします。

また、この作業内で Apache のインストールも行うので、翻訳したページをウェブで公開する事が出来るようになります。

#### Jenkins のインストール
まずは Jenkins をインストールします。Jenkins の動作マシンは公開マシンと同じにしました。

```
$ sudo wget -O /etc/yum.repos.d/jenkins.repo http://pkg.jenkins-ci.org/redhat/jenkins.repo
$ sudo rpm --import http://pkg.jenkins-ci.org/redhat/jenkins-ci.org.key
$ sudo yum -y install jenkins
```

サブディレクトリで Jenkins を動作させるために、`/etc/sysconfig/jenkins` の `JENKINS_ARGS` を変更します。

```:/etc/sysconfig/jenkins
JENKINS_ARGS="--prefix=/jenkins"
```

その後、サービスを起動します。

```
$ sudo service jenkins start
```

#### Apache のインストール

ウェブサーバの Apache をインストールします。

また、Jenkins を 80 番でアクセスできるようにリバースプロキシの設定も行います。

```
$ sudo yum -y install httpd
$ sudo vi /etc/httpd/conf/httpd.conf
```

```:/etc/httpd/conf/httpd.conf
<VirtualHost *:80>
  ProxyPreserveHost Off
  ProxyPass /jenkins/ http://localhost:8080/jenkins/
  ProxyPassReverse /jenkins/ http://localhost:8080/jenkins/
</VirtualHost>
```

Apache を起動します。

```
$ sudo service httpd start
```

ブラウザから `http://サーバ名/jenkins` にアクセスして Jenkins の画面が表示されれば、Jenkins のインストールは完了です。

#### Jenkins のジョブ登録

Jenkins の画面から「Jenkins の管理」->「プラグインの管理」から [Git Plugin](https://wiki.jenkins-ci.org/display/JENKINS/Git+Plugin)、[GitHub API Plugin](https://wiki.jenkins-ci.org/display/JENKINS/GitHub+API+Plugin)、[Parameterized Trigger Plugin](https://wiki.jenkins-ci.org/display/JENKINS/Parameterized+Trigger+Plugin) をインストールします。

その後、「新規ジョブ作成」からジョブを作成します。

<dl>
  <dt><strong>ジョブ名</strong></dt>
  <dd>update-ansibledoc</dd>
  <dt><strong>ジョブの種類</strong></dt>
  <dd>フリースタイル・プロジェクトのビルド</dd>
</dl>

ジョブの設定は次の様にします。

<dl>
  <dt><strong>ソースコード管理</strong></dt>
  <dd>Git</dd>
  <dt><strong>Repository URL</strong></dt>
  <dd>https://github.com/kyoshidajp/ansible-modules-core.git</dd>
  <dt><strong>Branches to build</strong></dt>
  <dd>japanization</dd>
  <dt><strong>ビルド・トリガ</strong></dt>
  <dd>「Build when a change is pushed to GitHub」にチェック</dd>
</dl>

また、「ビルド手順の追加」から	シェルの実行を選択し、次の内容にします。

```
make webdocs
rsync -vr --delete docsite/htmlout/ /公開ディレクトリ/
```

試しにジョブを実行して結果を確認します。

次のモジュールに対してもそれぞれジョブを作成します。

- [ansible/ansible-modules-core](https://github.com/ansible/ansible-modules-core)
- [ansible/ansible-modules-extras](https://github.com/ansible/ansible-modules-extras)

それぞれビルドの「シェルの実行」にて、`ansible/modules/` 以下に `core` と `extras` として同期するようにします。

```
rsync -vr --delete --exclude ".git/" ./ ../../ansible のジョブ名/workspace/lib/ansible/modules/core
```

または

```
rsync -vr --delete --exclude ".git/" ./ ../../ansible のジョブ名/workspace/lib/ansible/modules/extras
```

になります。

これらはモジュールなので、「ビルド後の処理」で、ビルド（ソースの取得）が成功すれば、本体のジョブ（ジョブ名：update-ansibledoc）を実行するようにします。

これには「Trigger only if build is stable」にチェックをします。

最後にそれぞれジョブが成功する事を確認します。

#### GitHub の設定

次に先ほど作成した Jenkins のジョブを GitHub から呼び出す設定を行います。

GitHub の自分のプロジェクトで、「Setting」->「Web Hooks & Services」の Services - Add service から `Jenkins (GitHub plugin)` を指定します。

「Jenkins hook url」に Jenkins の URL + `github-webhook/` を登録します。

自分の場合、次のようになります。

```
http://www.kyoshida.jp/jenkins/github-webhook/
```

「Active」にチェックを入れて、「Test service」ボタンからアクセス確認をします。

```
Okay, the test payload is on its way.
```

という様な結果が表示されれば、OK です。

試しに適当にファイルを git push して、ジョブが実行されると設定は完了です。

ただし、これもリポジトリ分の設定を行います。つまり

- [ansible/ansible-modules-core](https://github.com/ansible/ansible-modules-core)
- [ansible/ansible-modules-extras](https://github.com/ansible/ansible-modules-extras)

に対しても行います。

## 翻訳について

### ルール

翻訳について、本当はある程度ルールはあった方がいいと思います。ただ、とりあえずスタートしたので、実践には移せていません。

色々と読んだ中で

- [翻訳について | Djangoと日本の仲間たち](http://www.djangoproject.jp/pages/about/translation/)

はとても参考になりました。特に元の英訳をコメントアウトして残すというのは、他の方が後で確認できるので良さそうです。

対象のバージョンも devel ブランチを分岐させたのは良くなかったかな、と思います。

また、TIPS については次のページも参考になりました。

- [ドキュメントの翻訳にSphinxを使う (i18n非利用) — Python製ドキュメンテーションビルダー、Sphinxの日本ユーザ会](http://sphinx-users.jp/cookbook/translation.html)

### 固有名詞をどう訳すか

`playbook` や `inventory` といった固有名詞（専門用語）の訳は、次のパターンがあるようです。

1. そのままにする
2. `プレイブック`、`インベトリ` とする
3. 初出時に `プレイブック(playbook)`、`インベトリ(inventory)`とする

感覚的に 2. はしっくりこなくて、3. は初出がいつか分かりづらい（または今後のアップデートで変更された場合に気づきにくい）ため、そのままにしています。

### 進め方

当初の予定では、まず [Introduction](http://docs.ansible.com/intro.html) と [Playbooks](http://docs.ansible.com/playbooks.html) の基本部分を終わらせた後、各種モジュールのうち、よく使いそうなものや、[Glossary ](http://docs.ansible.com/glossary.html) などを進めるつもりでした。

...でしたが、なかなか進められず、先にモジュールや [Ansible Tower](http://www.kyoshida.jp/ansibledoc-ja/tower.html) に手をつけたりしています。


## 最後に

長々と書きましたが、あらためて振り返ると、しっかりとしたプランもなく進めてしまっている事に気づきました。特にルールが無いような状態なので、今後問題が出てくる可能性が高そうです。

とはいえ、事前にすべての不安要素を解決してから作業を開始するという方法ではいつまでたっても出来ないという事も分かっていました。その意味ではともかく始められた事は良かったのかもしれません。

肝心の翻訳の進捗はなかなか思わしくないので、年末年始の休暇中に出来るだけ進めたいと思います。

また、訳がひどい箇所が多数あるかと思います。PullRequest を受け付けていますので、気になった方はよろしくお願いします。

## 最後の最後に

出来れば上記の環境を作成する playbook を載せたかったのですが、Jenkins 関係のタスクが時間切れで完成させる事が出来ませんでした。

Galaxy で [Stouts.jenkins](https://galaxy.ansible.com/list#/roles/858) を見つけたので、これを使えば可能かもしれません。