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

はじめに

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