RESTful API データモデリング

RESTful APIにおける国際化対応(i18n)データ設計:多言語文字列とモデルの表現

Tags: データモデリング, RESTful API, 国際化, 多言語対応, 設計パターン

はじめに

現代のウェブアプリケーションやモバイルアプリケーションは、世界中のユーザーに利用されることが増えています。そのため、APIが提供する情報も多言語に対応している必要があります。RESTful APIのデータモデリングにおいて、多言語対応(国際化、i18n)は特に文字列データをどのように表現し、クライアントに提供するかが重要な課題となります。

この記事では、RESTful APIで多言語データを扱う際のデータモデリングについて、いくつかの具体的なパターンとそれぞれのメリット・デメリット、そして設計上の考慮事項を解説します。

なぜ多言語対応のデータモデリングが課題となるのか

APIが返すデータの中に、ユーザーインターフェースに表示されるようなテキスト(例: 商品名、商品説明、エラーメッセージなど)が含まれる場合、これらのテキストはユーザーの言語に合わせて表示されるべきです。しかし、単一のフィールドに一つの言語の文字列だけを持たせる設計では、多言語に対応できません。

例えば、Product リソースが name というフィールドを持つ場合を考えます。

{
  "id": 123,
  "name": "Apple",
  "price": 100
}

この設計では、「Apple」という商品名を日本語ユーザーには「リンゴ」と表示させたい、といった要求に応えられません。APIは、クライアントが必要とする言語の文字列を提供できるようなデータ構造である必要があります。

クライアントは通常、HTTPの Accept-Language ヘッダーなどを使って希望する言語を示します。APIは、その言語に応じたデータをレスポンスとして返す必要があります。これを実現するためには、サーバー側のデータ構造およびAPIレスポンスのデータモデリングが適切に行われていることが不可欠です。

多言語データの表現パターン

多言語文字列データをAPIレスポンスの中でどのように構造化するか、いくつかの代表的なパターンがあります。ここでは、主に以下の3つのパターンについて説明します。

  1. フィールドごとに言語コードをサフィックスとして付与
  2. 言語コードをキーとするMap/オブジェクト構造
  3. 別のリソース(関連リソース)として管理

それぞれのパターンについて、具体的なJSON構造の例と、メリット・デメリットを見ていきましょう。ここでは、商品名 (name) と商品説明 (description) が多言語対応が必要なフィールドであると仮定します。対応する言語は英語 (en) と日本語 (ja) とします。

パターン1: フィールドごとに言語コードをサフィックスとして付与

多言語化が必要なフィールド名の末尾に、言語コードをアンダースコアなどで区切って付与するパターンです。

JSON構造例:

{
  "id": 123,
  "name_en": "Apple",
  "description_en": "A sweet red fruit.",
  "name_ja": "リンゴ",
  "description_ja": "甘くて赤い果物です。",
  "price": 100
}

メリット:

デメリット:

考慮事項:

パターン2: 言語コードをキーとするMap/オブジェクト構造

多言語化が必要なフィールドを、言語コードをキー、文字列を値とするJSONオブジェクト(Map)として表現するパターンです。

JSON構造例:

{
  "id": 123,
  "name": {
    "en": "Apple",
    "ja": "リンゴ"
  },
  "description": {
    "en": "A sweet red fruit.",
    "ja": "甘くて赤い果物です。"
  },
  "price": 100
}

メリット:

デメリット:

考慮事項:

パターン3: 別のリソース(関連リソース)として管理

多言語化が必要な文字列データを、元のリソースとは別のリソースとして管理するパターンです。元のリソースからは、この関連リソースへの参照を持つか、あるいは関連リソースをネストして含める形を取ります。

例えば、Product リソースに対して、その翻訳情報を表す ProductTranslation リソースを用意するイメージです。

データ構造のイメージ (テキストによるER図的な表現):

+------------+       1:N        +----------------------+
|  Product   |------------------|  ProductTranslation  |
+------------+                  +----------------------+
| id         |                  | id                   |
| price      |                  | product_id (FK)      |
| ...        |                  | lang_code            |
+------------+                  | name                 |
                                | description          |
                                +----------------------+

