文字列の翻訳

文字列を国際化する方法

概要

このガイドでは、useGT() フック & getGT() 関数を使用して、Next.jsアプリで文字列を国際化する方法について説明します。

以下の内容をカバーします:

useGT() フックを使用するタイミング

useGT() フックの使用方法

変数の使用

よくある落とし穴

このガイドで useGT() フックについて言及する際は、getGT() 関数についても同様に言及しています。

この2つの唯一の違いは、いつ使用するかです。

getGT() 関数は、プロミス化された関数を返す非同期関数であり、 一方で useGT() フックは関数を直接返します。

同期コンポーネントでは getGT() 関数を使用し、 非同期コンポーネントでは useGT() フックを使用してください。

src/app/page.tsx
import { useGT } from 'gt-next';
export function MyComponent() {
  const translate = useGT();
  const translatedString = translate('Hello, world!');
  return <div>{translatedString}</div>;
}
src/app/page.tsx
import { getGT } from 'gt-next/server';
export async function MyComponent() {
  const translate = await getGT();
  const translatedString = translate('Hello, world!');
  return <div>{translatedString}</div>;
}

useGT() フックを使うタイミング

useGT() フックは、文字列を翻訳するために使用できる React フックです。

ほとんどの場合、<T> コンポーネントを使用できます。 ただし、JSX が適切でない場合には、useGT() フックを使用できます。

useGT() フックの方が適している場合の例は以下の通りです:

  • placeholdertitle 属性のように、厳密に文字列が求められるプロパティの場合。
  • 文字列が大きなオブジェクトの一部である場合。例えば:
const user = {
  title: 'Mr.',
  name: 'John',
  description: 'John is a software engineer at General Translation',
}

この場合、description プロパティのみ翻訳する必要があります。

可能な限り、<T> コンポーネントを使用してください。 <T> コンポーネントは JSX コンテンツの翻訳を可能にし、文字列を翻訳する推奨方法です。


useGT() フックの使用方法

useGT() フックは <GTProvider> 内で呼び出す必要があります。

文字列を翻訳するには、フックから返される関数に文字列を直接渡すだけです。

import { useGT } from 'gt-next';
export function MyComponent() {
  const translate = useGT();
  return <div>{translate('Hello, world!')}</div>;
}

従来のi18nライブラリとは異なり、useGT() フックでは関数に key を渡す必要がありません。 代わりに、文字列を直接関数に渡します。

これは辞書を使用する必要がないことを意味します!

getGT() 関数の使用方法

一方、getGT() 関数は非同期関数であるため、 async コンポーネントで使用でき、<GTProvider> 内で呼び出す必要がありません。

getGT() のコンテキストは、next.config.ts ファイル内の withGTConfig 関数によって処理されます。

import { getGT } from 'gt-next/server';
export async function MyComponent() {
  const translate = await getGT();
  return <div>{translate('Hello, world!')}</div>;
}

変数の使用

多くの場合、変数を含む文字列を翻訳する必要があります。

例えば、数値を含む文字列を翻訳する必要があるかもしれません。

変数を追加するには、単純に文字列内に {variable} のようなプレースホルダーを追加し、フックから返される関数の第2引数としてオブジェクトを渡します。

const price = 100;
const translate = useGT();
translate('There are {count} items in the cart', { variables: { count: 10 } });

{count} プレースホルダーは、count 変数の値に置き換えられます。

これにより、翻訳内で動的な値を表示することができます。

APIの詳細については、APIリファレンスをご覧ください。


  1. コンポーネント内で文字列を翻訳する
import { useGT } from 'gt-next';

export default function MyComponent() {
  const t = useGT();
  return (
    <div>
      <h1>{t('Hello, world!')}</h1>
    </div>
  )
}
export default function MyComponent() {
  return (
    <div>
      <h1>Hello, world!</h1>
    </div>
  )
}
  1. 変数を含む文字列を翻訳する
