下書き・予約公開・多言語 — 運用しやすい公開フロー

深夜の公開作業をなくす予約公開と、AI翻訳による4言語展開の仕組み

予約公開下書き多言語AI翻訳キャッシュ更新
読了時間: 9分

はじめに

記事を書く機能ができても、それだけでは運用は回りません。「書きかけを保存しておきたい」「キャンペーン開始と同時に公開したい」「英語版も出したい」といった要望が、必ず出てきます。

この記事では、記事の公開にまつわる運用上の工夫を紹介します。地味な部分ですが、ここが使いにくいと運営者はコンテンツを更新しなくなってしまいます。

3つの状態で記事を管理する

下書き・公開・非公開

記事の状態は「下書き」「公開」「非公開」の3つを用意しました。

下書きと非公開を分けているのは、意味がまったく違うからです。下書きは「まだ出していない」、非公開は「出したけれど引っ込めた」。管理画面の一覧で区別できると、状況が把握しやすくなります。

予約公開は状態を増やさずに実現する

「4つ目の状態として『予約公開』を作る」という発想もありますが、今回は公開状態+未来の公開日時という組み合わせで表現しました。

公開日時が未来なら予約公開、過去なら公開中。これだけで済みます。状態を増やすと、状態遷移の組み合わせが増えて複雑になるので、既存の項目で表現できるなら、そのほうが安全です。

管理画面の一覧では、公開状態かつ日時が未来の記事に「予約公開」というバッジを表示して、運営者から見て分かりやすくしています。

日時は日本時間で扱う

日時の入力欄はブラウザの標準機能を使いますが、そのままだと利用者のパソコンの時刻設定に左右されてしまいます。海外から操作したら9時間ずれる、では困ります。

そこで入力された日時は必ず日本時間として解釈し、表示するときも日本時間に変換しています。運営者が「20時」と入力したら、日本の20時。当たり前のことですが、明示的に指定しないと崩れる部分です。

4言語をどう回すか

1つの画面で4言語を編集する

記事は日本語・英語・繁体字・韓国語の4言語で持てます。編集画面では言語ごとにタブを分けていますが、保存ボタンは1つだけです。

タブを切り替えても入力内容は保持され、保存すると4言語分がまとめて登録されます。言語ごとに保存ボタンがあると、「英語だけ保存し忘れた」という事故が起きやすくなります。

日本語のタイトルだけは必須にしました。逆に、ある言語のタイトル・要約・本文がすべて空なら、その言語の記事は削除されます。「英語版はやっぱり出さない」と決めたとき、空にするだけで済むわけです。

AI翻訳はボタンを押したときだけ

多言語対応の一番の負担は翻訳です。そこで管理画面に「AI翻訳を生成」ボタンを設け、日本語の記事から他の3言語を自動生成できるようにしました。

AI翻訳の流れ
日本語で記事を書く

まずは日本語版を完成させる

翻訳ボタンを押す

保存時に自動実行はしない。運営者が明示的に指示する

3言語を同時に生成

英語・繁体字・韓国語を並行して生成。1つ失敗しても他は完了する

内容を確認して保存

生成された文章は編集可能。おかしければ直してから公開

保存のたびに自動翻訳しない理由は2つあります。1つは費用。何度も保存するたびに翻訳が走ればAPI費用が積み上がります。もう1つは、手直しした翻訳が次の保存で上書きされてしまうからです。

書式を保ったまま翻訳する

翻訳の際に大事なのは、記事のHTML構造を壊さないことです。見出しは見出しのまま、お店カードは識別子を保ったまま訳してほしい。

そこでAIへの指示に「HTMLの構造をそのまま保持すること」を明記し、生成された結果も通常の記事と同じサニタイズを通してから保存しています。AIの出力だからといって検査を省かない、という方針です。

検索結果に表示されるタイトルや説明文については、直訳ではなく、その言語として自然な表現に置き換えるよう指示を分けました。

訳がない言語は日本語で見せる

英語版がまだ用意できていない記事に英語で訪れた場合、記事が存在しないと表示するのではなく、日本語版を表示します。空のページを見せるより、読める形で出したほうが親切だと考えました。

公開したら即座に反映する

キャッシュと即時反映の両立

サイトの表示を速くするため、ページの内容は一定時間キャッシュされます。しかし記事を公開した運営者からすると、「公開したのにサイトに出ない」のは不安です。

そこで記事を保存・公開したタイミングで、関連するページのキャッシュを明示的に破棄する処理を入れました。一覧ページ、記事ページ、トップページ、サイトマップ。これらが即座に更新されます。

データベースが落ちてもページは出す

もしデータベースに接続できなくなったら、ブログ一覧ページはエラーになってしまうのでしょうか。それでは困ります。

今回は、データベースから記事を取得できなかった場合に、あらかじめ用意したサンプル記事を表示する仕組みを入れました。あわせて「これはサンプル表示です」という注記も出します。サイト全体が落ちるより、はるかにましな状態です。

まとめ

公開フローの設計で大事にしたのは、次の3点です。

  1. 状態を増やさない — 予約公開は「公開状態+未来の日時」で表現し、複雑化を避ける
  2. AI翻訳は明示的に実行 — 自動実行にせず、費用と手直しの上書きを防ぐ
  3. 即時反映と時間経過の二本立て — 手動更新はキャッシュ破棄、予約公開は時間経過で反映