API表現のパターン:

  1. ネストされたリソースとして表現: 元のリソース取得時に、関連する翻訳情報もネストして含める。

    JSON構造例:

    json { "id": 123, "price": 100, "translations": [ { "lang_code": "en", "name": "Apple", "description": "A sweet red fruit." }, { "lang_code": "ja", "name": "リンゴ", "description": "甘くて赤い果物です。" } ] }

    メリット: * 元のリソースと翻訳データが論理的に分離されます。 * 新しい言語の追加や翻訳フィールドの追加・変更が、元のリソースのスキーマに影響を与えません。 * ネストされた構造のため、どの言語が存在するか、関連する翻訳データは何かが見やすいです。

    デメリット: * データ構造がネストされます。 * APIのレスポンスとして、常に全ての言語の翻訳リストを返す場合、レスポンスサイズが大きくなります。

    考慮事項: * このパターンでも、クライアントからの要求言語に応じて、サーバー側でtranslationsリストから該当する言語のエントリのみをフィルタリングして返す、あるいはリストではなく単一の翻訳オブジェクトを返す、といった最適化が可能です。

  2. 関連リソースとして参照: 元のリソースからは翻訳データへの直接的な参照を持たず、別途翻訳リソースを取得させる。

    APIエンドポイントのイメージ: * GET /products/{id} -> 商品の基本情報を返す(翻訳データは含まない) * GET /products/{product_id}/translations -> 特定商品の全言語の翻訳リストを返す * GET /products/{product_id}/translations/{lang_code} -> 特定商品の特定言語の翻訳データを返す

    GET /products/123 のJSON構造例:

    json { "id": 123, "price": 100, // 翻訳データは含まない、あるいは翻訳リストへのURIを示す // "translations_url": "/products/123/translations" }

    GET /products/123/translations のJSON構造例:

    json [ { "lang_code": "en", "name": "Apple", "description": "A sweet red fruit." }, { "lang_code": "ja", "name": "リンゴ", "description": "甘くて赤い果物です。" } ]

    メリット: * リソースが明確に分離され、責務が分割されます。 * 元のリソース取得時のレスポンスサイズを小さく保てます。 * 必要な言語の翻訳データだけをピンポイントで取得できます(例: GET /products/123/translations/ja)。

    デメリット: * 元のリソースと翻訳データを同時に表示する場合など、クライアントは複数のAPI呼び出しが必要になることがあります(いわゆるN+1問題に似た状況)。

    考慮事項: * このパターンは、翻訳データが非常に多くなる可能性がある場合や、翻訳データの更新頻度が高いが元のリソースの更新頻度は低い場合などに適しています。また、必要に応じて関連リソースを埋め込む(Embedding)オプションを提供するなど、柔軟なデータ取得方法を検討すると良いでしょう。

パターン選択の指針

どのパターンを選択するかは、アプリケーションの要件、データの特性、開発・運用コストなど、様々な要素を考慮して決定する必要があります。

多くの場合、多言語対応が必要なフィールド数がそれなりにあり、将来的な言語追加も考慮すると、パターン2(言語コードをキーとするMap/オブジェクト構造) を採用し、API側でクライアントの要求言語に応じてフィルタリングして返す、というアプローチがバランスが良いと言えるでしょう。ただし、非常に大量の翻訳データを持つ場合や、翻訳データのみを独立して管理・更新したい場合は、パターン3(別のリソースとして管理) も有力な選択肢となります。

パターン1は、対応言語数が非常に限定的で、フィールド数も少なく、シンプルさを最優先する場合に検討する価値がありますが、将来的な拡張性には注意が必要です。

まとめ

RESTful APIにおける多言語対応データのモデリングは、文字列データをどのように表現し、クライアントに提供するかが鍵となります。

これらのパターンにはそれぞれメリット・デメリットがあり、アプリケーションの要件に応じて最適なアプローチを選択することが重要です。特に、データ量、取得頻度、更新頻度、そして将来的な拡張性を考慮して、保守性の高いデータモデリングを目指してください。多言語対応を適切に設計することで、より多くのユーザーに利用される使いやすいAPIを提供できるでしょう。