WHR-G300NとLEDE-Project

少し前に雑記ブログのほうでOpenWrt / LEDE-ProjectにおけるWHR-G300Nに関しての記事(BUFFALO WHR-G300NとOpenWrt/LEDE-Project)を書きましたが、この中で触れたパーティションの問題について、LEDE-Projectではつい最近修正が入りました(OpenWrtは修正されるのか不明)。

ramips: add missing partitions – lede-project/source

The partitions were lost during migration to device tree.

コミットメッセージを読むに、OpenWrt 10.xx backfire 辺りまで各デバイス毎の構成情報がCで記述されていたものを OpenWrt 12.xx Atitude Adjustment 辺りから Device Tree Source (dts) に書き換えるにあたって、パーティション定義が抜け落ちてしまった模様。
BUFFALO WHR-G300N のほかに Upvel UR-336UN も同様に抜け落ちていたものの、そちらも今回のコミットでパーティション定義が追加されました。

lede-project/source からのフォークである musashino-build/lede-source では古いコードから引っ張った情報でWHR-G300N のdtsにパーティション定義の追加を行い、正常動作するようにしていましたが、今回の公式のコミットにより独自に追加したものを使う理由は無くなったので、WHR-G300N.dts を公式のものに差し替えました。

この状態で独自にビルドし、実機上で問題なく起動・動作することも確認できました。

Mastodon with IIS (IIS編)

さて、ひとつ前の記事の続きです。今回は Mastodon の上位にくる IIS 側の設定をしていきます。
既に IIS を使用して Web サイトを複数公開していましたが、2年前くらいに立てたとき色々知識が無い状態で弄ったために肥大化しており、ちょうどいいタイミングだったので一から再構築しました。

注意事項など

大体は前回の記事と同じなので、この記事で追加で注意することなど。

  • Mastodon は Streaming API に WebSocket を使用します。IIS は 8.0 以降(Windows Server 2012 以降)から対応しており、それ以前の IIS では(たぶん)利用できないため、構築できても Streaming 等の機能はエラーで使用できません。
  • 今回使用する OS は、Windows Server 2012 R2 です。恐らく Windows 8.1 / 10 等のクライアント版 Windows でも適宜読み替えて設定すれば機能するとは思います。

IIS のインストール

今回は OS をインストールした直後のまっさらな状態からスタートなので、まず IIS のインストールから。