import { useGT } from 'gt-next';

export default function MyComponent() {
  const t = useGT();
  const count = 10;
  return (
    <div>
      <h1>{t('There are {count} items in the cart', { variables: { count } })}</h1>
    </div>
  )
}
export default function MyComponent() {
  const count = 10;
  return (
    <div>
      <h1>There are {count} items in the cart</h1>
    </div>
  )
}
  1. オブジェクトの一部を翻訳する
import { useGT } from 'gt-next';

export default function MyComponent() {
  const t = useGT();
  const users = [
    {
      name: 'John',
      description: t('John is a software engineer at General Translation'),
    },
    {
      name: 'Jane',
      description: t('Jane is a software engineer at Google'),
    },
  ]
  return (
    <div>
      {users.map((user) => (
        <div key={user.name}>
          <h1>{user.name}</h1>
          <p>{user.description}</p>
        </div>
      ))}
    </div>
  )
}
export default function MyComponent() {
  const users = [
    {
      name: 'John',
      description: 'John is a software engineer at General Translation',
    },
    {
      name: 'Jane',
      description: 'Jane is a software engineer at Google',
    },
  ]
  return (
    <div>
      {users.map((user) => (
        <div key={user.name}>
          <h1>{user.name}</h1>
          <p>{user.description}</p>
        </div>
      ))}
    </div>
  )
}
  1. 共有定数を翻訳する
src/llms.ts
// Custom function to get LLM data with translations
export function getLLMData(t: (content: string) => string) {
  return [
    {
      name: 'GPT-4.1',
      id: 'gpt-4.1',
      description: t('GPT-4.1 is a large language model developed by OpenAI'),
    },
    {
      name: 'Claude 3.7 Sonnet',
      id: 'claude-3-7-sonnet',
      description: t('Claude 3.7 Sonnet is a large language model developed by Anthropic'),
    },
  ]
}
import { getLLMData } from './llms';
import { useGT } from 'gt-next';

export default function MyComponent() {
  const t = useGT();
  const llms = getLLMData(t);
  return (
    <div>
      {llms.map((llm) => (
        <div key={llm.id}>
          <h1>{llm.name}</h1>
          <p>{llm.description}</p>
        </div>
      ))}
    </div>
  )
}
src/llms.ts
export const llms = [
  {
    name: 'GPT-4.1',
    id: 'gpt-4.1',
    description: 'GPT-4.1 is a large language model developed by OpenAI',
  },
  {
    name: 'Claude 3.7 Sonnet',
    id: 'claude-3-7-sonnet',
    description: 'Claude 3.7 Sonnet is a large language model developed by Anthropic',
  },
]
import { llms } from './llms';

export default function MyComponent() {
  return (
    <div>
      {llms.map((llm) => (
        <div key={llm.id}>
          <h1>{llm.name}</h1>
          <p>{llm.description}</p>
        </div>
      ))}
    </div>
  )
}

この最後の例では、llms配列を翻訳付きでデータを返す関数に変換しました。 データを返す関数にt関数を渡しています。

別の方法として、llms配列をカスタムフックに変換することもできます。 ただし、これは推奨されません。useGT()フックの使用方法に非常に注意する必要があり、 Reactのルールに違反しないようにする必要があるためです。


よくある落とし穴

動的コンテンツの翻訳

すべての文字列はビルド時に判明している必要があります。

つまり、実行時に生成または取得される動的コンテンツは翻訳できません。

これは、たとえ文字列であっても変数も含まれます。

export default function MyComponent() {
  const [dynamicContent, setDynamicContent] = useState('Hello, world!');
  const t = useGT();
  return (
    <div>
      <h1>{t(dynamicContent)}</h1> {/* This will not work */}
    </div>
  )
}

CLI ツールは、useGT() フックで動的コンテンツを翻訳しようとした場合に警告を表示します。


次のステップ

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