コードに直書きされた文字列が多言語対応を静かに妨げる理由と外し方
ソースコードの中に、関数のどこかに引用符で直接書かれた文字列は、書いている本人には無害に見えます。コンパイルは通り、動作し、意図した通りのテキストが表示されます。問題が表面化するのは後になってからで、ゲームを多言語対応しようとしたときに、コードに埋め込まれたテキストは書き出せず、数えられず、コードベースごと渡さない限り翻訳者に渡すこともできないと分かった時点です。
コード直書きがパイプライン全体を止める理由
多言語対応のツール群 — スプレッドシートであれ、翻訳管理用のファイルであれ、自動書き出しの仕組みであれ — は、決められた場所からテキストを取り出す前提で動きます。リソースファイル、データベースのテーブル、構造化された書き出しデータなどです。任意のソースコードの中を覗いて文字列を見つけることはできません。コードを読むだけでは、ユーザーに見えるテキストなのか、ログ出力なのか、デバッグ用のラベルなのか、内部の定数なのかを安全かつ確実に見分ける方法がないからです。
つまり、コードに直書きされた文字列は、誰かが手作業で見つけ出し、パイプラインが見える場所に移すまで、実質的に多言語対応プロセスからは見えない存在になります。コードベース全体に対してこれを後から行うのは、最初から一つひとつの文字列を書く時点でやっておくよりも、遅く、間違いが起きやすい作業です。
テキストをキー付きリソースファイルへ移す
標準的な解決策は文字列の外部化です。使う場所に直接テキストを書く代わりに、リソースファイル(JSON、CSV、文字列テーブルなど — 形式そのものより、それを徹底する規律のほうが重要です)に安定したキーを付けて保存し、コードからはそのキーを参照します。コードはキーでテキストを要求し、実際に翻訳者と書き出しパイプラインが触れるのはリソースファイルだけになります。
// Before: どの多言語対応ツールからも見えない文字列
showMessage("ゴールドが足りないため購入できません。");
// After: コードはキーを参照し、テキストはリソースファイルに置く
showMessage(t("shop.error.insufficient_gold"));
// strings/ja.json
{
"shop.error.insufficient_gold": "ゴールドが足りないため購入できません。"
}文字列連結は近道ではなくバグの温床
同じ問題のもう少し分かりにくい形が、個別に翻訳された断片を実行時につなぎ合わせて一つの文にすることです。「ゴールド」という単語を使い回し、「アイテム」という単語を使い回して文を組み立てる、一見便利なやり方ですが、語順や、そもそもその位置に単語が必要かどうかは言語によって異なります。個別に翻訳された断片から組み立てられた文は、翻訳者が語順を直すことができません。翻訳者には文全体ではなく、断片しか見えていないからです。
// 脆い例: 語順が連結の中に固定されてしまっている "You received " + itemName + " x" + count // 日本語の翻訳者はここで語順を直せない — // 見えているのは断片だけで、組み立てられた文全体ではないため
プレースホルダーによる組み立てに切り替える
解決策は、文全体を一つの単位として翻訳し、動的な値を挿入する位置をプレースホルダーで示すことです。翻訳者は文脈の中で文全体を見ることができ、自分の言語の文法に合わせてプレースホルダーの位置を動かせます。単語単体ではなく、文の構造そのものを翻訳する権限が翻訳者にあるからです。
// strings/en.json
{ "inventory.received": "You received {itemName} x{count}" }
// strings/ja.json — 語順が違っても問題ない:
// 断片ではなく文全体を翻訳者がコントロールしている
{ "inventory.received": "{itemName} を {count} 個手に入れた" }どこまで外部化すべきか
コードベース内のすべての文字列をこのパイプラインに通す必要はありません。内部向けのログメッセージ、開発者専用のデバッグ出力、設定用のキーはプレイヤーに見えるものではなく、翻訳ファイルに入れるべきではありません。そこに入れると、翻訳者が読み飛ばさなければならないノイズが増えるだけです。線引きはシンプルです。プレイヤーに見えるなら、キー付きで外部化する。開発者にしか見えないなら、コードに残す。
この規約はプロジェクトの早い段階で確立するほど、コストが安く済みます。何年も直書きの文字列が積み上がったコードベースに後から外部化を適用するのは、実際に数週間規模のエンジニアリング作業になります。プロジェクトが最初のUI文字列を書く時点から徹底しておけば、コストはほとんどかかりません。