IIS 本体

  • サーバー マネージャーを開く
    設定を変えたりしていなければ、OS 起動後ログインすると自動で起動してくる。
  • “役割と機能の追加” を開く
  • サーバーの選択(IIS をインストールするサーバーを選択)
  • サーバーの役割で “Web サーバー (IIS)” にチェックを入れる
  • “機能” は変更無し
  • IIS の詳細な機能の選択
    “Web サーバーの役割 (IIS)” の “役割サービス” で IIS 内の必要機能を追加で選択する。最低限必要なもののほかに、個人的に必要かなーと思ったモノも含めた。
    • Web サーバー / HTTP 共通機能

      HTTP エラー, ディレクトリの参照, 既定のドキュメント, 静的なコンテンツ, HTTP リダイレクト

    • Web サーバー / セキュリティ

      要求フィルター, IP およびドメインの制限, URL 承認

    • Web サーバー / パフォーマンス

      静的なコンテンツの圧縮

    • Web サーバー / 状態と診断

      HTTP ログ, カスタム ログ, トレース, 要求の監視

    • Web サーバー / アプリケーション開発

      WebSocket プロトコル(重要

    • 管理ツール / IIS 管理コンソール

  • インストール開始
  • ウィザードの終了

Application Request Routing と URL Rewrite のインストール

クライアントから受けたリクエストを Mastodon に転送するために必要となる、Application Request Routing (ARR) と URL Rewrite をインストールする。
サーバーマネージャーから一旦 “IE セキュリティ強化の構成” を Administrator グループで無効にして、Microsoft の公式サイトから WebPI (Web Platform Installer) をダウンロードして起動する。

Application Request Routing 3.0 (ARR)

WebPI 右上の検索欄に “arr” と入力して Enter 、いくつか候補が出てくるので、バージョンが最新の “Application Request Routing 3.0” を “追加” する。

URL Rewrite 2.0

同様に検索欄に “url rewrite” と入力して Enter 、一つだけ “URL Rewrite 2.0″ が候補として現れるので、”追加” する。

上記2つを追加したら、”インストール” を実行する。
以上で IIS とその関連のインストールは完了。

IIS の設定

Application Request Routing の有効化

インストールしただけでは無効のままなので、有効化する。

  • Internet Information Service (IIS) Manager(または インターネット インフォメーション サービス (IIS) マネージャー)を起動する
  • サーバー ホーム画面の “Applicatoin Request Routing Cache” に入る
  • 右側のペインから “Serverr Proxy Settings” に入る
  • “Enable proxy” にチェックを入れる
  • その他の設定は変更せず右側のペインから “適用” する

Mastodon 用 Web サイトの作成

Mastodon へリクエストを転送するための Web サイトを作成する。
先に、

C:\inetpub\wwwroot\

以下に “mastodon(名前は任意)” という名前のフォルダーを作成しておく。

IIS マネージャーの画面左側のペインで、”Web サイト” を右クリックし “Web サイトの追加” から作成画面を開く。
“サイト名” には “mastodon” など任意のわかりやすい名前を入力し、”物理パス” には先程作成済みの “mastodon” フォルダーを指定する。
“バインド” には、以下の通り設定した。

  • 種類: http
  • IP アドレス: 未使用の IP アドレスすべて
  • ポート: 80
  • ホスト名: mstdn.taiha.net

ホスト名には、自身がMastodonで使用するドメイン名を入力する。

Mastodon 用 Web サイトの設定

Web サイトを作成したので、Let’s Encrypt での暗号化とHTTPSへのリダイレクト、 Mastodon への転送のための設定を行う。

Let’s Encrypt の対応

先程作成した Web サイトのホーム画面から “MIME の設定” を開き、右側ペインの “追加…” から以下の通りの設定で MIME を追加する。

  • ファイル名の拡張子: .(半角ドット)
  • MIME の種類: text/plain

Let’s Encrypt で証明書を取得する際、アクセスされるファイルを読み取れるようにする。

HTTPSへのリダイレクト

Mastodon はユーザーのメールアドレスとパスワードを扱うため、HTTPS化は必須。
Web サイトのホーム画面から “URL 書き換え” を開き、右側ペイン “規則の追加” → “受信規則” 内の “空の規則” を選択し OK。
下記の通り設定した。

  • 名前: redirect_https(任意)
  • 要求された URL: パターンに一致する
  • 使用: 正規表現
  • パターン: ^(.*)$
  • (条件)論理グループ化: すべて一致
    • 入力: {HTTPS}
    • 種類: パターンに一致する
    • パターン: off

    • 入力: {URL}
    • 種類: パターンに一致しない
    • パターン:
      ^\.well-known/acme-challenge/(.*)$
      
  • アクションの種類: リダイレクト
  • リダイレクト URL: https://{SERVER_NAME}/{R:1}
  • クエリ文字列の追加: チェック
  • リダイレクトの種類: 永続的 (301)(任意)

設定後、右側ペインで “適用” して “URL 書き換え” ページに戻る。

Mastodon への転送設定

“URL 書き換え” ページで、右側ペイン “規則の追加” → “受信規則” 内の “空の規則” を選択し OK。
下記の通り入力した。

  • 名前: rewrite_mastodon(任意)
  • 要求された URL: パターンに一致する
  • 使用: 正規表現
  • パターン: ^(.*)$
  • (条件)論理グループ化: すべて一致
    • 入力: {URL}
    • 種類: パターンに一致しない
    • パターン:
      ^\.well-known/acme-challenge/(.*)$
  • アクションの種類: 書き換え
  • URL の書き換え: http://mstdn.taiha.net/{R:0}
  • クエリ文字列の追加: チェック
  • 書き換えられたURLを記録する: 未チェック
  • 後続の規則の処理を停止する: チェック

上記の通り、Let’s Encrypt でのドメイン認証時はこのサーバー内のフォルダにアクセスさせるため、

.well-known/acme-challenge/

以下のURL を Mastodon サーバへ転送しないよう設定した。
また、以前別の記事で Jenkins へ IIS 経由で同様に転送したときは問題なかったものの、今回 Mastodon への転送では、転送先 URL で下記のようにローカル IP アドレスを指定すると問題の出るページがあった。

そのため、今回は Mastodon に利用するドメイン名を指定した。この場合、そのままでは IPv4 ではドメインに登録されているグローバルアドレスに、IPv6 ではこの Web サーバ自体にアクセスが戻ってきてしまうため、

C:\Windows\System32\drivers\etc\hosts

にドメインに対して Mastodon サーバーの IP アドレスを指定する必要がある。以下の通りに指定した。
IPv6 対応環境の場合、同様に Mastodon サーバーのグローバル IPv6 アドレスとドメイン名の組を登録したほうが良いかもしれない。

# MastodonサーバーIP ドメイン名
192.168.11.250  mstdn.taiha.net

以上で、Mastodon サーバーへリクエストを転送する設定が完了。
当方の環境では、最終的なWeb サイトの設定ファイル (web.config) は以下の通り。

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <rewrite>
            <rules>
                <clear />
                <rule name="redirect_https" enabled="true" stopProcessing="true">
                    <match url="^(.*)$" ignoreCase="false" />
                    <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
                        <add input="{HTTPS}" pattern="off" ignoreCase="false" />
                        <add input="{URL}" pattern="^\.well-known/acme-challenge/(.*)$" negate="true" />
                    </conditions>
                    <action type="Redirect" url="https://{SERVER_NAME}/{R:1}" />
                </rule>
                <rule name="mastodon_ubuntu-server" stopProcessing="true">
                    <match url="^(.*)$" ignoreCase="false" negate="false" />
                    <conditions logicalGrouping="MatchAll" trackAllCaptures="false">
                        <add input="{URL}" pattern="^\.well-known/acme-challenge/(.*)$" ignoreCase="false" negate="true" />
                    </conditions>
                    <action type="Rewrite" url="http://mstdn.taiha.net/{R:0}" />
                </rule>
            </rules>
        </rewrite>
        <staticContent>
            <mimeMap fileExtension="." mimeType="text/plain" />
        </staticContent>
    </system.webServer>
</configuration>

ついでに、IIS に最初からある “Default Web Site” は使用しないので、右クリックのメニューなどから停止させておく。

Let’s Encrypt 証明書取得

Mastodon のサイトの通信を暗号化するため、Let’s Encrypt の証明書を取得する。

Windows 用Let’s Encrypt ツールの導入

github.com/Lone-Coder/letsencrypt-win-simple から、最新のツールをダウンロードして C:\ 以下に展開する。

ツール内の Web_Config.xml 書き換え

この Web_Config.xml で設定される部分は既に IIS で設定済みなのと、そのまま利用した場合エラーが出たので、このファイルが何もしないように書き換えてしまう。
以下の通りに書き換えた。

<?xml version="1.0" encoding="UTF-8"?>

<configuration>
  <system.webServer>
  </system.webServer>
  <system.web>
  </system.web>
</configuration>

Let’s Encrypt で証明書を取得

今回、既に別のサイトも存在するので、それらもまとめてカバーするために単一のサイト用の証明書ではなく、”SAN 証明書” を取得した。
上記で Windows 用 Let’s Encrypt ツールを展開したフォルダに移動し、コマンドプロンプトを管理者権限で起動して下記の通り実行していく。ハイライト箇所が入力した場所。
なんだかものっそい長くなっているのはドメインが多すぎるためで、証明書を取得するドメインが1個だけなら多少短くなる。

C:\letsencrypt-win-simple>letsencrypt.exe --san
The global logger has been configured
Let's Encrypt (Simple Windows ACME Client)
Renewal Period: 60
Certificate Store: WebHosting
ACME Server: https://acme-v01.api.letsencrypt.org/
Config Folder: C:\Users\Administrator\AppData\Roaming\letsencrypt-win-simple\htt
psacme-v01.api.letsencrypt.org
Certificate Folder: C:\Users\Administrator\AppData\Roaming\letsencrypt-win-simpl
e\httpsacme-v01.api.letsencrypt.org
Loading Signer from C:\Users\Administrator\AppData\Roaming\letsencrypt-win-simpl
e\httpsacme-v01.api.letsencrypt.org\Signer
Getting AcmeServerDirectory
Loading Registration from C:\Users\Administrator\AppData\Roaming\letsencrypt-win
-simple\httpsacme-v01.api.letsencrypt.org\Registration
Scanning IIS Sites
 6: SAN - IIS eject.taiha.net (D:\wwwroot\eject.taiha.net)
 3: SAN - IIS mstdn.taiha.net (D:\wwwroot\mstdn.taiha.net)
 5: SAN - IIS sokuten.taiha.net (C:\inetpub\wwwroot)
 2: SAN - IIS taiha.net (D:\wwwroot\taiha.net)
 4: SAN - IIS teo.taiha.net (D:\wwwroot\teo.taiha.net)

 W: Generate a certificate via WebDav and install it manually.
 S: Generate a single San certificate for multiple sites.
 F: Generate a certificate via FTP/ FTPS and install it manually.
 M: Generate a certificate manually.
 A: Get certificates for all hosts
 Q: Quit
Choose from one of the menu options above: S
Running IISSiteServer Plugin
Enter all Site IDs seperated by a comma
 S: for all sites on the server 2,3,4,5,6
Authorizing Identifier taiha.net Using Challenge Type http-01
Writing challenge answer to D:\wwwroot\taiha.net\.well-known/acme-challenge/(ドメイン確認用ファイル)
Writing web.config to add extensionless mime type to D:\wwwroot\taiha.net\.well-
known\acme-challenge\web.config
Answer should now be browsable at http://taiha.net/.well-known/acme-challenge/(ドメイン確認用ファイル)
Submitting answer
Authorization Result: valid
Deleting answer
Additional files exist in D:\wwwroot\taiha.net\.well-known/acme-challenge/ not d
eleting.
Authorizing Identifier mstdn.taiha.net Using Challenge Type http-01
Writing challenge answer to D:\wwwroot\mstdn.taiha.net\.well-known/acme-challeng
e/(ドメイン確認用ファイル)
Writing web.config to add extensionless mime type to D:\wwwroot\mstdn.taiha.net\
.well-known\acme-challenge\web.config
Answer should now be browsable at http://mstdn.taiha.net/.well-known/acme-challe
nge/(ドメイン確認用ファイル)
Submitting answer
Authorization Result: valid
Deleting answer
Additional files exist in D:\wwwroot\mstdn.taiha.net\.well-known/acme-challenge/
 not deleting.
Authorizing Identifier teo.taiha.net Using Challenge Type http-01
Writing challenge answer to D:\wwwroot\teo.taiha.net\.well-known/acme-challenge/
(ドメイン確認用ファイル)
Writing web.config to add extensionless mime type to D:\wwwroot\teo.taiha.net\.w
ell-known\acme-challenge\web.config
Answer should now be browsable at http://teo.taiha.net/.well-known/acme-challeng
e/(ドメイン確認用ファイル)
Submitting answer
Authorization Result: valid
Deleting answer
Additional files exist in D:\wwwroot\teo.taiha.net\.well-known/acme-challenge/ n
ot deleting.
Authorizing Identifier sokuten.taiha.net Using Challenge Type http-01
Writing challenge answer to C:\inetpub\wwwroot\.well-known/acme-challenge/(ドメイン確認用ファイル)
Writing web.config to add extensionless mime type to C:\inetpub\wwwroot\.well-kn
own\acme-challenge\web.config
Answer should now be browsable at http://sokuten.taiha.net/.well-known/acme-chal
lenge/(ドメイン確認用ファイル)
Submitting answer
Authorization Result: valid
Deleting answer
Deleting web.config
Deleting C:\inetpub\wwwroot\.well-known/acme-challenge/
Deleting C:\inetpub\wwwroot\.well-known
Authorizing Identifier eject.taiha.net Using Challenge Type http-01
Writing challenge answer to D:\wwwroot\eject.taiha.net\.well-known/acme-challeng
e/(ドメイン確認用ファイル)
Writing web.config to add extensionless mime type to D:\wwwroot\eject.taiha.net\
.well-known\acme-challenge\web.config
Answer should now be browsable at http://eject.taiha.net/.well-known/acme-challe
nge/(ドメイン確認用ファイル)
Submitting answer
Authorization Result: valid
Deleting answer
Additional files exist in D:\wwwroot\eject.taiha.net\.well-known/acme-challenge/
 not deleting.
Requesting Certificate
Request Status: Created
Saving Certificate to C:\Users\Administrator\AppData\Roaming\letsencrypt-win-sim
ple\httpsacme-v01.api.letsencrypt.org\2,3,4,5,6-crt.der
Saving Issuer Certificate to C:\Users\Administrator\AppData\Roaming\letsencrypt-
win-simple\httpsacme-v01.api.letsencrypt.org\ca-0A0141420000015385736A0B85ECA708
-crt.pem
Saving Certificate to C:\Users\Administrator\AppData\Roaming\letsencrypt-win-sim
ple\httpsacme-v01.api.letsencrypt.org\2,3,4,5,6-all.pfx
Installing Non-Central SSL Certificate in the certificate store
Opened Certificate Store WebHosting
 Set private key exportable
Set private key exportable
Adding Certificate to Store
Closing Certificate Store
Installing Non-Central SSL Certificate in server software
Updating Existing https Binding
IIS will serve the new certificate after the Application Pool Idle Timeout time
has been reached.
Committing binding changes to IIS
Opened Certificate Store WebHosting
Removing Certificate from Store X509Certificate2 {(置き換えられた古い証明書の情報)}
Closing Certificate Store
Updating Existing https Binding
IIS will serve the new certificate after the Application Pool Idle Timeout time
has been reached.
Committing binding changes to IIS
Opened Certificate Store WebHosting
Closing Certificate Store
Updating Existing https Binding
IIS will serve the new certificate after the Application Pool Idle Timeout time
has been reached.
Committing binding changes to IIS
Opened Certificate Store WebHosting
Closing Certificate Store
Updating Existing https Binding
IIS will serve the new certificate after the Application Pool Idle Timeout time
has been reached.
Committing binding changes to IIS
Opened Certificate Store WebHosting
Closing Certificate Store
Updating Existing https Binding
IIS will serve the new certificate after the Application Pool Idle Timeout time
has been reached.
Committing binding changes to IIS
Opened Certificate Store WebHosting
Closing Certificate Store
Adding renewal for IISSiteServer 2,3,4,5,6 ()
Creating Task letsencrypt-win-simple httpsacme-v01.api.letsencrypt.org with Wind
ows Task scheduler at 9am every day.

Do you want to specify the user the task will run as? (y/n)
Renewal Scheduled IISSiteServer 2,3,4,5,6 () Renew After 2017/06/24
Press enter to continue.


C:\letsencrypt-win-simple>

このツールは自動的に IIS に設定されている Web サイトを検出し、リストアップしてくれる。ただし、IDN(日本語ドメインなど)には非対応で、その URL は検出できない。Let’s Encrypt 自体は IDN に対応している。
今回は IIS に設定されている Web サイトの証明書を取得するため 29行目で “S” を、リストアップされている Web サイトすべてが対象なので 32行目でリストの先頭についている番号 “2,3,4,5,6” を指定した。”1″ は IIS に最初から存在していた “Default Web Site” に割り当てられている。
番号を指定して Enter を押すと、自動で確認用ファイルの作成と Let’s Encrypt サーバーからのアクセス確認(ドメインが存在するかどうか)が行われ、さらに IIS の各サイトへ HTTPS の設定と証明書の割り当てまで行ってくれる。

最後142行目で尋ねられているのは、取得した証明書の更新スケジュールをシステムのスケジュールに登録するが、これを別のユーザーとして実行するかどうかの指定。特に変える必要も無いため、”n” を入力して進んだ。するとスケジュールに登録した趣旨の表示の後 “Press enter to continue” と表示され、Enter キーを押すとツールが終了する。
できれば、タスクスケジューラを開き、”タスク スケジューラ ライブラリ” -> “letsencrypt-win-simple …” というタスクが存在するか確認する。これが実行されないと、証明書が更新されず期限が 90日で切れ、Web サイトがエラーでアクセスできなくなる。

以上で IIS の設定と証明書の取得は全て終了。

アクセス確認

正常に IIS へのアクセスが Mastodon へ転送されるか確認する。IPv6 が利用可能な環境ではドメインに IPv6 アドレスを設定していれば直接アクセスできるが、v4 のみの場合はクライアント PC の hosts 内に、ドメインに対して Web サーバ側の IP アドレスを指定する。

また、可能であれば携帯電話やスマートフォン等から docomo や au、softbank 等のモバイル回線を使用して、外部からも正常にアクセスできるかを確認する。
↓ LAN 内の PC から

↓ docomo spmode 回線を利用して L-05E から


以上で全て完了です。
今回のやり方で立てたインスタンス “どんぶり大破” と、その後最新の開発バージョンを追う予定で立てたインスタンス “ておくれ” は、今のところ継続的に運用する予定です。

それでは。

Mastodon with IIS (Mastodon編)

というわけでやりました、Mastodon インスタンス構築。”サーバを自分で建てられる” と聞いてやらないわけがない性格なので仕方ないね。
今回はMastodon 本体の構築。と言っても、ほとんど公式ドキュメント (Production guide)に準拠します。

下記手順については、記事執筆時点の公式ドキュメントに従ったものです。公式ドキュメントは頻繁に更新されるため、最新の手順に従ってください。

注意事項など

  • サーバの構築などは学習目的で行っています。間違いや改善すべき点等含んでいる前提でご覧ください。
  • クレジットカードが無い(作るのも現状不可)などの理由で、クラウドの利用はそもそも選択肢にありません。
  • 今回は非Docker環境で構築します。そもそもDocker についての知識が乏しいことなどが理由です。
  • 構築先の環境等の詳細については、構築済みインスタンス “どんぶり大破” の about/more ページに記載しています。

必要パッケージのインストール

Production guide の “General dependencies” “Redis” “Postgres” に従ってインストールしていきます。

General dependencies

Nginx は apt-get install の中にありませんが、OSに入ってないのでここで入れてしまいました。

sudo apt install imagemagick ffmpeg libpq-dev libxml2-dev libxslt1-dev nodejs file git curl nginx
curl -sL https://deb.nodesource.com/setup_4.x | sudo bash -

sudo apt install nodejs

sudo npm install -g yarn

Redis

そのまんまインストール

sudo apt install redis-server redis-tools

Postgres

インストール

sudo apt install postgresql postgresql-contrib

Mastodon 用ユーザーの作成

ユーザーを Postgresql によって作成済みのユーザー “postgres” に切り替えて Postgresql のコンソールへログインし、データベース管理の新規ユーザー “mastodon” を作成する。

sudo su - postgres
psql

# ↓新規ユーザー "mastodon" をデータベース作成権限を与えて作成
CREATE USER mastodon CREATEDB;

# ↓Postgresql のコンソールを終了
\q

その他

上記の “\q” の下に “Under Ubuntu 16.04, …” と書かれているが、Ubuntu 16.04 未満の場合必要な操作なので、Ubuntu Server 16.04 を用いている今回は関係無し。

新規 Linux ユーザーの作成

Mastodon は専用のユーザーアカウントで実行する関係で、新規のユーザー “mastodon” を作成する。参考

sudo adduser mastodon
# パスワード入力後、色々聞かれるが何も入力せず4回ほどEnter。最後 "これで良いか" という問いは "y" と入力しEnter でユーザーの作成を完了する。
gpasswd -a mastodon sudo

ユーザーの作成と sudo 権限の付与が完了後、sudo su – mastodon で作成したアカウントに切り替える。
これ以降の作業は、このアカウントで行う。

Rbenv

Ruby のインストール / 管理を行う rbenv の準備
“Production guide” にある通り、rbenv の公式ドキュメントにある方法でインストールを行う。GCC などが必要になるので、”まあいいや” とか言いつつ apt install build-essential をしてしまった。
rbenv のインストールが完了後、

rbenv install 2.4.1
rbenv global 2.4.1

で Ruby ver.2.4.1 のインストールとグローバルバージョンの設定を行った。
Ruby のインストールの際、必要なパッケージが不足していてビルドがコケたりもした。コンソール上のエラーメッセージ内に不足しているパッケージが表示される(libreadline-devなど)ので、それに従い追加でインストールする。

Mastodon 本体の引き込みと追加インストール

Git を利用してMastodon 本体をサーバー上に引き込み、必要パッケージの追加インストールを行う。

引き込み

git clone で、そのまま引き込む。場所は特に変える理由もなかったので、公式ドキュメントに従った。

cd ~     # /home/mastodon
git clone https://github.com/tootsuite/mastodon.git live     # /home/mastodon/live/ 以下に clone
cd live

# master(開発版)はバグが入り込みやすく不安定なため、安定版のバージョンのコードを引き込む
git checkout $(git tag | tail -n 1)

追加パッケージのインストール

ここで “gem コマンドがインストールされていない” などのエラーが出る場合、Ruby のインストールに失敗している可能性があるので rbenv からやり直し。

gem install bundler
bundle install --deployment --without development test
yarn install --pure-lockfile

Mastodon の設定

Mastodon の全体的な設定を行う。

設定ファイルの作成

既存の .env.production.sample ファイルを .env.production としてコピー。

cp .env.production.sample .env.production

設定

デフォルトの設定からの変更のみ列挙、未変更の箇所は未記載。DBのパスワードは、公式ドキュメントにある通り空欄のままにする。

REDIS_HOST=localhost
DB_HOST=/var/run/postgresql
DB_USER=mastodon
DB_NAME=mastodon_production

# Mastodonで利用するドメイン名
LOCAL_DOMAIN=mstdn.taiha.net

# ~/live/ 以下で rake secret コマンドを1回ずつ実行して、生成された乱数を入れる。なので計3回実行することになる。
PAPERCLIP_SECRET=(乱数)
SECRET_KEY_BASE=(乱数)
OTP_SECRET=(乱数)

# Mastodon サイトアクセス時に、既定で表示に使われる言語
DEFAULT_LOCALE=ja

# アカウントの確認用に送信するE-Mail設定。
# 今回は Mailgunを試したものの無料アカウントの制限が厳しかったため、新規に取得した Gmail のアカウントを利用することにした。
SMTP_SERVER=smtp.gmail.com
SMTP_PORT=587
SMTP_LOGIN=(Gmail アカウントのメールアドレス 例: hogehoge@gmail.com)
SMTP_PASSWORD=(Gmail アカウントのパスワード)

その他

ユーザーのアイコンやヘッダー、アップロードされる画像や動画の保存先も変更したかったので “PAPERCLIP_ROOT_PATH” も設定してみたものの、メディアが保存はされるのにそこから読み出せないというトラブルが発生したため、デフォルトの保存先である “~/live/public/system” に対して、マウントしたドライブからシンボリックリンクを設置した。ドライブの当該フォルダの所有者は “mastodon” ユーザーに変更済み。

cd ~/live/public
mv ./system ./system.bak     # 一旦名前を変える
ln -s /mnt/mstdn_media/system system

Mastodon のセットアップ

データベースとCSSやJavaScriptの準備。

データベースの作成

データベース及びテーブルの作成。

RAILS_ENV=production bundle exec rails db:setup

CSS と JavaScript の precompile

RAILS_ENV=production bundle exec rails assets:precompile

Systemd サービスの作成

Mastodon の各プロセスを、systemd のサービスとして登録する。

  • /etc/systemd/system/mastodon-web.service
  • /etc/systemd/system/mastodon-sidekiq.service
  • /etc/systemd/system/mastodon-streaming.service

上記の3つを、Production guide からそれぞれそのままコピーして設置。
そのうえで、OS起動時の自動開始有効化と手動での開始を行う。

# 3つのサービスの自動開始有効化
sudo systemctl enable /etc/systemd/system/mastodon-*.service

# 手動開始
sudo systemctl start mastodon-web.service mastodon-sidekiq.service mastodon-streaming.service

Nginx の設定

今までに設定した Mastodon にアクセスできるように、Nginx のプロキシ等の設定を行う。
今回 Mastodon インスタンスのサーバー上で一緒に Nginx が動作するが、その上位でさらに別のサーバー上にある IIS を経由してクライアントからのアクセスを行えるようにするため、Producion guide にあるNginx の設定例から以下の部分を変更した。
Let’s Encrypt を利用した暗号化 (HTTPS) は上位の IIS で行うため、関連する設定は全て無効化。
server_name には、Mastodonで使用するドメイン名を設定する。

#server {
#  listen 80;
#  listen [::]:80;
#  server_name example.com;
#  # Useful for Let's Encrypt
#  location /.well-known/acme-challenge/ { allow all; }
#  location / { return 301 https://$host$request_uri; }
#}

server {
#  listen 443 ssl;
#  listen [::]:443 ssl;
  listen 80;
  listen [::]:80;
  server_name mstdn.taiha.net;

#  ssl_protocols TLSv1.2;
#  ssl_ciphers EECDH+AESGCM:EECDH+AES;
#  ssl_ecdh_curve prime256v1;
#  ssl_prefer_server_ciphers on;
#  ssl_session_cache shared:SSL:10m;

#  ssl_certificate     /etc/letsencrypt/live/example.com/fullchain.pem;
#  ssl_certificate_key /etc/letsencrypt/live/example.com/privkey.pem;
#  ssl_dhparam         /etc/ssl/certs/dhparam.pem;

  keepalive_timeout    70;
  sendfile             on;
  client_max_body_size 0;

  root /home/mastodon/live/public;

  gzip on;
  gzip_disable "msie6";
  gzip_vary on;
  gzip_proxied any;
  gzip_comp_level 6;
  gzip_buffers 16 8k;
  gzip_http_version 1.1;
  gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

  add_header Strict-Transport-Security "max-age=31536000";

  location / {
    try_files $uri @proxy;
  }

  location /assets {
    add_header Cache-Control "public, max-age=31536000, immutable";
  }

  location @proxy {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header Proxy "";
    proxy_pass_header Server;

    proxy_pass http://127.0.0.1:3000;
    proxy_buffering off;
    proxy_redirect off;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;

    tcp_nodelay on;
  }

  location /api/v1/streaming {
    proxy_set_header Host $host;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header X-Forwarded-Proto https;
    proxy_set_header Proxy "";

    proxy_pass http://localhost:4000;
    proxy_buffering off;
    proxy_redirect off;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection $connection_upgrade;

    tcp_nodelay on;
  }

  error_page 500 501 502 503 504 /500.html;
}

設定を記述し終わったら、/etc/nginx/sites-available/mastodon として保存し、/etc/nginx/sites-enabled/default を削除の上 /etc/nginx/sites-enabled/mastodon としてシンボリックリンクを作成する。

cd /etc/nginx/sites-enabled
sudo ln -s /etc/nginx/sites-available/mastodon mastodon

その後、Nginx サービスを再起動する。

sudo service nginx restart

以上で Mastodon 側の設定は終了。あとは IIS 側の設定に続きますが、疲れたので後で書きます…

2017/04/26追記: 書きました ==> Mastodon with IIS (IIS編)

LuCIの日本語訳について

今更ではあるものの、とりあえずメモというかざっくりまとめ。

LuCIとは

  • ルータ用Linuxディストリビューションである、OpenWrtやその派生のLEDE-Project用WebUI
  • “Lua Configuration Interface” の略の通り、Luaによって記述されている
  • 基本的にLuCIだけでは機能せず、本体アプリケーションと一緒に機能する
    例: luci-app-adblock -> luci-app-adblock (LuCI App) + adblock(本体)
  • LuCIの機能は、ユーザーが新しく追加することができる
  • 様々な言語で利用できる(2017/03/01現在、26言語)
  • 未翻訳の部分は、ユーザーが訳して追加することもできる
    • 少し前から参加

LuCIプロジェクトへの参加

  • 基本GitHub上での参加
    • 機能の追加や修正、翻訳の追加や修正どちらもここ
    • かつては翻訳ポータルを利用していたらしいが、現在はGitHubのみ
  • ガイドラインで全てのコミットに実名と有効なメールアドレスでサインを入れることが定められている
    • “git commit –signoff”、もしくは手書き
    • 例: Signed-off-by: YAMADA Tarou <hogehoge@gmail.com>
    • メールアドレスはGmail等でOK
    • 名前の書き方についてはweblioの解説ページなどを参照
      • 私は基本 “姓 名” の順で姓を全て大文字
    • 実名ではない名前でのコミットをPRした場合、プロジェクトメンバーから “次から実名でコミットするように” と指摘が入る
      • 何度も繰り返すとたぶんPRを蹴られる(やったことは無い)

LuCIの翻訳

  • 現状LuCIプロジェクトに各言語の担当者はいない
  • luci-base、luci-appで一つずつ分離されているpoファイルに対訳を書き込む
  • 既存の訳文と表記をできるだけ揃える
    • 現在作業中
  • poファイルが存在しないluci-appの場合、当該Appのpot(テンプレートファイル)から新規にpoファイルを作成する
    • 作成するpoファイルは、”luci-app-xxx” の “xxx” と同じファイル名にする(違っていると翻訳が適用されない)
  • pot(テンプレートファイル)が存在しないluci-appの場合、buildディレクトリ以下にある “i18n-scan.pl” を使用してテンプレートを他のluci-appと同様の階層に生成する
    $ ./build/i18n-scan.pl applications/luci-app-adblock > applications/luci-app-adblock/po/templates/adblock.pot
    • LuCI翻訳補助ツール等のドキュメント
    • poが存在しない場合と併せ、可能であれば翻訳後にビルドして翻訳が適用されるか確認する
      • “feeds.conf.default” をコピーして “feeds.conf” とし、”luci” の行を
        src-git luci https://github.com/(GitHubユーザー名)/(自フォーク).git;(ブランチ名)

        に置き換える
        例:

        #src-git luci https://git.lede-project.org/project/luci.git
        src-git luci https://github.com/musashino205/luci.git;wg-add-ja
        
  • 翻訳する機能を可能な限り理解してから訳す
    • トンデモ訳や誤操作の原因になる誤訳を防止するため
    • 翻訳するluci-appの本体Appのドキュメントが理解するのに最適
  • 翻訳する文字列がどこに表示されるものか、極力実際のUIで確認する
    • 項目名なのか、項目に対する説明文なのかを区別するため
    • 説明は少々長くても可か否か
    • 稀に翻訳した箇所が適用されないことがある
      • Luaソースの問題など
  • “%s” や “%q” などは訳さず、順番も元の並びから変更しない
    • ユーザーの入力や設定情報、デバイスの情報をもとに文字列や値が入る
    • Luaソースに記述された順番で文字列や値が入るため、翻訳での順番を変えると誤った表示になる

LuCIの日本語訳について

  • 既に大半が翻訳済み
    • 2011 – 2013年頃に存在した部分は、ほぼ全てが当時参加した方が翻訳された模様
  • それ以降追加された箇所は私が少しずつ訳して投げてます
  • 新たにGitHubでの参加は、LuCIプロジェクト側の方々も(たぶん)ウェルカム(なはず)
  • 日本語訳で誤訳や改善、疑問等あれば、直接参加(openwrt/luciへのPullRequestまたはissue)か私のフォークのissuesページ
    • 私のフォークへのissueは日本語でOK
    • 翻訳について多くの方に聞きたいことが度々出てくるため、その相談にも乗っていただければ
      • カタカナ2単語間の区切り(中点かスペースか)、専門用語の一般名など

OpenWrt / LEDEのWebUI “LuCI” を翻訳する

少し前から翻訳に携わっているOpenWrt/LEDE-Projectで利用されているWebUI “LuCI” ですが、某所にて全体を通してのやり方について尋ねられたことがあったので、今後翻訳や修正に参加する人がもっと増えれば、ということで書き留めることにしました。
少し前にLEDE 17.01向けLuCIのブランチ(lede-17.01)が切られましたが、今回はmasterブランチのみに絞って書きます。

今回記事がかなり長いので、記事内リンクを設置。


作業環境

翻訳の主体となる .po ファイルの編集とGitの操作のみであればWindowsのみでも可能。ただし、LuCI側で用意されているツールを利用する場合Linux系の環境が必要。
あくまで筆者自身のやり方なので、若干面倒な気がしなくもないけど悪しからず。

Windows環境

  • OS: Windows 10

    言わずと知れたWindows系最新OS。

  • Git環境: Git for Windows

    筆者自身は、主にgit-bashを使用。

  • gettext(.po)エディタ: Poedit

    OSDN / SourceForgeのPoeditはバージョンが古くなっているため、公式サイトからのダウンロードを推奨。
    無償版と有償版があり、違いはネット上のデータベースからの翻訳サジェスト機能や詳細な統計情報など。
    LuCIの翻訳では、自身の英語力にもよるものの無償版で十分。ちなみに、筆者に英語力はありません。

  • LuCIツール環境: WSL (Windows Subsystem for Linux)

    Windows 10 Anniversary Updateより正式に追加(これ自体はまだbeta機能)された、CUIなLinux (Ubuntu)環境。
    LuCI側で用意されているツール類はWindows環境では動作しないため、これらのツールを使う場合は一旦WSLで作業。


Linux環境

現在普段使用するPCにLinux環境が無く確認できないため、詳しくは書かない。

  • OS: 任意のLinux ディストリビューション

  • Git環境: git-coreなど

  • gettext(.po)エディタ: Poedit

    WSLで試すも、1.8.11ソースコードからのインストールが上手くいかなかった。

    apt-get install poedit

    でインストール可能だが、旧バージョンの1.5.4がインストールされる。

  • LuCIツール環境: 各shell(bash等)


必要なもの

  • GitHubアカウント

    翻訳した .poなどはGitHubを通してPull Request (PR)を行い、メンテナが確認したうえでマージ(取り込み)されるため、GitHubのアカウントが必要。

  • 任意: 英和辞書等

    翻訳の際に使ったり。筆者はインターネット上の辞書サイトを見たりしている。

  • ある程度のネットワーク, PC関連知識

    一般的な英単語だけでなく、専門用語の単語もある程度入ってくる。

  • 多少の英語読解力

    どちらかというと、そこまで難易度の高い英単語が登場する頻度は多くは無い。
    ただ、やはり慣用句的なものが使用されることが多少あったり、また、GitHubでPRを行う際にメンテナから英語による指摘が入る場合があるため、それに従って正確に対応する必要がある。

  • 根気

    筆者の様に、あまり英語力が無い状態で翻訳を行おうとすると、辞書等とエディタを行ったり来たり、Google翻訳で再翻訳(訳した日本語→英語)を繰り返したり(できる限りの翻訳の信頼性)するため、非常に時間が掛かる。
    英語の読解力に長けている場合は、スムーズに翻訳できると思うので恐らく問題無し。

    2017/02/23 追記:Twitterで興味深い記事が流れてきたのでリンク。
    Web翻訳の結果をオープンソースソフトウェア(OSS)の翻訳に突っ込んではいけませんという話 – いくやの斬鉄日記

  • チャレンジ精神

    翻訳されていない箇所を見つけた場合、「誰かが訳すだろう」ではまず翻訳されない。実際、筆者が翻訳を始めた時点で確認できた限りでは、日本語訳の最終更新が2013年だったが(恐らくそれ以降追加や変更された)未訳箇所が大量にあった。
    見つけたら、「英語があまり得意でないからやらない」「誰かがやるだろう」ではなく、「ならば自分がやる」という気持ちを持つ。もちろん、自信を持てない箇所を無理に翻訳する必要は無く、未訳として残してPRを行っても問題ない


翻訳の流れ

実際の翻訳作業の流れ。基本的には、LuCIのGitHubリポジトリ内にある Contributing Guidelines (CONTRIBUTING.md) の説明に従う。

準備

初回や環境が変わる場合のみ必要な作業。GitHubのアカウントは既に取得しているものとし、GitとPoeditのインストールも済んでいるものとする。
また、LuCIのツールを利用した作業を行う場合は、WSLにも同様にGitの設定が必要になる。

  • Gitの設定

    Git操作を行うにあたり、必要な設定を行う。具体的にはユーザー名とメールアドレス。
    LuCIは後で説明する通り、コミット(作業内容を確定する)に自分の本名でのサインが必要であるため、筆者はユーザー名に本名を登録した(ついでにGitHubのアカウントも表示名を本名に変更した)。
    サインを手動で記述する場合は、GitHubに登録したハンドルネームなどでも(恐らく)問題ない。

    git config --global user.name "(本名または任意のユーザー名)"
    git config --global user.email "(自分の公開用メールアドレス)"
    

    例:

    git config --global user.name "musashino205"
    git config --global user.email "hoge@gmail.com"
    

    設定した内容は、

    git config --global --list
    

    で確認できる。
    名前は漢字ではなく英語表記。
    メールアドレスはGitHub上で公開されるほか、コミットにもサインと一緒に残るため、それでも問題ないアドレスを使用する。Gmailなどのフリーメールで問題ない。

  • LuCIリポジトリのフォーク

    自分のGitHubアカウントに、LuCIリポジトリをコピー(フォーク)する。GitHubのWeb上で、右上にある Fork ボタンから操作を行う。

  • フォークしたリポジトリを作業環境にclone

    自分のアカウントにフォークしたリポジトリを、Gitを利用して作業環境にclone(ダウンロード)する。
    cloneする場所は任意の場所で問題ない。

    git clone https://github.com/(自分のGitHubユーザー名)/luci.git
    

    例(git-bash):

    Tofu@Tofu-H170W10 MINGW64 /
    $ cd ~/git
    
    Tofu@Tofu-H170W10 MINGW64 ~/git
    $ git clone https://github.com/musashino205/luci.git
    Cloning into 'luci'...
    remote: Counting objects: 92014, done.
    remote: Compressing objects: 100% (7/7), done.
    remote: Total 92014 (delta 0), reused 0 (delta 0), pack-reused 92007
    Receiving objects: 100% (92014/92014), 28.56 MiB | 2.43 MiB/s, done.
    Resolving deltas: 100% (53601/53601), done.
    Checking out files: 100% (2474/2474), done.
    
    Tofu@Tofu-H170W10 MINGW64 ~/git
    $
    

    ハイライトされている行が入力したコマンド。

    注: Windowsでは、”~/” の場所は

    C:\Users\(ユーザー名)\
    

    になる。

  • フォーク元リポジトリを登録する

    後でLuCIのフォーク元リポジトリが更新された際に、自分のフォークとの差異を取り込むためにフォーク元リポジトリをGitに登録しておく。
    この登録は、行った環境でのみ機能する。(PC1 → PC2に作業環境を変更した、などの場合は再登録が必要)

    git remote add upstream https://github.com/openwrt/luci.git
    


翻訳する

実際に翻訳していく。


  • 通常の手順

    • 作業用ブランチを切る

      作業環境でcloneしたLuCIのディレクトリに入ると、最初の状態ではmasterブランチ(枝)にいる。
      このmasterブランチは変更せず、作業中の状態との比較や後にPRした変更内容がLuCIに取り込まれた際に、その変更を自分のフォークにも取り込めるように残しておく。
      翻訳作業を開始するにあたって、masterブランチから新規のブランチを切り(枝分かれさせ)、そのブランチに移動して作業を行う。

      git checkout -b (任意の新規ブランチ名)
      

      例(Adblockの日本語訳を更新):

      git checkout -b adblock-upd-ja
      

      上記コマンドでは、新規ブランチの作成と同時にそのブランチへの移動も行われる。

    • poファイルを編集(翻訳)する

      LuCIでは、画面上に翻訳されたテキストを表示するためにgettextというシステムが利用され、その翻訳が記述されるのが .poという拡張子を持つファイルになっている。
      poファイルはLuCIのベース部分および各アプリケーションごとに分離され、それぞれのディレクトリに存在している。

      • ベース
        modules/luci-base/po/ja/
      • アプリケーション
        applications/

        • Adblock
          luci-app-adblock/po/ja/
        • Commands
          luci-app-commands/po/ja/
        • (以下省略)

      これらのpoファイルに、提示される英語のソーステキストに対する翻訳を記述していく。
      可能であれば、ルーター上で実際にLuCIの表示を見て、それぞれのテキストがどこでどのように表示されるものであるか確認しながら翻訳すると、不自然な翻訳になりにくい(です/ます調や文の切り方など)。
      後は根気で頑張って翻訳。先述の通り、不安な部分まで無理に訳す必要は無く、そこは未訳(訳が空)で留め置く。

      ※注: poファイルが存在しないアプリケーションの場合、luci-app-(アプリケーション名(以下 “App名”))/po/templates 以下にテンプレートが存在するので、それをもとに po/ja 以下に (App名).po のファイル名で新規にpoファイルを作成する。その際、poファイルのファイル名が正しくないと、翻訳を行ってもLuCIがアプリケーションのpoファイルを見つけられず翻訳が適用されない。
      テンプレートすら存在しない場合、ツールを利用してテンプレートを生成する必要がある。その場合、テンプレートが存在しない場合の手順 を参照。

      自分にできる範囲での翻訳が完了したら、Poeditで保存して終了し、Git環境に戻る。

    • GitHubのフォークに変更内容を適用する

      追加した翻訳などの変更内容をGitHubに適用する。
      Gitのaddコマンドを用いて変更内容を含ませ、

      git add ./
      

      ※この際、改行コードについて警告が出る場合がある。筆者の場合特に問題なかったので無視した。

      commitコマンドで変更内容の確定を行う。この際、作業した人の名前をコミットメッセージに含める必要がある。
      Git環境に実名を登録した場合は “–signoff” 引数を付け、登録していない場合は何も引数を付けない。
      実名登録済み:

      git commit --signoff
      

      実名未登録(ハンドルネームなど):

      git commit
      

      するとGit環境で既定に設定されているテキストエディタが開くため、そこでコミットメッセージを編集する。特に設定していなければ、恐らく “vi” が使用される。
      コミットメッセージについてもガイドラインでおおよその書き方が指定されている。
      まず、コミットのsubject(主題)は以下の形にする。

      luci-app-(App名): (簡潔な変更内容)

      次に、一行間隔を空けてある程度詳細な変更内容についての説明を書く。
      “最近追加された文字列の日本語訳を追加した(英文)” や、単に “日本語訳を追加した(英文)” など。詳細にとは言っても、そこまで厳密には求められないのでこの程度でもOK。
      ただし、説明を何も書かない場合、この後PRを行った際にメンテナから修正するよう指摘が入る場合がある。
      commitコマンドを “–signoff” 引数を付けて実行した場合は以下の通りになっているか確認する。引数を付けなかった場合は、以下の通りに記述する。

      (説明の後一行空ける)
      Signed-off-by: (自分の実名(英語)) <(メールアドレス)>
      

      例:

      
      Signed-off-by: YAMADA Tarou <tarou@gmail.com>
      

      名前とメールアドレスは適当なもの(私のではない)を使用しました。指摘いただいた場合は変更または削除します。
      コミットメッセージを記述したら、保存してエディタを終了する。

      次にpushコマンドを使用し、GitHubのフォークに翻訳した内容を適用する。

      git push origin --all
      

      この時、”テンプレートが存在しない場合の手順” を行っていた場合のみ、pushがGitHubに受け入れられず拒絶 (reject) される。
      これは先に一旦コミットの取り消しを行った結果、GitHubと作業環境で進み具合が異なるために発生する。
      この場合、GitHub上も作業環境で先に取り消したコミットはそのまま取り消して翻訳後のコミットにまとめるため、強制的にpushを行ってGitHubに適用する。

      git push -f origin --all
      

      pushの拒否と強制pushの例:

      Tofu@Tofu-H170W10 MINGW64 ~/git/luci/applications/luci-app-adblock/po (tool-test)
      $ git push origin --all
      To https://github.com/musashino-build/luci.git
       ! [rejected]        tool-test -> tool-test (non-fast-forward)
      error: failed to push some refs to 'https://github.com/musashino-build/luci.git'
      hint: Updates were rejected because the tip of your current branch is behind
      hint: its remote counterpart. Integrate the remote changes (e.g.
      hint: 'git pull ...') before pushing again.
      hint: See the 'Note about fast-forwards' in 'git push --help' for details.
      
      Tofu@Tofu-H170W10 MINGW64 ~/git/luci/applications/luci-app-adblock/po (tool-test)
      $ git push -f origin --all
      Counting objects: 9, done.
      Delta compression using up to 8 threads.
      Compressing objects: 100% (7/7), done.
      Writing objects: 100% (9/9), 1.40 KiB | 0 bytes/s, done.
      Total 9 (delta 3), reused 1 (delta 0)
      remote: Resolving deltas: 100% (3/3), completed with 2 local objects.
      To https://github.com/musashino-build/luci.git
       + e7ad4b4...5325cb2 tool-test -> tool-test (forced update)
      
      Tofu@Tofu-H170W10 MINGW64 ~/git/luci/applications/luci-app-adblock/po (tool-test)
      $
      

  • テンプレート(.pot)が存在しない場合の手順

    luci-app-(App名)/po/ja/(App名).po
    

    が存在せず、また

    luci-app-(App名)/po/templates/(App名).pot
    

    も存在しない場合、まずテンプレートを作成してから翻訳を行う。

    • 準備

      ツールは前述のとおりWindows環境では動作しないため、Linux環境(WSL)を使用する必要がある。
      WSLを起動し、上記 “準備” の項目のGitによるcloneまで行い、また、作業用ブランチも切る。

    • ツールを実行

      LuCI側で用意されているツールを実行し、テンプレートファイルを作成する。
      テンプレートを作成するアプリケーションのディレクトリ以下に po/templates/ ディレクトリを作成した後、WSL上にてLuCIの一番上位のディレクトリで以下のコマンドを実行する。

      ./build/i18n-scan.pl applications/luci-app-(対象App名) > applications/luci-app-(対象App名)/po/templates/(App名).pot
      

      この “i18n-scan.pl” ツールは、最初の引数で指定されたアプリケーション内のソースコードをスキャンして翻訳するよう指定された(translate, translatef関数が付けられている)文字列を探し出し、出力することができる。
      上記コマンドでは “>” を付けているため、その後に指定されたファイルに対して出力された内容が書き込まれる。

      実行例(luci-app-adblock):

      tofu@TOFU-H170W10:~/openwrt/luci$ mkdir -p applications/luci-app-adblock/po/templates
      tofu@TOFU-H170W10:~/openwrt/luci$ ls -al applications/luci-app-adblock/
      合計 12
      drwxrwxrwx 2 tofu tofu   0  1月 24 18:41 .
      drwxrwxrwx 2 tofu tofu   0  1月 24 18:26 ..
      -rw-rw-rw- 1 tofu tofu 292  1月 24 18:26 Makefile
      drwxrwxrwx 2 tofu tofu   0  1月 24 18:26 luasrc
      drwxrwxrwx 2 tofu tofu   0  1月 24 18:41 po
      drwxrwxrwx 2 tofu tofu   0  1月 24 18:26 root
      tofu@TOFU-H170W10:~/openwrt/luci$ ./build/i18n-scan.pl applications/luci-app-adblock > applications/luci-app-adblock/po/templates/adblock.pot
      tofu@TOFU-H170W10:~/openwrt/luci$ ls -al applications/luci-app-adblock/po/templates/
      合計 4
      drwxrwxrwx 2 tofu tofu    0  1月 24 18:42 .
      drwxrwxrwx 2 tofu tofu    0  1月 24 18:41 ..
      -rw-rw-rw- 1 tofu tofu 1199  1月 24 18:42 adblock.pot
      tofu@TOFU-H170W10:~/openwrt/luci$
      

      luci-app-adblockは既にテンプレートと日本語訳が存在するが、今回例として提示するため、一旦全て削除した。
      この “i18n-scan.pl” ツールは、テンプレートが作成された後LuCIのソースコード自体に変更が入り、コード中で翻訳対象として指定された文字列が変更 / 追加された場合に、テンプレートを更新する際にも用いる。
      テンプレートの更新と、それに従って翻訳する言語のpoファイルを更新する方法については、別記事で書く。

    • フォークに変更を適用

      テンプレートを作成したら、今度はWindows上で作業するために一旦GitHubの自分のフォークに対して、作業環境での変更を適用する。
      Gitのaddコマンドを使用して変更した内容を含ませ、

      git add ./
      

      commitコマンドで変更内容を確定する。

      git commit -m "hoge"
      

      このコミットは後でWindows環境に戻った際に一旦取り消すため、コミットメッセージは適当で構わない。
      次に、pushコマンドでフォークに対して変更を押し出す。

      git push origin --all
      

      以上で、自分のフォークリポジトリにWSLで作業した変更内容が適用される。

      実行例:

      tofu@TOFU-H170W10:~/openwrt/luci$ git add ./
      tofu@TOFU-H170W10:~/openwrt/luci$ git commit -m "test"
      [tool-test e7ad4b4] test
       1 file changed, 70 insertions(+)
       create mode 100644 applications/luci-app-adblock/po/templates/adblock.pot
      tofu@TOFU-H170W10:~/openwrt/luci$ git push origin --all
      Username for 'https://github.com': (GitHubユーザー名)
      Password for 'https://(GitHubユーザー名)@github.com': (GitHubパスワード, 表示されない)
      Counting objects: 27, done.
      Delta compression using up to 8 threads.
      Compressing objects: 100% (4/4), done.
      Writing objects: 100% (5/5), 496 bytes | 0 bytes/s, done.
      Total 5 (delta 2), reused 0 (delta 0)
      remote: Resolving deltas: 100% (2/2), completed with 2 local objects.
      To https://github.com/musashino-build/luci.git
         d385688..e7ad4b4  tool-test -> tool-test
      tofu@TOFU-H170W10:~/openwrt/luci$
      

    • Windows上に変更を引き出す
      GitHub上に適用した変更を、Windows上の作業環境に引き出す。既に作業用ブランチを作っていた場合は、一旦削除する。
      Windows上のGit環境で、pullコマンドを実行する。

      git pull origin -a
      

      すると、WSLで作成した作業用ブランチがWindows上のGit環境にも反映されるので、checkoutコマンドで作業用ブランチに移動する。

      実行例:

      Tofu@Tofu-H170W10 MINGW64 ~/git/luci (master)
      $ git pull origin -a
      remote: Counting objects: 9, done.
      remote: Compressing objects: 100% (8/8), done.
      remote: Total 9 (delta 2), reused 0 (delta 0), pack-reused 0
      Unpacking objects: 100% (9/9), done.
      From https://github.com/musashino-build/luci
       * [new branch]      tool-test  -> origin/tool-test
      Already up-to-date.
      
      Tofu@Tofu-H170W10 MINGW64 ~/git/luci (master)
      $ git checkout tool-test
      Branch tool-test set up to track remote branch tool-test from origin.
      Switched to a new branch 'tool-test'
      
      Tofu@Tofu-H170W10 MINGW64 ~/git/luci (tool-test)
      $
      

    • コミットを一旦取り消す

      必要以上にコミットを増やすべきではなく、日本語の翻訳によるコミットとまとめるため一旦WSL上で行った作業のコミットを取り消す。

      git reset --soft HEAD^
      

      “–soft” という引数を使用することで、変更内容を維持しつつコミットを取り消す(”–hard” では変更内容も削除される)。

      以上まで完了したら、再度 poファイルを編集(翻訳)する に戻り、そこからの手順を行う。


PRの流れ

フォーク元のLuCIリポジトリに対してPull Request (PR)を出し、マージされるまでの流れ。

リポジトリを比較する

実際にPRを出す前に、一旦自分のフォークリポジトリとフォーク元のLuCIリポジトリを比較し、変更点を確認する。

GitHubで自分のフォークリポジトリのページを開き、”Branch: master” となっているドロップダウンリストから翻訳作業を行ったブランチを選択する。その後、”Clone or download” という緑色のボタンの下にある “Compare” リンクを開く。

変更内容を確認し、問題なければPRを作成する。

PRを作成する

リポジトリの比較ページ内にある “Create pull request” ボタンを押下し、PR作成画面に移る。
この時、作業用ブランチに含まれるコミットが1つのみの場合は、コミットのsubject(主題)とメッセージがPRにもそのまま反映される。
反映された内容は、特に変更しなくてもOK。
コミットが2つ以上含まれる場合はブランチ名がsubjectに入り、PRのコメントには何も入力されていない状態となる。この時は、主となるコミットの内容をsubjectとPRコメントに書き写すか、もしくは自分で書く。
特に大きい変更でなかった場合も、PRコメントはコミットメッセージ同様に何かしら書いたほうが良い(たぶん)。

PRのsubjectとコメントの内容を確認し、コメント入力欄右下の “Create pull request” を押下するとPull Request (PR)が作成される。

マージ(または修正の指摘)

PRを作成してしばらくすると、LuCIの翻訳関連を担当するメンテナが内容を確認し、マージを行うか、もしくは内容に不備がある場合、その点の指摘と修正依頼が英語で行われる。
何らかの指摘が行われた場合、その指摘に従ってコミットまたはそれに含まれる内容を修正し、再度コミットするなどした後PRのコメントを追加してメンテナに確認を依頼する。
特に指摘など無くマージされた場合、それで完了となる。

後片付け

PRが通過すると、LuCIのmasterブランチへのマージが行われ変更が取り込まれるため、自分のフォークリポジトリの作業ブランチはこの時点で不要となる。
PRが通過すると、PRページの時系列の最後に作業用ブランチの削除ボタンが出現するため、そこからGitHub側の作業用ブランチを削除する。
その後、作業環境内にある作業用ブランチも削除する。

git branch -D (作業ブランチ名)

以上で、1回の翻訳作業が完了。記事が長くなるほど文字量が多くなっていますが、ある程度繰り返して慣れてくるとそんなに時間はかかりません。
不安な時は、LuCIのコミットログやclose済みのPRなど眺めてみましょう。色々ヒントがあります(ぶっちゃけ、筆者自身もガイドラインとPR流し読んだ程度でトライしてみた)。
各種ツッコミお待ちしてます。