# General Translation Knowledge Base: TanStack Start に i18n を追加するには？
URL: https://generaltranslation.com/ja/kb/add-i18n-to-tanstack-start.mdx
Docs index: https://generaltranslation.com/llms.txt
Description: TanStack Start には組み込みの i18n がないため、サーバーリクエストごとにロケールを解決し（通常は URL プレフィックスまたはクッキーから）、レンダリング前にメッセージを読み込むライブラリを追加します。Paraglide JS、react-i18next、Lingui は自分で用意した翻訳をレンダリングするのに対し、General Translation の実験的な gt-tanstack-start は、JSX 内にインラインで記述したテキストから翻訳を生成することもできます。
Category: 国際化
Last updated: 2026-10-28
Authors: General Translation Team
Published: 2026-10-28

TanStack Start には i18n レイヤーが含まれていないため、次の 3 つの要素を自分で用意する必要があります。アクティブな言語でテキストをレンダリングするライブラリ、サーバーリクエストのたびにその言語を解決する仕組み、そして翻訳そのものです。Start はドキュメント全体をサーバーでレンダリングしてからブラウザでハイドレーションするため、サーバーとクライアントの両方で同じロケールと同じメッセージを使う必要があります。そうしないと、初回描画が誤った言語で表示されたり、ハイドレーションに失敗したりします。

## TanStack Start が提供するもの、提供しないもの

