翻訳ファイルがズレるのは、2つのシステムが同じデータを所有していて、どちらも決定権を持たないためです。リポジトリは開発者がマージしたときに変わります。翻訳ファイルは誰かが更新を思い出したときに変わります。これらは異なる時計で動いており、その間にある隙間こそが、欠落キー、孤立キー、古びた文字列が生まれる場所です。globalize.nowはAIを活用したローカライゼーション基盤で、コードが書かれるその場でキーとロケールファイルを生成することで、この隙間を閉じ、追いつくべき「もう1つの時計」自体が存在しなくなるようにします。
ロケールファイルが同期を失う本当の原因は何ですか?
1つのファイルは「執筆」され、残りは「保守」されている――そしてこれらは同じ仕事ではありません。
機能を実装する開発者はen.jsonを編集します。なぜなら、その文字列が入っていく先のファイルだからです。他のロケールは、別の人が別のスケジュールで対応する問題になります。この現象についてDEV上で書いた開発者は、2つの失敗パターンを説明しています。1つは、キーが英語ファイルに追加され、他のファイルでは忘れられてしまい、アプリの一部が黙って英語表示にフォールバックしてしまうパターン。もう1つは、あるロケールでキーが削除されても別のロケールには残り続け、使われない項目が積み重なっていくパターンです。どちらの場合も、発覚のきっかけは数週間後の顧客からの問い合わせです。
どちらも翻訳の問題ではありません。誤訳は一切ありません。文字列がそもそもどこにもルーティングされていなかっただけです。
これは、どんなツール更新でも消えない失敗モードです。なぜなら、ツールは文字列が生成された地点よりも下流に位置しているからです。文字列がそもそもパイプラインに入らないなら、より良いパイプラインを用意しても意味がありません。同じ根本原因は、コーディングエージェントがそもそもキー化されなかった文字列を書いてしまうという、もっと上流の段階でも現れます。
ロケールファイルはなぜこれほど多くのマージコンフリクトを生むのですか?
それは、機械が書くために作られたフォーマットの「生成データ」を、人間が手で編集しているからです。
ロケールファイルは、キーと文字列の平坦なマップです。ある機能を追加する2つのブランチは、どちらもそのマップに追記します。しかもたいてい同じ位置、たいてい同じアルファベット順の近所です。Gitからは、意味的な構造を理解できないファイルの隣接行に対する2つの編集にしか見えず、人間に解決を求めることになります。
対応する開発者は、翻訳先の言語を読めない人間であることが多いです。安全な方法は両方を残すことで、これが重複キーを生む原因になります。速い方法は片方だけ残すことで、これが翻訳を静かに消し去る原因になります。
ロックファイルのコンフリクトを手作業で解消する人はいません。再生成するだけです。ロケールファイルも、人間が手で書くドキュメントでなくなった瞬間から、同じ扱いを受けるべきものになります。
レビュー待ちの間に、翻訳はどれくらい古くなってしまうのか?
製品の実態を説明できなくなるほど古くなる。しかもこれは公開データで確認できる。
DevOps.comに掲載されたフィールドレポートでは、オープンソースプロジェクトにおける実際のローカライゼーションPR(プルリクエスト)を5件追跡している。特に示唆に富むのがKilo CodeのPR #8377だ。自動チェックは問題なく通過したが、メンテナーによるレビューが遅れて到着した頃には、リポジトリ側の構造がすでに変わってしまっていた。結局このPRはクローズされ、最新のアーキテクチャに対して出し直すよう案内された。同じレポートには、OpenClawのIssueで、スペイン語・日本語・ポルトガル語・韓国語・中国語・ベトナム語の翻訳をボランティアが提供したものの、メンテナー側に取り込む仕組みがなかったという記録もある。
これらは品質の問題としてではなく、遅延(レイテンシー)の問題として読むべきだ。翻訳は書かれた時点では正しかった。待機している間にインターフェースの方が変わってしまったのだ。
これは、ローカライゼーションツールを比較する際に誰も値段をつけないコストだ。誰もが翻訳の質は測る。だが、文字列が受け渡しの途中でどれだけ時間を費やしたか、その間にインターフェースがどう変わったかを測る人はほとんどいない。
この往復(ラウンドトリップ)には実際どれだけコストがかかっているのか?
翻訳そのものより、調整作業にかかるコストの方が大きい。だからこそ、請求書にはその痛みが決して記されない。
目に見えるコストは単語単位、キー単位、あるいは席(シート)単位で、月に一度請求書に現れる。目に見えないコストは、「どのファイルを編集すればいいのか」と尋ねる開発者、読めない言語のコンフリクトを解消する羽目になる別の開発者、ドイツ語ビルドに11個のキーが欠けていることに気づく三人目、そして5週間前に自分が書いた文字列について今さら質問される元の機能担当者だ。
これらは一切、価格比較には出てこない。しかし、そのすべてが毎スプリント、開発者の時給レートで支払われている。表示価格が安くても、エンジニア二人分の一日を毎週食いつぶすツールは、決して安くはない。
そのコストを生み出しているのが、この往復そのものだ。文字列が生まれる場所と、翻訳される場所との間でファイルを移動させる工程こそが高くつくステップであり、それはどこから購入しようと変わらない。だからこそローカライゼーションは開発ループの上流へと移動し続けているのだ。
コードが書かれるその場所でキーが生成されるようになると、何が変わるのか?
二つ目の時計が消え、ズレ(ドリフト)そのものが発生しようがなくなる。
従来の流れ――開発者がハードコードされた文字列を書く、誰かが後からそれを見つける、誰かがキー化する、誰かがファイルを外部に送る、誰かが翻訳する、誰かがそれを持ち帰る――はもう不要になる。代わりに、文字列は機能の実装と同じコミットの中で、値を伴ったキーとしてその場で書かれ、翻訳はそこから自然に続いていく。
globalize.nowでは、これは一度きりの変換作業から始まる。アプリでリポジトリを接続すると、既存のハードコードされた文字列が一括でキーとロケールファイルに抽出される。その後は、エージェントスキルによってCursorやClaude Codeといったコーディングエージェントが、最初からハードコードではなくキー化された文字列を書くようになり、プッシュジョブが新しく現れたカタログの単位を随時翻訳していく。
重要なのは「一度だけ」という点だ。変換作業こそが最も大変な部分であり、それは一度で終わる。その後に続くのは、かつては手作業だった部分が、コードと同じ時計の上で動くようになったものであり、それをそばに置くのではなく開発者のワークフローの中に組み込むことにこそ意味がある。
ランタイムライブラリには影響しない。i18nextやnext-intlは、これまでと全く同じようにロケールファイルを読み込む。翻訳がどう配信されるかは何も変わらない。変わるのは、そのファイルを誰が書くかということだけだ。
ドリフトと本物の翻訳の問題を、どう見分ければいいのか?
その文字列を、そもそも翻訳者が目にしたことがあるかどうかを確認すればいい。
ドイツ語ファイルにキーが欠けているとして、それは翻訳者の失敗ではない。その文字列は、そもそも翻訳者のもとに届いていないのだ。これはルーティングの失敗であり、レビュー工程を増やせば、すでにレイテンシーが問題であるプロセスに、さらに待ち時間を積み増すだけで事態は悪化する。
一方、ドイツ語ファイルにキーは存在していて、文脈に対して言葉選びが誤っているのであれば、それは正真正銘の翻訳の問題であり、ドイツ語を話し、その文字列が実際にどこに表示されるかを確認できる人間にこそ対応してもらう価値がある。そこにかける時間は無駄にはならない。
多くのチームは、後者よりも前者の方が圧倒的に多いにもかかわらず、両者を同じ問題として扱っている。だからこそローカライゼーションは終わりのない作業に感じられる。両者を切り分ければ、作業量そのものが減る。なぜなら、ルーティング側の作業はそもそも人間の仕事ではなくなるからだ。この区別はチームが小さいほど重要性を増し、だからこそ高速に開発を進める個人開発者や少人数チームにとって特に顕著な問題として現れる。
有用なチェック方法がある。直近10件のローカライゼーション関連のバグのうち、「言葉が間違っていた」ものと「言葉がそもそも存在しなかった」ものの割合を数えてみるといい。もし大半が後者、つまり欠落であれば、それは翻訳の問題ではない。配管(プラミング)の問題だ。そして配管は、判断力とは違って自動化できる。この論理は、ローカライゼーションに実際いくらかけるべきかを考えるときにも同じように当てはまる。
ロケールファイルのドリフトは、翻訳の問題の顔をしたルーティングの問題だ。リポジトリを一度接続してしまえば、ルーティングはもうあなたの仕事ではなくなる。
globalize.nowは、ハードコードされたアプリ内テキストを翻訳可能なロケールファイルに変換し、リリースのたびに自動で最新の状態を保ちます。
globalize.nowを無料で試す