個人開発Read this article in English

スプレッドシートでゲーム翻訳を管理する:列設計から書き出しまで

文字列が数千行あり、翻訳者は一人か二人、翻訳支援ツールに払う予算はない。誰かが共有スプレッドシートを提案し、別の誰かが「それは素人くさい」と言い、結局ツール選びで一週間止まって一行も訳されない、という状況はよくあります。

スプレッドシートで問題ありません。小規模なゲームで対応言語が少ないうちは、むしろ他の選択肢より優れていることが多いのです。関わる全員がすでに持っていて、すでに使い方を知っている唯一のツールだからです。破綻するのはスプレッドシート自体ではなく、既定の使い方のほうです。三列しかなく、誰が何を編集してよいかの取り決めがなく、書き出し手順を本番当日まで誰も試していない、という使い方です。

この記事では、実務に耐える形を示します。列をどう設計するか、腐らせずに共有するには何を固定するか、スプレッドシートにテキストを壊されずに書き出すには何を見るか、回を重ねたときに変更をどう追跡するか、そしていつ卒業すべきかです。

小規模チームではいまでも正解であり続ける理由

利点は本物なので、はっきり書いておきます。しばらくツール導入を我慢する理由になるからです。翻訳者はインストールもアカウント作成も研修もなしに開けます。二人が同時に作業して互いの動きが見えます。コメント機能があるので、ある行についての質問がメールのやりとりではなくその行の隣に残ります。変更履歴があるので失敗しても戻せます。絞り込みと並べ替えができます。この規模のプロジェクトで翻訳ツールが実際にやっていることの大半は、これで足ります。

限界についても正直であるべきで、始める前に知っておく価値があります。スプレッドシートには、キーが一意であるという概念も、原文にあるプレースホルダーが訳文にもあることを保証する仕組みも、前回似た行をどう訳したかという記憶もありません。マージもできません。二人が同じセルを編集すれば、どちらか一方が黙って勝ちます。そしてバージョン管理の外側にあるので、ゲームがビルドに使うファイルと、人が編集しているファイルは別物になり、手作業で突き合わせる必要があります。

実務上の境界はおおむねこうです。言語が数言語まで、同時に作業する人が数人まで、翻訳が常時ではなく週単位の「回」で進む規模なら、スプレッドシートはうまく機能します。それを超えると、突き合わせの作業量が翻訳の作業量より速く増えていきます。それが移行の合図です。

列を設計する

スプレッドシート運用の失敗の多くは、シートが三列しかないことに行き着きます。キー、原文、訳文。それ以外の情報を書く場所がありません。追加の列は形式主義ではなく、どれも「メールで何度も同じことを聞かれたから」存在します。

言語ごとにタブを分けるのではなく、一枚のシートに言語ごとの列を置いてください。言語別タブはキー列と原文列を複製することになり、それらはやがてずれていきます。ある行がどの言語で欠けているかも一目で分かりません。1行=1文字列、1列=1言語、そのほかの列はその行を説明するもの、という形にします。

  • key — 自分以外は編集しない列。別の意味に使い回さない
  • context — その行が何で、どこに出て、誰が言い、どんなトーンかの説明。シートの中で最も価値の高い列です
  • max — 決まった枠に収める必要がある文字列の上限文字数。不要な行は空欄に。上限を知っている翻訳者はその範囲で書きます
  • 原文と訳文の言語列 — 言語ごとに一列、順番は常に固定
  • 言語ごとの状態列 — 運用はここに宿ります。二回目以降の翻訳を可能にするのはこの列です
  • 備考・質問 — テキスト本体を編集せずに翻訳者が指摘を残せる列を一つ
key            | context                  | max | ja        | en               | en_status
shop.buy       | ボタン。ショップの一覧内     | 8   | 購入        | Buy              | reviewed
shop.noGold    | 購入失敗時のトースト        | -   | ゴールドが足りません。| Not enough gold. | translated
boss2.taunt    | 3章ボスのセリフ。傲慢な口調  | -   | もう一度どうぞ。   |                  | new
item.potion.d  | アイテム説明。%n%=回復量    | -   | HPを%n%回復。 | Heals %n% HP.    | question

腐らせずに共有する

共有シートを使い物にし続ける唯一のルールは、原文とキーは自分のもの、訳文は相手のもの、という切り分けです。翻訳者が原文の誤字や曖昧さを見つけても、シート上で直してはいけません。コメントか備考に残し、自分が直します。原文の変更は、他のすべての言語列に波及する結果を持ち、それが見えるのは自分だけだからです。

これは人間関係ではなく構造で担保してください。キー・context・原文の列を保護して共同編集者からは読み取り専用にし、言語列だけ編集可能にします。アクセス権は必要な人にだけ与え、翻訳ではなくレビューをする人にはコメントのみの権限を使います。状態列は入力規則でドロップダウンにして、その日その人が打った文字列ではなく決まった値しか入らないようにします。自由入力の状態列は二週間で使い物にならなくなります。

もう二つのルールが、意外なほどの苦痛を防ぎます。行の追加と削除は自分以外がしないこと。並び替えられたシートに行が挿入されるのは、訳文が別のキーに紐づく典型的な事故です。そして、他人に影響する形での並べ替え・絞り込みをしないこと。共同編集者にはフィルタ表示の使い方を教えてください。自分の表示だけが変わり、他の人のシートを並べ替えてしまうことがありません。

