コンテンツへスキップ
DedicatedPHP 接触

PHPの多言語コンテンツ管理:データモデルと編集ワークフロー

翻訳の関連付け、言語ごとの編集ステータス、URL・検索・未完成コンテンツの明確なルールを定め、PHPの多言語コンテンツを設計します。

PHPアプリケーションで編集コンテンツと、言語ごとの翻訳および公開ステータスを関連付ける図

多言語アプリケーションは、画面上のラベルを翻訳するだけでは成り立ちません。記事、商品情報などの編集コンテンツも提供する場合、各コンテンツの言語、各言語版の関連付け、翻訳が公開可能な状態であることの意味を表現する必要があります。曖昧なモデルは、古いテキスト、リンク先のないリンク、本来見せるべきでないユーザーに表示される下書きにつながります。

PHPで多言語コンテンツ管理を計画する際は、インターフェース、データ、編集ワークフローに関する判断を分けるとよいでしょう。インターフェースには翻訳ファイル、可変のコンテンツにはデータベースを利用できますが、その分け方はドメインと編集者のニーズに即したものである必要があります。

インターフェース言語、原文の言語、翻訳を分ける

インターフェース言語、原文の言語、翻訳を分ける — guía visual de DedicatedPHP

インターフェース言語は、ラベル、検証メッセージ、日付形式など、製品固有のテキストを決定します。PHPアプリケーションでは、たとえばロケール別に整理したファイルなどの翻訳カタログで管理し、ユーザー設定やセッション設定に基づいて選択できます。閲覧するコンテンツの言語と混同してはいけません。

一方、原文の言語は、編集コンテンツが作成された言語を示します。各翻訳はそのコンテンツに関連付けられた版であり、それぞれ固有の言語を持ちます。ユーザーはインターフェースをスペイン語で操作しながら、原文が英語のページを開くことがあります。それを許可するか、どのように知らせるかを、アプリケーション側で明示的に決める必要があります。

正規化した言語コードを保存し、必要に応じて地域ロケールの扱いに一貫した方針を適用してください。言語と国を同じものとみなしてはいけません。地域別のバリエーションはテキストだけでなく、形式、提供状況、商業上の要件にも影響する場合があります。製品で対応するロケールと、不完全な設定を解決する際に使うロケールを定義してください。

ドメインを表現できるデータモデルを選ぶ

よく使われるパターンは3つあり、それぞれ異なるトレードオフがあります。

  • 言語別のフィールド: title_esやtitle_enのようなカラムは、言語数が少なく、フィールド構成が安定していて、直接クエリを行う場合には簡潔です。言語を追加すると柔軟性が失われ、スキーマ変更のたびに対応言語一覧への依存が生じます。
  • 独立したレコード: 各版を別個のコンテンツとして保存します。版ごとにライフサイクルや構造が本当に独立している場合には適していますが、版を確実にグループ化する別の方法が必要です。似たタイトルやURLを暗黙の関連付けに使ってはいけません。
  • 関連付けられた翻訳テーブル: 共通のコンテンツに言語ごとの行を関連付けます。たとえばcontent_idとlocaleを使います。言語の追加や利用可能な版の検索が容易になります。同じコンテンツと言語の組み合わせで翻訳が重複しないよう、制約が必要です。

版どうしが同じ識別情報と構造を共有する場合は、関連テーブルが適していることが多いものの、万能のルールではありません。内部参照など翻訳されないフィールドは共通エンティティに置き、編集用のローカライズされたフィールドは翻訳側に置けます。また、翻訳ごとにURL、検索メタデータ、公開日を設定できるかどうかも明確にしてください。

データベースでは、外部キー、コンテンツと言語の組み合わせに対する一意性、データ削除時の動作を定義します。PHPのアプリケーションロジックでも、言語が対応対象であること、関連するコンテンツが存在することを検証する必要があります。データベース制約は、事前検証だけでは防げない同時書き込みやエラーからデータを保護します。

すべての言語版を必須にせず関連付ける

すべてのコンテンツがすべての言語で存在するわけではなく、翻訳が完成するタイミングも異なります。この実態をモデルに反映してください。翻訳が任意であるなら、行が存在しないことを整合性エラーと解釈すべきではありません。一方、行は存在するもののまだ公開できない場合にどうなるかは、編集ステータスで示す必要があります。

