ブランチコンポーネント

翻訳内の条件付きコンテンツにブランチコンポーネントを使う方法

ブランチコンポーネントは、<T> コンポーネント内で条件付きコンテンツをレンダリングできるようにします。if/else ステートメントや複数形ルールといった動的ロジックを処理し、あらゆるコンテンツのバリエーションが適切に翻訳されるようにします。

利用可能なコンポーネント

  • <Branch>: 値や状態に応じた条件分岐コンテンツ
  • <Plural>: ロケール固有の複数形ルールによる自動化

クイックスタート

分岐コンポーネントは、条件分岐を扱うために <T> の内部で機能します。

import { T, Branch, Plural, Num, Var } from 'gt-react';

function NotificationPanel({ user, messageCount }) {
  return (
    <T>
      <Branch 
        branch={user.status}
        online={<p><Var>{user.name}</Var> は現在オンラインです</p>}
        away={<p><Var>{user.name}</Var> は離席中です</p>}
      >
        <p><Var>{user.name}</Var> のステータスは不明です</p>
      </Branch>
      
      <Plural
        n={messageCount}
        one={<p>メッセージが <Num>{messageCount}</Num> 件あります</p>}
        other={<p>メッセージが <Num>{messageCount}</Num> 件あります</p>}
      />
    </T>
  );
}

ブランチコンポーネントの仕組み

ブランチコンポーネントは、翻訳内の条件付きレンダリングを次のように解決します。

  1. <T> 内の三項演算子や条件分岐ロジックを置き換える
  2. 条件が想定どおりの値に一致しない場合にフォールバック用コンテンツを提供する
  3. 想定しうるすべてのコンテンツバリエーションを翻訳可能にする
  4. 複数形ルールに関するロケールの規則に自動的に従う
// ❌ 動作しません - <T> 内での条件分岐
<T><p>{isActive ? 'ユーザーは有効です' : 'ユーザーは無効です'}</p></T>

// ✅ 動作します - Branch を使った条件分岐
<T>
  <Branch 
    branch={isActive} 
    true={<p>ユーザーは有効です</p>}
    false={<p>ユーザーは無効です</p>}
  />
</T>

コンポーネントガイド

<Branch> - 条件付きコンテンツ

<Branch> は、value や状態に基づく条件付きレンダリングに使用します。

// ユーザーのステータス表示
<T>
  <Branch 
    branch={user.role}
    admin={<p>管理者dashboard</p>}
    user={<p>ユーザーdashboard</p>}
    guest={<p>ゲストアクセス</p>}
  >
    <p>アクセスレベル不明</p>
  </Branch>
</T>

// 真偽値の条件
<T>
  <Branch 
    branch={isLoggedIn}
    true={<p>おかえりなさい!</p>}
    false={<p>ログインしてください</p>}
  />
</T>

// サブスクリプションのティア
<T>
  <Branch
    branch={subscription.tier}
    free={<p>アップグレードしてプレミアム機能を有効にしましょう</p>}
    premium={<p>プレミアム体験をお楽しみください</p>}
    enterprise={<p>エンタープライズ向けソリューションはサポートまでお問い合わせください</p>}
  >
    <p>サブスクリプションのステータスを取得できません</p>
  </Branch>
</T>

<Plural> - スマートな複数形ルール

数量に応じて内容が変わる場合は、<Plural> を使用します。

// 基本的な複数形ルール
<T>
  <Plural
    n={itemCount}
    one={<p>カートに<Num>{itemCount}</Num>件の商品があります</p>}
    other={<p>カートに<Num>{itemCount}</Num>件の商品があります</p>}
  />
</T>

// 0件の扱い
<T>
  <Plural
    n={notifications}
    zero={<p>新しい通知はありません</p>}
    one={<p>通知が<Num>{notifications}</Num>件あります</p>}
    other={<p>通知が<Num>{notifications}</Num>件あります</p>}
  />
</T>

// 複雑な複数形ルール(Unicode CLDRに準拠)
<T>
  <Plural
    n={days}
    zero={<p>期日は本日です</p>}
    one={<p>期日まで残り<Num>{days}</Num>日</p>}
    few={<p>期日まで残り<Num>{days}</Num>日</p>}
    many={<p>期日まで残り<Num>{days}</Num>日</p>}
    other={<p>期日まで残り<Num>{days}</Num>日</p>}
  />
</T>

Variable コンポーネントとの組み合わせ

Branching コンポーネントと Variable コンポーネントはシームレスに連携します。