変更履歴が取り消し機能です。多くの人が思っているより強力で、どのセルを誰がいつ変えたかを見られますし、ファイル全体を以前の状態に戻せます。大きな操作の前 — 一括貼り付け、並べ替え、取り込み — には名前付きのバージョンを作っておくと、戻る先が明確になります。

壊さずに書き出す

スプレッドシートに噛まれるのはここです。このアプリは数値に対して親切になるよう作られていて、その親切さはテキストに対しては破壊的に働きます。CSV や TSV に書き出したら、信用する前に次を確認してください。

セルの内容が等号・プラス・マイナスで始まっていると、テキストではなく数式として解釈されることがあります。ゲームのテキストでこれは思ったより起こります。ダメージ補正の表示、装飾としての矢印、謎解きのヒントに出てくる数式などです。誰かが貼り付ける前に言語列を書式なしテキストに設定しておけば変換を防げますし、他の自動変換も止まります。数値に見える文字列の先頭のゼロが消える、日付に見える文字列が実際の日付になる、桁の多い数字が指数表記に書き換えられる、といった変換です。

二つ目の危険が自動置換です。まっすぐな引用符が黙って曲がった引用符になり、ピリオド三つが三点リーダー一文字になり、ハイフンがダッシュになります。組版としてはそれが望ましい場合もあります。問題は、それが確認なしに、しかも一貫せずに起こることです。ファイルの半分が一方の文字、残り半分がもう一方の文字になり、置換後の字形を持たないフォントでは空の四角が出ます。作業開始前にアプリの設定で自動置換を切り、書き出したファイルでも確認してください。

残りは機械的ですが、チェックリストにする価値があります。セル内の改行は、引用符で囲まれた複数行のCSVフィールドとして書き出されます。規格上は正しいものの、一行ずつ読む素朴なパーサーは壊れます。自分の取り込み処理が対応しているのか、それとも改行はテキスト中の明示的な記号にすべきなのかを決めてください。行頭・行末の空白はセル上では見えませんがゲームでは意味を持ちます。取り込み時に落としてください。貼り付けた内容からノーブレークスペースが紛れ込むことがあり、見た目は通常の空白と区別が付きません。そしてセル内のカンマと引用符は、読み込む側が正しくクオート・エスケープを解釈する必要があります。ある行から先で列が一つずつずれて取り込まれるという定番の事故は、たいていこれが原因です。

何が変わったかを追う

一回目の翻訳なら、スプレッドシートは何の問題もなくこなします。設計のないシートが崩れるのは二回目以降です。問われる内容が「この行は何と書いてあるか」から「前回から何が変わったか」に変わるからです。

その大部分を担うのが状態列です。値の集合は小さく、曖昧さのないものにしてください。new / translated / reviewed / needs-update / question といった具合です。そして、決められた状態に到達した行だけをビルドに書き出す、というルールにします。これで未完成のシートも出荷可能なものになります。終わっていない行は空欄として出るのではなく、元の言語にフォールバックするからです。

難しいのは、訳し終わったあとに原文が変わった行です。この訳文は黙って間違いになります。見た目は完成していて、状態は reviewed で、内容はゲームがもうやっていないことを説明しています。軽量な対策は、訳した時点の原文のコピーを保持する列を作り、現在の原文と比較する数式を置くことです。食い違ったらその行は古くなっているので、状態を needs-update に倒します。この一列が、スプレッドシート運用で生まれる最も被害の大きい種類の誤りを捕まえます。

カットしたコンテンツの行を削除するのも我慢してください。削除ではなく removed の印を付けて残します。コンテンツは復活しますし、削除した行は訳文と履歴を道連れにします。行を消すのは、シートと書き出し結果の行数が合わなくなる原因でもあり、そうなった日の午後はろくなことになりません。

状態列の値(入力規則のドロップダウン)
  new          — 原文はあるが未翻訳
  translated   — 訳したが未確認
  reviewed     — 文脈の中で確認済み。出荷してよい
  needs-update — 翻訳後に原文が変わった
  question     — 保留。備考列を参照
  removed      — ゲームから外したが履歴として保持

卒業のタイミング

早く出ることに価値はありませんし、居座りすぎることにも価値はありません。移行すべき合図は好みの問題ではなく、具体的です。言語が数言語を超えてシートが横に広がりすぎ、読めなくなってきた。複数人が同時に編集していて、衝突した編集を手作業で解決している。同じ行が更新のたびに繰り返し出てきて、翻訳メモリが欲しくなった。手作業の書き出しではなく、ビルド処理が最新のテキストを自動で必要とするようになった。あるいは、シートを検証するスクリプトを自分で書き始めた。最後のものは、避けていたはずのツールを自分で作り始めた地点です。

早い段階の一つの判断が、その移行を安くします。初日からキー列を一意で安定したものに保つことです。スプレッドシートから出るどの経路 — 翻訳管理サービス、リポジトリ内のファイル、データベース — も、結局はキーからテキストへの対応付けです。キーがきれいなら、移行は半日で終わります。同一性を行の位置や原文そのもので担保していたなら、プロジェクト内の全文字列を人手で突き合わせることになります。設計の悪いシートの本当のコストは、それを最後に一度で支払わされることです。

関連記事