実装Read this article in English

成長に耐えるストリングキー設計

ローカライズ用のキーは、それを最初に書いたコードよりも長く生き続けるメタデータです。テキストは書き直され、機能は名前を変え、ファイルは再構成されますが、キーは通常「安定していなければならない唯一のもの」です。翻訳メモリもレビュー履歴も、下流のツールすべてがキーを軸に紐づいているからです。文字列が200件の段階では些細に見える命名判断が、20,000件になると高くつきます。

階層的な名前空間

フラットなキー一覧はスケールしません。2つの機能がそれぞれ「title」や「confirm」というキーを欲しがれば衝突しますし、そのキーがどこで使われているかも一目ではわかりません。画面やシステムでキーを名前空間分けすれば、両方の問題を同時に解決できます。

menu.settings.audio.masterVolumeLabel
menu.settings.audio.muteButton
shop.item.buyConfirm

安定したIDと原文由来のキーの違い

一部のシステムでは原文そのものからキーを生成します — 英語の「Continue」という文字列自体がキーになる、という方式です。導入は速いのですが、特有の壊れ方をします。英語のテキストがわずかにでも変わると、キー自体が変わってしまい、意味は変わっていないにもかかわらず、そのキーに対する既存の翻訳がすべて宙に浮きます。

任意の安定したID(menu.continueButton)を使えば、キーと原文テキストを切り離せます。英語の文言を推敲したり修正したりしても、他言語の翻訳は無効になりません。そのキーの値だけを再レビューすればよく、翻訳メモリのマッチも引き続き有効です。

キーに文脈を埋め込む

同じ英単語でも、使われる場所によって求められる訳が異なることがよくあります。ボタンラベルと、同じ単語を含む完全な文は互換ではなく、多くの訳し先言語ではこの違いが語調や文法上の差として現れます。使用文脈をキー名に埋め込んでおけば、翻訳者が推測に頼らずに済みます。

  • shop.buyButton — 短く命令形、幅の決まったボタンに収まる
  • shop.buyConfirmSentence — 確認ダイアログ内の完全な文
  • tutorial.buyHint — プレイヤーに直接語りかける指示口調

1つのキーを2つの意味で使い回さない

キー設計で最も高くつく間違いは、意図する意味が異なる2箇所で1つのキーを使い回すことです。英語は文脈をまたいで同じ単語を使い回すことに、他言語より寛容な言語です。メニューの見出しの「Level」と、ゲームの「ステージ」を指す「Level」は、英語ではどちらも同じ単語ですが、多くの訳し先言語では別の単語になります。両方が1つのキーを共有していれば、翻訳者は1つの訳しか入れられず、どちらかの文脈は構造的に間違えることになります。これは翻訳ミスではなく、実在する区別を翻訳者から隠してしまった設計のミスです。

この修正は設計段階なら安く、事後になるほど高くつきます。現在の英語の値がたまたま同じであっても、論理的に異なる2つのUI文脈の間でキーを共有しないこと。訳し先言語のどこかで訳が分かれる可能性があるなら、今日の英語の値が同一であっても、2つのキーを用意してください。

後からのリネームとそのコスト

キーの後からのリネームは無料ではありません。多くのシンプルなエクスポート/インポートのパイプラインは履歴を明示的に引き継がないため、リネームは旧翻訳と新キーの結びつきを断ち切ります。リネームの実態はこうなりがちです — 旧キーの翻訳が消え、再翻訳されるまで各言語がフォールバックまたは英語のテキストを表示し続ける。これはスプレッドシートのレビューでは見えず、ゲーム内では非常に目立ちます。

だからこそ、名前空間と文脈の設計は、たとえ粗くても早い段階で決めるべきです。翻訳者がすでに旧名で履歴を積み上げた後にフラットな命名から500件のキーを移行するより、最初からmenu.settings.audio.masterVolumeLabelのように始めるほうがはるかに安く済みます。

関連記事