<T>
  <Branch
    branch={order.status}
    pending={
      <p>
        注文 <Var>{order.id}</Var> は保留中です。
        合計:<Currency currency="USD">{order.total}</Currency>
      </p>
    }
    shipped={
      <p>
        注文 <Var>{order.id}</Var> は <DateTime>{order.shippedDate}</DateTime> に発送されました
      </p>
    }
    delivered={
      <p>注文 <Var>{order.id}</Var> は正常に配達されました</p>
    }
  >
    <p>注文状況は不明です</p>
  </Branch>
</T>

ブランチングコンポーネントを使うべきタイミング

三項演算子を置き換える

<T> 内で使えるように条件分岐を変換します:

// ❌ <T> では三項演算子は使えません
<T>{isActive ? <p>アクティブユーザー</p> : <p>非アクティブユーザー</p>}</T>

// ✅ 代わりに Branch を使用してください
<T>
  <Branch 
    branch={isActive}
    true={<p>アクティブユーザー</p>}
    false={<p>非アクティブユーザー</p>}
  />
</T>

複数の条件を扱う

switch 文や複数の if/else 条件を置き換えます:

// ❌ 複雑な条件分岐ロジック
<T>
  {status === 'loading' ? <p>読み込み中...</p> : 
   status === 'error' ? <p>エラーが発生しました</p> : 
   status === 'success' ? <p>成功しました!</p> : 
   <p>不明なステータスです</p>}
</T>

// ✅ シンプルな分岐ロジック
<T>
  <Branch
    branch={status}
    loading={<p>読み込み中...</p>}
    error={<p>エラーが発生しました</p>}
    success={<p>成功しました!</p>}
  >
    <p>不明なステータスです</p>
  </Branch>
</T>

複数形ルール

手作業での複数形対応を置き換えます:

// ❌ 複数形ルールの手動対応
<T>{count === 1 ? <p>1 item</p> : <p>{count} items</p>}</T>

// ✅ 複数形ルールの自動対応
<T>
  <Plural
    n={count}
    one={<p><Num>{count}</Num> 個のアイテム</p>}
    other={<p><Num>{count}</Num> 個のアイテム</p>}
  />
</T>

スタンドアロンでの使用

ブランチングコンポーネントは、翻訳を伴わない純粋なロジック用途として、<T> の外でも使用できます。

// 純粋な条件分岐レンダリング
<Branch
  branch={theme}
  dark={<DarkModeIcon />}
  light={<LightModeIcon />}
>
  <DefaultIcon />
</Branch>

// 純粋な複数形処理
<Plural
  n={count}
  one={<SingleItemComponent />}
  other={<MultipleItemsComponent />}
/>

よくある問題点

分岐キーの不足

一致しない値には、必ずフォールバック用のコンテンツを用意してください:

// ❌ 想定外の値に対するフォールバックがない
<Branch
  branch={userRole}
  admin={<AdminPanel />}
  user={<UserPanel />}
  // userRole が "moderator" の場合は?
/>

// ✅ 常にフォールバックを用意する
<Branch
  branch={userRole}
  admin={<AdminPanel />}
  user={<UserPanel />}
>
  <DefaultPanel /> {/* その他の値に対するフォールバック */}
</Branch>

不完全な複数形

デフォルトのlocaleで必要な複数形を指定してください:

// ❌ "other" 形式が不足
<Plural
  n={count}
  one={<p>1 item</p>}
  // 0、2、3などの場合は?
/>

// ✅ 必要な形式を含める
<Plural
  n={count}
  zero={<p>アイテムなし</p>}
  one={<p>1個のアイテム</p>}
  other={<p>{count}個のアイテム</p>}
/>

複雑なネスト構造のロジック

これは機能しますが、分岐ロジックはできるだけシンプルに保ち、深いネストは避けることをおすすめします。

// ❌ 複雑にネストした分岐
<Branch branch={status}>
  <Branch branch={subStatus}>
    {/* 読みにくく、保守しづらい */}
  </Branch>
</Branch>

// ✅ ロジックを平坦化するか、複数のコンポーネントを使う
<Branch
  branch={`${status}-${subStatus}`}
  active-online={<ActiveOnline />}
  active-offline={<ActiveOffline />}
  inactive-online={<InactiveOnline />}
>
  <DefaultState />
</Branch>

複数形ルールについては、Unicode CLDR のドキュメントをご参照ください。

次のステップ

このガイドはいかがですか?