チェック・トラブル対処Read this article in English

あるツールでは正常、別のツールでは文字化けするCSVの正体

翻訳者が表計算ソフトでCSVを開いて何行か編集し、送り返してきたファイルを取り込んだら文字化けした。あるいは逆に、パイプラインが書き出したCSVを誰かがダブルクリックしたら文字化けして見えた。どちらも根っこは同じで、プレーンなCSVにはエンコーディングを示す情報が一切含まれておらず、開くツールごとに推測に頼るしかないため、日本語ロケールの環境では推測結果がツールによってバラつくのが原因です。

なぜプレーンCSVはレガシーなエンコーディングに寄ってしまうのか

CSVファイルは単にカンマ区切りのバイト列であり、フォーマット自体にはそのバイト列がどのエンコーディングかを示す情報がありません。日本語ロケールのOS環境では、UTF-8が今日のような事実上の標準になるずっと前から、表計算ソフトがプレーンCSVの読み書きにShift_JIS、より正確にはMicrosoftによるその拡張であるCP932を使ってきた歴史があります。

その既定挙動は完全にはなくなっていません。そうした環境の表計算ソフトから、他に手がかりのない状態で保存されたCSVは、いまだにUTF-8ではなくCP932で書き出されることが珍しくありません。現代のコードやローカライズ用ツール、Webベースのツールの多くはUTF-8を前提としているため、そのまま読むと非ASCII文字がすべて文字化けします。

UTF-8のBOMが挙動を変える理由

BOM(バイトオーダーマーク)は、ファイルの先頭に置かれる特定のバイト列で、そのファイルのエンコーディングを示す目印です。UTF-8の場合はEF BB BFという3バイトで、これ自体は目に見える文字には対応しておらず、次にファイルを読むソフトへの手がかりとしてのみ存在します。

日本語ロケールの表計算ソフトは、多くの場合この目印を認識します。先頭がEF BB BFで始まるCSVはUTF-8として正しく開かれる一方、まったく同じ中身でもBOMがなければレガシーなCP932の想定にフォールバックします。「CSVの互換性を保つならUTF-8のBOMを付けろ」という助言が繰り返し言われるのはこのためで、これは飾りではなく既定挙動を切り替える唯一の合図です。

ただしトレードオフもあります。すべてのツールがBOMを想定しているわけではなく、ファイルを厳密にデータとして扱うパーサーは、先頭の3バイトを除去せずに1セル目の内容の一部として読み込んでしまい、最初の列見出しに余計な文字がくっついたように見えることがあります。BOMを付けるかどうかは、ファイルをやり取りする双方のツールの前提を確認した上で決めるべきで、一律の既定にはできません。

表計算ソフトでの保存が黙ってエンコーディングを変えてしまう

翻訳の往復作業で特にはまりやすいのがこのケースです。パイプラインからBOM付きUTF-8のCSVを書き出し、翻訳者がそれを開いて何セルか編集して保存します。選んだ保存形式やソフトの既定値次第で、戻ってきたファイルはUTF-8ではなくなっていることがあります。CP932として黙って再保存され、最初に付いていたBOMも失われることがあり、その変化を知らせる画面上の警告は一切出ません。

この往復作業のどこにも、翻訳者から見て間違って見える箇所はありません。ソフトはファイルを正しく開き、そのシステム上でCSVとして「普通」とみなす形式で保存しただけです。破損が見えるようになるのは受け取った側だけで、想定していたエンコーディングでインポーターが読み込んだ瞬間に文字化けとして現れます。

往復編集に耐える安全な運用方法

最も確実なのは、パイプラインの外で編集されるファイルにプレーンCSVをそのまま使うのをやめることです。

  • ツール側が直接読めるなら、人間が編集する工程には表計算ソフト固有の形式を使う。そちらはエンコーディングや書式の情報を自身のファイル内に明示的に持っているため、どちらの側も推測する必要がない。
  • CSVが必須の場合は、表計算ソフトを経由することが分かっているファイルにはUTF-8のBOMを意図的に付けて書き出し、取り込み側がそれをコンテンツではなく除去すべき目印として正しく処理できているか確認する。
  • 取り込み時にエンコーディングを決め打ちしない。BOMの有無や軽量なヒューリスティック判定で明示的に検出し、どのファイルをどのエンコーディングとして扱ったかをログに残す。そうすれば、黙った再保存が3工程後の文字化けではなく、その場で見えるログの1行として現れる。
  • システム間の受け渡しはすべてエンコーディングの境界とみなし、その境界で検証する。全角・半角文字を含むサンプルで実際に往復させるテストを一度行うだけで、この種の不具合を本番のテキストに届く前に発見できる。

関連記事