実装Read this article in English

翻訳ファイルの整理術 — 命名、構成、そしてマージコンフリクトを決めるもの

翻訳ファイルは、アプリケーションコードほど設計レビューの対象になりませんが、どう整理するかには現実的な影響があります。差分がどれだけ読みやすいか、並行して作業する翻訳者同士がどれだけ衝突するか、ある言語に文字列が抜けているかをどれだけ簡単に判別できるか。こうした問題の多くは、後からではなく、ファイル構成を選んだ時点で決まってしまいます。

言語ごとに1ファイル、機能ごとに1ファイル

よくある構成は二つあります。一つは言語ごとに1ファイルにする方法で、en.jsonに英語のすべての文字列、ja.jsonに日本語のすべての文字列、というように分けます。もう一つは機能や画面ごとに1ファイルにする方法で、checkout.jsonの中にenとjaのキーが両方入っている、といった形です。

言語ごとに1ファイルにする方式は、翻訳者に渡すのがシンプルです — 翻訳に必要なものが全部入った1ファイルだけを渡せば済みます。機能ごとに1ファイルにする方式は関連する文字列をまとめておけるため、アプリが大きくなるほどスケールしやすくなります。チェックアウト画面への変更がcheckout.jsonだけで完結し、言語ファイルすべてを編集する必要がないからです。多言語で規模の大きいプロジェクトほど、変更を局所化できるという理由で機能ごとの構成に寄っていく傾向があります。言語数が二つか三つの小さなプロジェクトでは、どちらでもそれほど困らないことが多いです。

言語タグを使った命名規則

どちらの構成を選ぶにせよ、ファイル名には独自の略称ではなく標準の言語タグを使うべきです。BCP 47のタグ(en、ja、pt-BR、zh-Hantなど)は、多くのツールやブラウザ、プラットフォームがすでに前提としている形式なので、ja.jsonやpt-BR.jsonという名前は人間にもソフトウェアにも一意に伝わります。japanese.jsonやjp.jsonという名前は、標準タグを期待するライブラリに出会うまではうまく動きますが、そこで通じなくなります。

地域サブタグは、pt-BRとpt-PTのように語彙や綴りが実際に異なる地域変種がある場合に意味を持ちます。そうした違いが不要な言語にまで習慣的に地域サブタグを付ける必要はありません — 誰も参照しない層が増えるだけです。

locales/
  en.json
  ja.json
  pt-BR.json
  zh-Hant.json

原文言語の置き場所

どのプロジェクトにも、文字列が最初に書かれる言語 — 通常はプロダクトが設計されている言語 — が一つあります。この原文ファイルは明確で曖昧さのない位置づけを持つべきです。開発者はまずここでキーを追加・編集し、他のすべての言語ファイルはこれの翻訳として理解されるべきで、独立した文書として扱われるべきではありません。

原文ファイルを特別扱いせず、単なる「もう一つの言語ファイル」として扱うと、乖離が起きやすくなります。原文以外のファイルにだけ追加されて他のどこにも存在しないキーができたり、どちらも参照にならないためにキーの意味そのものが二つの言語ファイル間で食い違ったりします。

キー順序の安定性が差分を読みやすくする

多くの翻訳ファイル形式は、キーの順序を特に要求しません。つまりツールやエディタが保存のたびにファイル全体をアルファベット順に並べ替えたり、好きなように並び替えたりすることが可能です。それが起きると、一つの文字列を追加しただけの変更が、周囲の行がすべて移動したせいでファイル全体に及ぶ差分になってしまいます。

キーの順序を安定させること — 新しいキーは末尾に追加する、または保存のたびに並び替えず機能ごとに固定した順序でグループ化する — によって、差分は実際に変更された行だけを示すようになります。これは小さな規律ですが、コードレビューでは丸ごと報われます。レビュアーは、移動しただけの大量の行の中から重要な一行を探すのではなく、追加・削除・編集のどれかを一目で判別できます。

  • 順序のルール(アルファベット順、または機能ごとのグループ化)を一つ決めて意図的に守る
  • 自動整形ツールは並べ替えではなく、その順序を維持するように設定する
  • 可能な限り、新しいキーは途中に挿入せず末尾に追加する

構成がマージコンフリクトをどう左右するか

複数人が同時に別々の言語へ翻訳している場合、言語ごとに1ファイルにする構成は、各人が別のファイルを編集することになるため翻訳者同士の衝突を自然に避けられます。ただし、開発者が原文ファイルにキーを追加するのと、翻訳者が同じファイル内の無関係な文字列を編集するのが同時に起きることまでは防げません。

機能ごとに1ファイルにする構成は逆のトレードオフを持ちます。すべての言語が同じファイルに同居していると、同じ機能を別言語で翻訳している二人の翻訳者が同じファイルに触れることがあります。一方で、開発者のキー追加と翻訳者の文言修正は、対象が十分に狭いファイルに収まりやすいため、めったに重ならなくなります。どちらの構成もコンフリクトを完全にはなくせません。目指すべきは、実際に起きるコンフリクトが解決しやすい種類のものになる方を選ぶことです。

関連記事