社内勉強会用に作成した資料だったものに手を加えて公開。

はじめに

Mattermost のローカライズに協力し始めたので、そのフローの記録(2016/12 月現在)

Mattermost 開発参加の背景

チャットツールとの出会い

外部の勉強会にはよく参加しており、DevOps/ChatOps なんかの言葉も認識していました。 少し前の Hubot による ChatOps ブームの際に、お試しとして社内の Linux サーバに Kandan を入れたのが Chat ツールとの出会いです。

その後、一緒にチャットを使ってくれる方々を巻き込みつつ、Kandan は機能が足りないので Let’s chat へ、Let’s Chat の開発滞ってきたところに同期が Docker で Mattermost 立ててくれたので移行したり。 そんな感じで Mattermost を使い始めてからは、機能的に不満もないためバージョンアップを繰り返しながら、そろそろ1年使い続けています。

最近ようやく Slack を使い始めたのですが、Mattermost に体が慣れすぎて違和感を感じ、プロキシという壁に阻まれた生活を続けたことで身体がガラパゴス化しているのを痛感しています。

ローカライズ参加までの流れ

元々、リモートワーク的な開発を経験するために、そこそこ大きな OSS にコントリビュートしてみたいと思っていました。参加するなら、やはり日常的に使うツールの方が良いと思っており、また、Mattermost はサーバサイド Go 言語・フロントエンド React.js と、まさに興味ピンポイントな技術を採用していたため非常に興味を持っていました。

そんな中、普通に Mattermost を使う中で誤翻訳を一つ発見。

良い機会なので、公式サイトのLocalization ガイドを見ながら開発チームのチャット(Mattermost)に参加し、翻訳のサジェスションを行ってみました。(翻訳を確定するには権限が必要。権限のないユーザはサジェスションまでしか行えない) その時、未翻訳だと思われるメッセージが残っていたため、併せて翻訳作業を続けていました。

そうこうしている内に、新しいバージョンのリリースが近づいたようで翻訳サーバーに翻訳対象メッセージ大量投入されました。が、その当時の公式レビュワーの方が多忙で連絡つかないようで、開発チームのチャットの方でコアメンバーから個別に日本語公式レビュワーにならないかと打診され、本格的に日本語への翻訳を開始することになりました。


matran8.png

Mattermost ローカライズの進め方

ここからは、実際の翻訳作業について記述します。

ローカライズ対象

Mattermost のローカライズ対象メッセージはサーバー/クライアントそれぞれ別ファイルで管理されています。

サーバーサイドは Go 言語で書かれており、utils.TもしくはContext.Tを呼び出している部分で言語ごとのメッセージに変換しています。

func NewServer() {
	l4g.Info(utils.T("api.server.new_server.init.info"))

	Srv = &Server{}
}

platform/server.go at master · mattermost/platform

引数のメッセージ ID に対応するメッセージは JSON 形式でi18n/{lang}.jsonに存在します。

localize_server.jpg Mattermost Developer Brown Bag - Localization - YouTube


クライアントサイドは React.js で書かれており、下記関数を使って言語の変換を行っています。

<FormattedMessage
  id='help.learnMore'
  defaultMessage='Learn more about:'
/>

platform/messaging.jsx・mattermost/platform

引数のメッセージ ID に対応するメッセージはwebapp/i18n/{lang}.jsonに存在します。

localize_webapp.jpg Mattermost Developer Brown Bag - Localization - YouTube


各言語メッセージがかかれている{lang}.jsonファイルのうち、実際に PullRequest などで編集されるのはen.jsonだけで、その他の言語ファイルについては後述の翻訳サーバーにより生成されます。

Pootle

ローカライズ作業はPootleを利用して行っています。

日本語翻訳についてのコミュニケーションは開発者チャット上のi18n - Japanesei18n - Localizationあたりで行われています。 開発者チャットではRelease DiscussionDevelopersなどの開発上のコミュニケーションなども行われているため、開発に参加する場合はアカウントを作成しておいたほうが良いです。

Pootle とは?

ローカライズフロー

実際の開発でen.json内のメッセージが追加・変更されると、毎日 0:00(GMT)に自動で Pootle サーバーへ翻訳対象のメッセージの追加が行われます。 また、Pootle サーバー上で翻訳が完了したメッセージは、毎週月曜の 22:00(GMT)に本体へ Pull Request が作成され、それがマージされることにより翻訳作業が完了します。 translations PR 20161208 by enahum · Pull Request #4740 · mattermost/platform

mattermost_translatin.png Mattermost Developer Brown Bag - Localization - YouTube

Pootle サーバーでの実際の作業

全ての言語のローカライズがここで行われている matran1.png


メッセージはサーバー用とフロントエンド用に分かれている matran2.png


翻訳対象メッセージのステータスはTranslated(翻訳済み)Fuzzy(機械翻訳)Untranslated(未翻訳)に分類される。 matran3.png


Fuzzy(機械翻訳)は、翻訳大将メッセージがサーバに投入されると同時に Pootle システムが自動で翻訳を行ってくれたメッセージ。 レビュワーによる承認作業が必要。 matran4.png


翻訳作業は1メッセージごとに行う matran5.png


翻訳を行うとこのように見える。レビュワーが Reject(拒否)/Submit(承認)を判断する。 matran6.png

自分で翻訳ファイルを適用する場合

翻訳ファイルは毎週 master にマージされ、最新版が含まれた状態でリリースされるため、基本的に自分で動作している Mattermost に最新の翻訳を適用することは無いと思いますが、緊急で特定のメッセージを翻訳しなきゃいけない場合のために。

Pootle サーバーにて翻訳済みのメッセージは Pootle 画面からダウンロードできます。 matran7.png

Pootle サーバからダウンロードできるファイルは.poというファイルなのですが、実際のシステムで使用するためには.poファイルを.json形式に変換する必要があります。 変換にはrodrigocorsi2/mattermosti18nを使用するようです。

なんとなく、TravisCI で.jsonファイルまで生成できるリポジトリkaakaa/mattermosti18nを作ってみましたが、最新の翻訳データを使いたいと思ったことが無いので使っていません。 (英語なら英語のままで良いやと思ってしまう)

翻訳する時に気をつけていること

気をつけてはいますが、なかなか統一できないことも多々。。

ローカライズに参加してみて

成果

感想

comments powered by Disqus