ドメイン上で変化が必要な場合を除き、共有コンテンツに属する情報を翻訳ごとに重複させないでください。翻訳の関連付け解除、移動、アーカイブが可能なら、それぞれの操作と権限を定義します。各言語版のグループを特定するには、テキスト、slug、日付の一致ではなく、安定した関連付けを使ってください。

チームが古くなっている可能性のあるコンテンツを検出する必要がある場合は、翻訳の変更時に参照元となった原文の版を記録します。この情報だけで翻訳の誤りが証明されるわけではありませんが、レビューの優先順位付けに役立ちます。レビュー待ちのマークで十分な製品もあれば、版履歴と監査記録が必要な製品もあります。

言語ごとの編集ステータスを定義する

言語ごとに独立して作成、レビュー、公開できる場合、公開ステータスは各翻訳に持たせる必要があります。ある言語では公開済みでも、別の言語では下書きという状態があり得ます。コンテンツ単位の単一の公開フラグでは、この違いを表現できません。

たとえば「下書き」「レビュー中」「公開済み」のように、小さく明確なワークフローを設計してください。各ステータスを変更できる担当者、必須フィールド、レビューに承認が必要かどうかを定義します。プロセスの運用には公開日、担当者、変更履歴が必要な場合があります。チームの実際の操作に対応しないステータスを追加するのは避けてください。

公開用クエリでは、編集インターフェースが未公開の行を隠すことに頼らず、ステータスと言語で絞り込む必要があります。PHPでは、これらのルールをドメインアクセス層や再利用可能なクエリに集約し、コントローラー、API、バックグラウンドタスクが遵守することをテストしてください。編集や公開の操作では、対象となる言語とコンテンツに対する権限も確認する必要があります。

欠落、URL、検索を一貫して扱う

翻訳がない場合には、いくつかの方針があります。その言語ではコンテンツを非表示にする、別の言語でのみ利用可能だと知らせる、フォールバックを表示する、といった方法です。コンテンツの種類とユーザー体験への影響に応じて選択してください。フォールバックを翻訳であるかのように見せてはいけません。別の言語のコンテンツを表示する場合は明確に伝え、リクエストされた版に戻れるようにしてください。

インターフェースとコンテンツでは別のルールを適用します。ナビゲーションラベルが別のカタログにフォールバックできても、記事を原文版に自動的に置き換えてよいとは限りません。編集コンテンツのフォールバックは許可された言語と公開可能なコンテンツに限定し、下書きを返さないようにしてください。

URLは実在する版を特定するか、文書化されたリダイレクト規則に従う必要があります。言語を切り替える際は同じコンテンツの翻訳を探し、存在しない場合は有効に見えるパスを組み立てるのではなく、明確な選択肢を提示してください。SEOのために、見えないフォールバックによる空ページや重複ページの公開を避けます。検索では対象となる版だけをインデックスし、該当する言語で結果を絞り込み、表示してください。

公開前のチェックリスト

公開前のチェックリスト — guía visual de DedicatedPHP
  • インターフェース言語、原文の言語、各翻訳の言語は、モデル上で別の概念として扱われていますか?
  • 同じコンテンツと言語の組み合わせで、翻訳を2件保存できないようになっていますか?
  • 翻訳が存在しなくても、状態の不整合が生じない設計ですか?
  • チームは言語ごとに下書き、レビュー、公開を区別できますか?
  • 公開ルートと、言語切り替えリンクは、表示可能な版の存在を確認していますか?
  • フォールバックは用途ごとに定義され、ユーザーに伝えられ、下書きを決して公開しない設計ですか?
  • 検索は言語とステータスで絞り込み、公開停止された版のインデックス登録を解除しますか?
  • 権限、同時編集、削除、未完成コンテンツ、言語切り替えをテストしましたか?

リンク済みの翻訳を取り下げる場合、版の公開後に原文を更新する場合、利用できないURLへ直接アクセスする場合もテストしてください。それぞれについて、応答、ナビゲーション、検索結果での表示を確認します。目的はすべての言語を同じペースで進めることではなく、各版に固有の識別情報と検証可能なステータスを持たせ、編集者とユーザーにとって予測可能な動作を実現することです。

これらのアイデアをあなたのプロジェクトに活用してみませんか?あなたのPHPプラットフォームについて話し合いましょう。
関連サービスを見る