海外の反応を「要約せず原文つき」で載せるためのデータ設計
海外のフォーラムの投稿を翻訳して紹介するサイトを運用していると、最初にサボりたくなるのが原文と出典の保存だ。表示に使うのは翻訳文だけなので、翻訳文だけを持てば動く。動くのだが、あとから「この訳は正しいのか」「これは本当に実在の投稿なのか」を確認する手段が消える。
自分が運用しているアニメ海外の反応では、以前この失敗をしていた。データ 6,000 件すべてに原文も出典URLも無く、投稿者名は「海外視聴者A」のような生成値だった。一方でサイトの説明文と免責ページには「コメントを要約せず個別に翻訳して紹介する」「出典を明記する」と書いてあった。記述と実態がずれていたわけで、これは翻訳の質の問題ではなく誠実さの問題だ。
直し方は2通りある。記述を実態に合わせる(=「作例です」と書く)か、実態を記述に合わせる(=本当に翻訳する)か。後者を選んだので、そのためのデータ設計とビルド時のチェックをここに書く。
1件の反応が持つべきフィールド
要点は、表示に使わないフィールドを必須にすることだ。表示に使わないものは、必須にしておかないと必ず抜ける。
1 | |
text… 日本語訳。ページ本文に出るoriginal… 原文そのまま。折りたたみで併記するlang… 原文の言語sourceUrl… その投稿への permalink。スレッドの一覧URLでは不可handle… 出典元での表示名。架空名を作らないfetchedAt… 取得日
ここで効くのは sourceUrl の粒度だ。スレッドのURLだけを持つと、あとから「どの投稿だったか」を特定できない。MyAnimeList なら ?goto=post&topicid=…&id=… の形で投稿単位のURLが取れるので、それを保存する。1文字ぶんの手間で、検証可能性が保たれる。
運用ルールとしては「1つでも欠けるならその反応は載せない」にしてある。件数を埋めるために創作しない、というのが唯一の防波堤になる。
「取得できなかった日は書かない」を許す
このスキーマの副作用として、取得に失敗した日は0件になる。ここで「0件では寂しいから」と埋め始めると、元の状態に戻る。
なので運用側の判断基準を明文化した。取得できなかった日は、何を試して何が駄目だったか(試したURL・HTTPステータスまで)を記録して0件で終える。書かないことと、更新しないことは違うという整理で、記録さえ残れば翌日に打開できる。
壊れた参照を黙って落とさない
返信スレッドを表示するために、各反応は任意で id(安定した識別子)と replyTo(親の id)を持てる。ここが厄介で、replyTo が存在しない id を指していても、素直に実装すると返信表示が消えるだけで何も起きない。無言で機能が落ちるので、気づくのは数か月後になる。
対策として、索引を作る段階で重複を検出して警告するようにした。
1 | |
ctxLabel に「どの作品のどの話か」を入れておくのが実務上のポイントだ。警告文だけ出ても、6,000件の中のどこかでは直しようがない。
同じ考え方で、出典が複数あるページには初出順の通し番号を振っている。
1 | |
sourceUrl がある反応だけを数えるので、出典の無いデータが混ざっても番号を捏造しない。無いものは無いまま通すのが、この手の索引では正しい。
実際に試す
手元で確認するなら、上のスキーマで JSON を1つ作って、必須フィールドの検査だけ書けば十分だ。
1 | |
process.exit(1) にしてあるのが肝で、ビルドを止めないと結局そのまま公開される。警告を出すだけの検査は、無人で回している限り誰も読まない。
実際に出来上がったページはアニメ海外の反応で見られる。各コメントに「原文(EN)を表示」のトグルが付いていて、翻訳が気に入らなければ原文を確認できる。この状態にして初めて、サイトの説明文どおりのものになった。
書いていて思うのは、この手の設計は性能でも見た目でもなく、後から自分の書いたものを疑えるかどうかの問題だということだ。原文と permalink を持っていれば、3か月後の自分が検証できる。持っていなければ、信じるしかなくなる。