1本のファンアプリを雛形にして、グループ違いで4本に増やした。どれも20以上の言語を持っている。ある日、台湾のユーザーが10人から2人に減っているのに気づいて中身を数え直したところ、7,542の表示枠が英語のまま出ていた。誰も気づいていなかったのは、このバグが一度も落ちないからだ。
ファイルの数は、4本ともきれいに揃っていた
翻訳はロケールごとに1ファイル持つ。4本を並べると、どれも21ファイルだった。数が同じなので、ファイル一覧を見るかぎりは何の問題も無い。実際、この揃い方をもって「4本とも同じ状態だ」と扱っていた。
中を開いて、英語版にあるキーが各ロケールに何個入っているかを数えると、様子が変わる。「全枠」は英語のキー数 × ロケール数で、そのアプリが本来埋めるべき翻訳の総数だ。
| アプリ | ロケール | 英語のキー | 全枠 | 埋まっている |
|---|---|---|---|---|
| BLINK | 21 | 299 | 6,279 | 6,279(100%) |
| ARMY | 21 | 326 | 6,846 | 4,398(64%) |
| STAY | 21 | 326 | 6,846 | 4,398(64%) |
| CARAT | 21 | 310 | 6,510 | 3,864(59%) |
埋まっていない枠の合計は7,542。内訳はARMYが2,448、STAYが2,448、CARATが2,646で、BLINKだけが0だった。英語・日本語・韓国語は4本とも埋まっている。欠けているのはそれ以外の言語で、アラビア語・ベンガル語・ドイツ語・スペイン語・フィリピノ語・フランス語・ヒンディー語・インドネシア語・イタリア語・ポーランド語・ポルトガル語・ロシア語・タイ語・トルコ語・ウクライナ語・ベトナム語が、そろって半分ほど欠けていた。
落ちないので、テストでは絶対に出ない
翻訳が無いキーがあると実行時に落ちる、と思っていた。実際は落ちない。生成器は、翻訳が見つからないキーを英語の値で埋めたクラスを吐く。ドイツ語のファイルを開くと、こう書いてある。
この挙動そのものは正しい。訳が無いときに空白を出すより、英語を出すほうがましだ。困るのは、それが「訳が無い」という事実を隠してしまうことのほうにある。ビルドが通ることも、テストが緑であることも、翻訳が揃っている証拠にはならない。
生成そのものが、黙って失敗していた
繁体字(台湾)を4本に足したときに、もっと分かりにくい形の失敗を踏んだ。翻訳ファイルは4本すべてに置けたのに、1本だけ画面が繁体字にならない。生成物を見ると、繁体字のクラスがそもそも作られていなかった。生成器を手で走らせると、こう言われた。
ややこしいのは、その属性が付いたままでも翻訳ファイル自体は問題なく書き込めていたことだ。フォルダに読み取り専用が付いていても、中に新しいファイルは作れる。だから「ファイルは置けた」という手応えだけが残り、生成が動いていないことに気づけない。属性を外して生成し直したら、その場で通った。
この失敗の後に残る状態が悪い。翻訳ファイルは21個そろっていて、生成物も前回のものが残っている。ファイルの一覧も、更新日時を見ない限りは自然に見える。実機で言語を切り替えれば5秒で分かるが、一覧を眺めているだけでは永久に分からない。
名前を直すのと、中身を直すのは別の作業
雛形から複製したので、前のグループの痕跡も探した。メンバー紹介文のキーは、雛形のグループのメンバー名でそのまま付いている。4本を並べると、直し方が3通りに割れていた。
| アプリ | キー名 | 本文 | 画面での使用 |
|---|---|---|---|
| BLINK | 削除済み | 削除済み | — |
| ARMY | 残る | 残る | 15箇所で使用(正しい) |
| STAY | 残る | 差し替え済み | 0箇所 |
| CARAT | 残る | 残る | 0箇所 |
雛形になったアプリは、キーも本文も正しく、15箇所で実際に使われている。1本はキー名だけ残して本文を差し替えてあった。問題はもう1本で、キーも本文も雛形のまま残り、しかも画面からは1箇所も参照されていない。使われていないので表示上は何も起きないが、文字列としてはアプリの中に入って出荷される。固有のフレーズで数えると、21言語のうち21言語に1つ、13言語に別の1つが残っていた。
では何を見れば見つかるのか
今回の4件は、どれもビルドと静的解析を素通りしている。実際に見つけられた手順だけを書く。
- ファイルの数ではなく、キーの数を数える。ロケールごとに、英語のキーがいくつ定義されているかを出す。数分で書けるスクリプトで、7,542枠はこれで出た。
- 生成物のほうを読む。翻訳ファイルではなく、生成された各言語のコードを開いて、英語の文字列が混ざっていないかを見る。翻訳ファイルだけを見ていると、生成が止まっていることに気づけない。
- 生成物の更新日時を見る。「生成し直した」と「生成し直せた」は別のことで、日時を見れば区別がつく。今回は10日前のままだった。
- 前のグループの固有名詞で全ファイルを検索する。グループ名だけでは足りない。メンバー名、事務所名、そのグループにしか通じない愛称まで含めて、翻訳ファイルと生成物の両方を検索する。
4つに共通しているのは、どれも「揃っているように見える形」で壊れていることだ。ファイル数は同じ、ビルドは緑、画面も落ちない。数が合っていることは、中身が揃っていることの証明にはならない。数えるものを1段階下げるだけで、見えるようになる。
この記事に関係するページ
記事で触れた機能はこちらから試せます。

