はじめに

Contentfulで多言語サイトを構築中、運用担当者から「新規ページを作成してもPublishボタンがアクティブにならない」という報告を受けました。既存ページの更新は問題なくできるのに、新規作成だけができないという状況です。

本記事では、原因の特定プロセスと解決方法を紹介します。

環境

  • Contentful(ヘッドレスCMS)
  • ロケール: 日本語(ja、デフォルト)+ 英語(en)
  • Next.js + Contentful Delivery API でフロントエンドを構築

症状

  • 新規にPageエントリーを作成し、必要な情報をすべて入力しても Publishボタンがグレーアウト してクリックできない
  • 既存ページの更新(タイトルや本文の変更)は問題なくPublishできる
  • Draft保存は正常に動作する

原因の切り分け

1. コンテンツタイプのバリデーションを確認

まず、pageコンテンツタイプのフィールド定義を確認しました。

title:        Symbol, required: true,  localized: true
slug:         Symbol, required: true,  localized: false
body:         RichText, required: false, localized: true
bodyMarkdown: Text, required: false,    localized: true

titleslugが必須ですが、どちらも入力済み。slugのバリデーション(^[a-z0-9]+(?:-[a-z0-9]+)*$)にも違反していませんでした。

2. ユーザー権限を確認

Management APIでスペースメンバーシップを確認しました。

curl -s -H "Authorization: Bearer $TOKEN" \
  "https://api.contentful.com/spaces/$SPACE_ID/space_memberships"

報告者はAdmin権限を持っており、権限の問題ではありませんでした。

3. APIから直接Publishを試行 — 原因特定

UIでは原因がわからなかったため、Management APIから直接Publishを試みました。 これが決め手になりました。

curl -s -X PUT \
  -H "Authorization: Bearer $TOKEN" \
  -H "X-Contentful-Version: 13" \
  "https://api.contentful.com/spaces/$SPACE_ID/environments/master/entries/$ENTRY_ID/published"

レスポンス:

{
  "sys": { "type": "Error", "id": "InvalidEntry" },
  "message": "Validation error",
  "details": {
    "errors": [
      {
        "name": "required",
        "path": ["fields", "title", "en"],
        "details": "The property \"en\" is required here"
      }
    ]
  }
}

英語ロケールのtitleが未入力であることがバリデーションエラーの原因でした。

根本原因

ロケール設定を確認すると、以下の状態でした。

curl -s -H "Authorization: Bearer $TOKEN" \
  "https://api.contentful.com/spaces/$SPACE_ID/environments/master/locales"
ロケールデフォルトoptionalfallbackCode
ja (日本語)Yesfalseなし
en (英語)Nofalseなし

問題は2点です。

  1. optional: false — 英語の入力が必須。ローカライズされた必須フィールド(title)は、すべてのロケールで値が必要になる
  2. fallbackCode: null — フォールバックが未設定。英語の値がない場合に日本語の値を代用する仕組みがない

運用担当者は日本語でのみコンテンツを入力しており、英語のtitleを入力していなかったため、バリデーションに引っかかっていました。

なぜ既存ページは更新できたのか?

既存ページは開発時に日英両方のtitleを入力してPublish済みでした。更新時は既存の英語titleがそのまま残っているため、バリデーションを通過できていたのです。

解決方法

英語ロケールの設定を変更しました。

curl -s -X PUT \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/vnd.contentful.management.v1+json" \
  -H "X-Contentful-Version: $VERSION" \
  "https://api.contentful.com/spaces/$SPACE_ID/environments/master/locales/$EN_LOCALE_ID" \
  -d '{
    "name": "English",
    "code": "en",
    "fallbackCode": "ja",
    "optional": true
  }'

変更内容:

設定変更前変更後効果
optionalfalsetrue英語の入力が任意になる
fallbackCodenull“ja”英語が未入力の場合、日本語の値にフォールバック

この変更により、運用担当者は日本語のみ入力すればPublishできるようになり、英語の値が必要な場合は日本語の値が自動的に使用されます。

UIでは気づきにくい理由

ContentfulのWeb UIは、Publishボタンがグレーアウトしている理由を必ずしも明確に表示しません。特に多言語設定では、現在表示中のロケール(日本語)ではすべてのフィールドが正しく入力されているように見えても、別のロケール(英語)側でバリデーションエラーが発生しているケースがあります。

UIのサイドバーにエラー表示が出ることもありますが、ロケールを切り替えないと具体的な原因が見えない場合があります。

教訓

  1. 多言語サイトでは、ロケールのoptionalfallbackCodeを最初に設定する — 特にデフォルト以外のロケールはoptional: true+フォールバック設定をしておくと、運用時のトラブルを防げる
  2. UIで原因不明の場合はManagement APIを使う — APIからの操作はエラーメッセージが明確で、原因特定が速い
  3. 開発者と運用者の操作パターンの違いに注意 — 開発者は全ロケールを入力するが、運用者はデフォルトロケールのみで作業することが多い

まとめ

ContentfulでPublishできない問題の多くは、バリデーションエラーに起因します。特に多言語設定では、ロケールごとの必須/任意設定とフォールバックの有無が重要です。UIだけで原因を特定できない場合は、Management APIを活用することで、具体的なエラーメッセージを取得できます。