TanStack Start は「TanStack Router を基盤としたフルスタック React フレームワーク」であり、ドキュメント全体のサーバーサイドレンダリング (SSR) 、ストリーミング、サーバー関数、リクエストミドルウェアを備えています ([TanStack Start overview](https://tanstack.com/start/latest/docs/framework/react/overview)) 。このうちいくつかは、i18n のセットアップを支える土台となります。

* **ロケール URL。** `/{-$locale}/about` のような任意のパスパラメータを使えば、1 つのルートファイルで `/about`、`/es/about`、`/fr/about` のすべてにマッチします。あるいは、ルーターの `rewrite` オプションでロケールプレフィックスを付加・除去する方法もあります ([TanStack Router i18n guide](https://tanstack.com/router/latest/docs/guide/internationalization-i18n)) 。
* **リクエストミドルウェア。** `src/start.ts` で `createStart` に登録したミドルウェアは、SSR やサーバー関数を含むすべてのリクエストの前に実行されます ([TanStack Start middleware](https://tanstack.com/start/latest/docs/framework/react/guide/middleware)) 。i18nライブラリは、ここで URL、クッキー、`Accept-Language` ヘッダーを読み取ります。
* **ローダーと `head`。** ルートルートのローダーを使えば、レンダリング前にロケールのメッセージを読み込めます。また、各ルートの `head` では翻訳済みの `<title>` やメタタグを設定します。

Start が開発者に委ねているのは、メッセージカタログとそれを参照するランタイム、ロケール検出と選択されたロケールを記憶するクッキー、ルートシェルの `<html lang>` 属性、複数形と数値フォーマット、`hreflang` リンク、そして翻訳そのものです。TanStack の i18n ガイドでは、TanStack Start の SSR セットアップを含め Paraglide JS を詳しく解説しているほか、Intlayer と use-intl のコミュニティガイドへのリンクも掲載しています。さらに、TanStack CLI には新規アプリ向けの `paraglide` アドオンも用意されています。

## 選択肢

| ライブラリ                                                  | テキストの書き方                                                                                                        | サーバー上のロケール                                                                                                                                  | 翻訳の提供元                                                                         |
| ------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------------ |
| [Paraglide JS](https://paraglidejs.com/tanstack-start) | ロケールごとの JSON ファイルにメッセージを記述し、`m.greeting()` のような型付き関数にコンパイル                                                      | `paraglideMiddleware` がサーバーハンドラーをラップする。ストラテジーには URL、クッキー、優先言語などがある                                                                          | 自分自身、翻訳者、またはファイルに対して実行する機械翻訳コマンド                                               |
| [react-i18next](https://react.i18next.com/latest/ssr)  | JSON 名前空間内のキーを `t('home.title')` でレンダリング                                                                        | 公式ドキュメントに TanStack Start とのインテグレーションの記載はない。per-request インスタンスを用意し、`initialLanguage` と `initialI18nStore` をクライアントに渡す                         | 自分自身、翻訳者、または Locize などの翻訳管理システム (TMS)                                          |
| [Lingui](https://lingui.dev/ref/vite-plugin)           | `<Trans>` マクロをインラインで記述し、PO カタログに抽出                                                                              | Vite プラグインがカタログをコンパイルする。リクエストのロケールはサーバーとブラウザの両方で自分で有効化する                                                                                    | 自分自身、翻訳者、またはカタログと同期するサービス                                                      |
| General Translation (`gt-tanstack-start`、実験的)          | JSX を [`<T>`](/docs/react/reference/components/t) でラップし、文字列には [`useGT`](/docs/react/reference/hooks/use-gt) を使用 | [`gtMiddleware`](/docs/react/tanstack-start/reference/functions/gt-middleware)：URL プレフィックス (オプトイン) → クッキー → `Accept-Language` → デフォルトロケールの順 | [`npx gt translate`](/docs/cli/reference/commands/translate) で生成し、ダッシュボードでレビュー |

TanStack が公式ドキュメントで紹介しているセットアップ、型付きメッセージ関数、メッセージ単位のツリーシェイキングを使いたく、JSON ファイルを埋める手段もすでにあるなら、Paraglide JS が適しています。別のアプリから i18next のカタログを移行するなら react-i18next、翻訳者が PO ファイルで作業するなら Lingui がおすすめです。テキストをコンポーネント内にインラインで書いたまま、そこから翻訳を生成して常に最新の状態に保ちたいなら、General Translation を選びましょう。 (より詳しい比較は [General Translation vs. Paraglide JS](/kb/general-translation-vs-paraglide) を参照してください。) 

`gt-tanstack-start` は実験的な段階にあります。General Translation のドキュメントでも、破壊的変更が入る可能性があり、本番環境での使用はまだ推奨されないとされています。現時点で安定した React のセットアップについては、[React アプリを翻訳するには？](/kb/translate-react-app) を参照してください。

## TanStack Start に General Translation を追加する

このウォークスルーでは、ページにスペイン語とフランス語を追加し、サーバー関数を翻訳したうえで、各言語をそれぞれ専用の URL に移行します。動作確認は、`npx @tanstack/cli@latest create` で生成したアプリ (`@tanstack/react-start` 1.169.4) 、`gt-tanstack-start@11.4.16`、`gt@2.26.11` で行っています。このパッケージには `@tanstack/react-start` 1.159.0 以降が必要で、ESM 専用です。

[セットアップウィザード](/docs/cli/reference/commands/init) (`npx gt@2.26.11 init`) を使うと、手順 1〜4 と同じ変更が適用されます。パッケージのインストールに加え、ローダー、ミドルウェア、ルーター呼び出し、ルートルートを書き込み、安全に変更できない箇所があれば一覧表示します。ウィザードによる差分をレビューするか、手順に沿って手動で進めてください。

### 1. ライブラリとCLIをインストールする

```bash
npm install gt-tanstack-start@11.4.16
npm install --save-dev gt@2.26.11
```

`gt-tanstack-start` は、[`<T>`](/docs/react/reference/components/t) や [`<LocaleSelector>`](/docs/react/reference/components/locale-selector) などの共通 React コンポーネントに加え、サーバー用ヘルパーもエクスポートします。`gt` CLI は翻訳元のテキストを検出し、翻訳ファイルを生成します。

### 2. 言語を設定する

```json title="gt.config.json"
{
  "defaultLocale": "en",
  "locales": ["es", "fr"],
  "files": {
    "gt": {
      "output": "src/_gt/[locale].json"
    }
  }
}
```

Vite がファイルをインポートできるよう、出力先は `src/` 配下にしてください。続いて、ローダーを追加します。

```ts title="src/loadTranslations.ts"
export default async function loadTranslations(locale: string) {
  const translations = await import(`./_gt/${locale}.json`);
  return translations.default;
}
```

### 3. リクエストミドルウェアを登録する

```ts title="src/start.ts"
import { createCsrfMiddleware, createStart } from '@tanstack/react-start';
import { gtMiddleware } from 'gt-tanstack-start';

// サーバー関数向けの TanStack Start の CSRF 保護はそのまま有効にしておきます。
const csrfMiddleware = createCsrfMiddleware({
  filter: ({ handlerType }) => handlerType === 'serverFn',
});

export const startInstance = createStart(() => ({
  requestMiddleware: [csrfMiddleware, gtMiddleware],
}));
```

General Translation の [`gtMiddleware`](/docs/react/tanstack-start/reference/functions/gt-middleware) は、リクエストごとに一度だけロケールを解決します。ロケールクッキー、`Accept-Language`、`defaultLocale` の順に参照し、解決したロケールをクッキーに保存します。複数のリクエストが同時にレンダリングされる場合でも、各リクエストはそれぞれ独自のロケールを保持します。

### 4. ライブラリを初期化し、ルートルートをハイドレートする

既存の `src/router.tsx` のモジュールスコープに、初期化処理を追加します:

```tsx title="src/router.tsx"
import { initializeGT } from 'gt-tanstack-start';
import gtConfig from '../gt.config.json';
import loadTranslations from './loadTranslations';

initializeGT({ ...gtConfig, loadTranslations });

// ... 既存の getRouter() はそのまま
```

次に、ルートルートでロケールとその翻訳を読み込み、両方を [`<GTProvider>`](/docs/react/reference/components/gt-provider) に渡します。

```tsx title="src/routes/__root.tsx"
import { HeadContent, Scripts, createRootRoute } from '@tanstack/react-router';
import {
  GTProvider,
  LocaleSelector,
  getLocale,
  getTranslationsSnapshot,
} from 'gt-tanstack-start';

export const Route = createRootRoute({
  // 初回リクエストではサーバー上で実行されるため、HTMLは翻訳済みの状態で返されます。
  loader: async () => {
    const locale = getLocale();
    return { locale, translations: await getTranslationsSnapshot(locale) };
  },
  shellComponent: RootDocument,
});

function RootDocument({ children }: { children: React.ReactNode }) {
  const { locale, translations } = Route.useLoaderData();
  return (
    <html lang={locale}>
      <head>
        <HeadContent />
      </head>
      <body>
        <GTProvider locale={locale} translations={translations}>
          <LocaleSelector />
          {children}
        </GTProvider>
        <Scripts />
      </body>
    </html>
  );
}
```

[`getLocale`](/docs/react/tanstack-start/reference/functions/get-locale) は、サーバー上ではリクエストのロケールを、ブラウザ上ではクッキーを読み取るため、サーバーとクライアントのレンダリング結果が一致します。`lang={locale}` を設定することで、スターターのシェルにハードコードされている `lang="en"` が置き換わります。

### 5. 翻訳対象のコンテンツをマークする

```tsx title="src/routes/index.tsx"
import { createFileRoute } from '@tanstack/react-router';
import { T, useGT } from 'gt-tanstack-start';

export const Route = createFileRoute('/')({ component: Home });

function Home() {
  const gt = useGT();

  return (
    <main>
      <T>
        <h1>Find your next project</h1>
        <p>Explore projects from teams around the world.</p>
      </T>
      <input type="search" placeholder={gt('Search projects')} aria-label={gt('Search projects')} />
    </main>
  );
}
```

[`<T>`](/docs/react/reference/components/t) は、マークアップを文脈として利用し、見出しと段落をひとまとまりで翻訳します。属性の文字列は [`useGT`](/docs/react/reference/hooks/use-gt) で扱います。[`<T>`](/docs/react/reference/components/t) 内の名前、数値、日付には、[変数コンポーネントおよびフォーマットコンポーネント](/docs/react/guides/formatting-variables)を使用してください。

### 6. 翻訳を生成

[`npx gt login`](/docs/cli/reference/commands/login) でサインインし、`GT_PROJECT_ID` (または `gt.config.json` の `projectId`) を設定してから、[`npx gt translate`](/docs/cli/reference/commands/translate) を実行します。`src/_gt/es.json` と `src/_gt/fr.json` が出力されます。生成には[従量課金](https://generaltranslation.com/pricing)が適用されます。

アカウントを作成せずにセットアップを試す場合は、[`npx gt generate`](/docs/cli/reference/commands/generate) を実行します。英語の原文が入った同じファイルが出力されるので、手動で編集してください。ファイルがまだ存在しないロケールでは原文がレンダリングされ、翻訳を読み込めなかったという警告がログに記録されます。

### 7. 実行して言語を切り替える

`npm run dev` を実行し、セレクターで Español を選択します。選択内容がロケールのクッキーに保存されてページが再読み込みされ、サーバーがスペイン語でレンダリングします。テストアプリで本番環境のビルドを確認したところ、`Accept-Language: es` を指定したリクエストにはスペイン語の見出しとプレースホルダーを含む `<html lang="es">` が、言語の指定がないリクエストには英語の `<html lang="en">` が返されました。

## サーバー関数とメタデータで翻訳する

[`getGT`](/docs/react/tanstack-start/reference/functions/get-gt) は、リクエストのロケールに基づいて、サーバー関数内の文字列を翻訳します：

```tsx title="src/routes/account.tsx"
import { createFileRoute } from '@tanstack/react-router';
import { createServerFn } from '@tanstack/react-start';
import { getGT } from 'gt-tanstack-start';

const loadAccount = createServerFn({ method: 'GET' }).handler(async () => {
  const gt = await getGT();
  return { title: gt('Your account') };
});

export const Route = createFileRoute('/account')({
  loader: () => loadAccount(),
  // 翻訳後のタイトルは、ページの <title> としても使用されます。
  head: ({ loaderData }) => ({ meta: [{ title: loaderData?.title }] }),
  component: () => <h1>{Route.useLoaderData().title}</h1>,
});
```

これらのヘルパーは、サーバー上で [`gtMiddleware`](/docs/react/tanstack-start/reference/functions/gt-middleware) が処理したリクエストの外側 (モジュールスコープなど) で呼び出すと例外をスローします。辞書エントリと登録済みメッセージについては、[サーバー関数の使用](/docs/react/tanstack-start/using-server-functions)でも説明しています。

## 言語ごとに専用のURLを割り当てる

上記のセットアップでは、すべての言語が同じURLで配信され、表示言語はクッキーまたはブラウザの言語設定によって決まります。検索エンジンは1つのURLにつき1つの言語しかインデックスしないため、[公開ページには `/es/about` のようなプレフィックスが必要です](/kb/locale-routing-seo)。`createFileRoute('/{-$locale}/')` を使用した `src/routes/{-$locale}/index.tsx` のように、ルートを任意のセグメント配下に移動してから、ロケールルーティングを有効にします:

```json title="gt.config.json"
{
  "defaultLocale": "en",
  "locales": ["es", "fr"],
  "localeRouting": true
}
```

これにより、ミドルウェアはまずパスを確認し、セレクターはプレフィックス付きの URL に遷移するようになります。テストアプリでは、`/es` と `/es/account` は `<html lang="es">` 付きのスペイン語で、`/` は英語でレンダリングされました。なお、プレフィックスのない URL の場合、再訪問者には引き続きクッキーの設定が適用されます。また、[`hreflang` リンク](/kb/what-is-hreflang)は各ルートの `head` に手動で追加する必要があります ([ロケールルーティングのセットアップ](/docs/react/tanstack-start/setup#locale-routing)を参照) 。

## 翻訳をリリースし、常に最新の状態に保つ

ビルドのたびに事前に翻訳を実行し、新しいテキストをすべての言語でリリースできるようにします：

```json title="package.json"
{
  "scripts": {
    "build": "gt validate && gt translate && vite build"
  }
}
```

[`gt validate`](/docs/cli/reference/commands/validate) は、翻訳を壊すおそれのあるコンテンツを検出すると、API 呼び出しの前にビルドを失敗させます。CI では、`GT_PROJECT_ID` と、**Files &gt; Write** および **Translation queue &gt; Enabled** の権限を持つプロジェクトの APIキーを `GT_API_KEY` として設定してください ([CLI の認証情報](/docs/cli/guides/configuring#credentials)) 。2 回目以降の実行では、新規または変更された翻訳元のみが翻訳されます。

レビュー担当者は General Translation の[翻訳エディター](/docs/platform/dashboard/guides/reviewing-translations)で任意の文字列を編集できます。また、JSON ファイル上で行った編集は [`npx gt save-local`](/docs/cli/reference/commands/save-local) で送り返せるため、以降の実行でもその編集が保持されます。[コンテキストグループ](/docs/platform/dashboard/guides/defining-context-for-translations)には用語集とカスタムプロンプトが格納されるため、このアプリ、ドキュメント、その他のプロジェクト全体で製品名やトーンを統一できます。General Translation の AIエージェントである [Locadex](/docs/platform/locadex/guides/configuring-automations) は TanStack Start アプリに対応しており、新しい文言をプルリクエスト経由で翻訳できます。

## よくある質問

### TanStack Start には i18n 機能が組み込まれていますか？

いいえ。TanStack Router には任意のロケールセグメントと URL の書き換え、Start にはミドルウェアとローダーが用意されていますが、メッセージ、ロケール検出、翻訳といった機能はライブラリで実装する必要があります。

### TanStack Start で react-i18next を使用できますか？

はい、React ライブラリとして使用できます。ただし、TanStack のドキュメントには記載がなく、react-i18next の SSR ガイドで紹介されているのも Next.js、Remix、Gatsby のインテグレーションのみです。そのため、per-request のインスタンスとクライアント側のハイドレーションは自分で組み込む必要があります。

### gt-tanstack-start は本番環境で使用できますか？

現時点では推奨されません。General Translation はこのパッケージを実験的なものと位置付けています。バージョンを固定し、アップグレード前には必ず変更履歴をレビューしてください。

## 重要なポイント

* TanStack Start には i18n レイヤーがありません。i18n を組み込む場所は、任意の `/{-$locale}` セグメント、`createStart` ミドルウェア、ルートローダーです。
* ロケールはリクエストごとにサーバー上で解決し、同じメッセージでクライアントをハイドレートしてください。また、`<html lang>` はスターターにハードコードされた `lang="en"` のままにせず、ローダーから設定します。
* TanStack のドキュメントで紹介されているライブラリは Paraglide JS です。Paraglide JS、react-i18next、Lingui はいずれも、開発者が用意した翻訳をレンダリングする仕組みです。
* General Translation の実験的な `gt-tanstack-start` は、[`gtMiddleware`](/docs/react/tanstack-start/reference/functions/gt-middleware)、[`initializeGT`](/docs/react/reference/config#initialize)、[`<GTProvider>`](/docs/react/reference/components/gt-provider) を提供し、テキストを [`<T>`](/docs/react/reference/components/t) 内にインラインで記述できます。翻訳は [`npx gt translate`](/docs/cli/reference/commands/translate) によって `src/_gt/[locale].json` に書き出されます。
* 言語ごとにインデックス可能な個別の URL が必要な場合は、任意の `{-$locale}` セグメントとあわせて `"localeRouting": true` を追加してください。

## Related questions

- [Next.js App Router アプリに i18n を追加するには？](https://generaltranslation.com/ja/kb/add-i18n-to-nextjs.mdx): まず gt init を実行して、対応する App Router プロジェクトに General Translation を設定します。次にソースコンテンツをマークし、翻訳を生成して、言語の切り替えが機能することを確認します。gt-next はテキストを翻訳の文脈とともに JSX 内に保持し、生成、レビュー、継続的な更新は CLI、ダッシュボード エディター、Locadex が担います。このガイドでは、ローカルファイルを明示的に使うセットアップ方法も紹介します。
- [General Translation と Paraglide JS：どちらを使うべきか](https://generaltranslation.com/ja/kb/general-translation-vs-paraglide.mdx): コピーをインラインで記述したまま、React コンポーネントの構造、共有の用語集、ダッシュボード でのレビューを活かして翻訳を生成したいなら General Translation を選びましょう。コンパイル済みの型付きメッセージ関数と、メッセージ単位のツリーシェイキングを重視するなら Paraglide JS が適しています。Paraglide はカタログをレンダリングするライブラリであり、General Translation は翻訳元のコピーを翻訳の生成から継続的な更新までつなげます。
- [Reactアプリに最適なi18nライブラリは？](https://generaltranslation.com/ja/kb/best-react-i18n-library.mdx): React向けの主要なi18nライブラリは、General Translationのgt-react、react-i18next、Lingui、React Intlの4つです。いずれも翻訳のレンダリングと書式設定に対応していますが、JSXにインラインで記述したテキストから翻訳の生成まで行えるのはgt-reactだけです。i18nextのカタログやプラグインを引き続き使いたい場合はreact-i18next、メッセージを抽出してコンパイル済みカタログを生成したい場合はLingui、FormatJSとICU MessageFormatを使いたい場合はReact Intlを選びましょう。
- [言語リダイレクトと SEO：URL、クッキー、Accept-Language のどれを使うべきか](https://generaltranslation.com/ja/kb/locale-routing-seo.mdx): Googlebot は Accept-Language ヘッダーを送信せず、クロールの大半を米国の IP アドレスから行います。そのため、インデックスさせたいすべてのページの言語は URL で決めましょう。保存済みのクッキーの選択、次いで Accept-Language を使うのは、/ のような中立的なルートのリダイレクト先を決める場合だけにとどめ、その際は一時的な 302 または 307 を使います。
- [React アプリを翻訳するには？](https://generaltranslation.com/ja/kb/translate-react-app.mdx): React アプリを翻訳するには、まずコンポーネントを国際化してユーザーの言語でレンダリングできるようにし、次にすべての文字列をサポート対象の各言語に翻訳します。General Translation の gt-react は `<T>` コンポーネント内の JSX をインプレースで翻訳し、npx gt translate は言語ごとに 1 つのファイルを書き出します。

## Previous and next questions

- Previous question: [strings.xml で Android アプリをローカライズするには？](https://generaltranslation.com/ja/kb/localize-android-app.mdx)
- Next question: [Weglot の代替: General Translation と Weglot の比較](https://generaltranslation.com/ja/kb/general-translation-vs-weglot.mdx)

## Sitemap

See the [Knowledge Base sitemap](https://generaltranslation.com/ja/kb/sitemap.md) for every article.
