# IntlayerとNext.js 15アプリルーターでの国際化 (i18n) の始め方
## Intlayerとは?
**Intlayer**は、モダンウェブアプリケーションにおける多言語サポートを簡素化するために設計された革新的なオープンソース国際化(i18n)ライブラリです。Intlayerは最新の**Next.js 15**フレームワークとシームレスに統合され、強力な**アプリルーター**も含まれています。効率的なレンダリングのために**サーバーコンポーネント**での動作に最適化されており、[**Turbopack**](https://nextjs.org/docs/architecture/turbopack)にも完全に対応しています。
Intlayerを使用すると、以下を実現できます:
- **宣言型辞書を使用して翻訳を簡単に管理**することができます。
- **メタデータ、ルート、およびコンテンツを動的にローカライズ**することができます。
- **クライアントサイドおよびサーバーサイドコンポーネントで翻訳にアクセス**することができます。
- **自動生成された型を使用してTypeScriptサポート**を確保し、オートコンプリートとエラーチェックを向上させます。
- **動的ロケール検出や切り替え**などの高度な機能を利用できます。
> IntlayerはNext.js 12、13、14、15に対応しています。Next.js Page Routerを使用している場合は、この[ガイド](/ja/doc/environment/nextjs/next-with-Page-Router)を参照してください。Next.js 12、13、14でApp Routerを使っている場合は、この[ガイド](/ja/doc/environment/nextjs/14)を参照してください。
---
## Next.jsアプリケーションにIntlayerをセットアップする手順ガイド
### ステップ1: 依存関係をインストール
npmを使用して必要なパッケージをインストールします:
```bash packageManager="npm"
npm install intlayer next-intlayer
```
intlayer
設定管理、翻訳、コンテンツ宣言、トランスパイレーション、CLIコマンドのための国際化ツールを提供するコアパッケージです。
next-intlayer
IntlayerとNext.jsを統合するパッケージです。Next.js国際化のためのコンテキストプロバイダーとフックを提供します。さらに、IntlayerをWebpackやTurbopackと統合するNext.jsプラグイン、およびユーザーの好ましいロケールを検出し、クッキーを管理し、URLリダイレクトを処理するためのミドルウェアを含んでいます。
ステップ2: プロジェクトを設定する
アプリケーションの言語を設定するための構成ファイルを作成します:
import { Locales, type IntlayerConfig } from "intlayer";
const config: IntlayerConfig = {
internationalization: {
locales: [
Locales.JAPANESE,
Locales.FRENCH,
Locales.SPANISH,
// その他のロケール
],
defaultLocale: Locales.JAPANESE,
},
};
export default config;
この構成ファイルを通じて、ローカライズされたURL、ミドルウェアのリダイレクト、クッキー名、コンテンツ宣言の場所と拡張子の設定、Intlayerのログをコンソールに表示しないようにするなどを設定できます。利用可能なパラメータの完全なリストについては、設定ドキュメントを参照してください。
ステップ3: Next.js設定にIntlayerを統合
Next.jsのセットアップをIntlayerを使用するように設定します:
import { withIntlayer } from "next-intlayer/server";
/** @type {import('next').NextConfig} */
const nextConfig = {};
export default withIntlayer(nextConfig);
withIntlayer() Next.jsプラグインは、IntlayerをNext.jsに統合するために使用されます。これは、コンテンツ宣言ファイルのビルドを保証し、開発モードでそれらを監視します。WebpackまたはTurbopack環境内でIntlayerの環境変数を定義します。さらに、パフォーマンスを最適化するためのエイリアスを提供し、サーバーコンポーネントとの互換性を確保します。
ステップ4: ロケール検出のためのミドルウェアを設定
ユーザーの好ましいロケールを検出するためのミドルウェアを設定します:
export { intlayerMiddleware as middleware } from "next-intlayer/middleware";
export const config = {
matcher:
"/((?!api|static|assets|robots|sitemap|sw|service-worker|manifest|.*\\..*|_next).*)",
};
intlayerMiddlewareは、ユーザーの好ましいロケールを検出し、設定で指定された適切なURLにリダイレクトします。また、ユーザーの好ましいロケールをクッキーに保存することを可能にします。
ステップ5: 動的ロケールルートを定義
RootLayoutからすべてを削除し、次のコードに置き換えます:
import type { PropsWithChildren, FC } from "react";
import "./globals.css";
const RootLayout: FC<PropsWithChildren> = ({ children }) => children;
export default RootLayout;
RootLayoutコンポーネントを空にすることで、<html>タグにlangとdir属性を設定できます。
動的ルーティングを実装するために、[locale]ディレクトリに新しいレイアウトを追加してロケールのパスを設定します:
import type { NextLayoutIntlayer } from "next-intlayer";
import { Inter } from "next/font/google";
import { getHTMLTextDir } from "intlayer";
const inter = Inter({ subsets: ["latin"] });
const LocaleLayout: NextLayoutIntlayer = async ({ children, params }) => {
const { locale } = await params;
return (
<html lang={locale} dir={getHTMLTextDir(locale)}>
<body className={inter.className}>{children}</body>
</html>
);
};
export default LocaleLayout;
[locale]パスセグメントはロケールを定義するために使用されます。例:/en-US/aboutはen-USに、/fr/aboutはfrに関連します。
次に、アプリケーションレイアウトにgenerateStaticParams関数を実装します。
export { generateStaticParams } from "next-intlayer"; // 挿入行
const LocaleLayout: NextLayoutIntlayer = async ({ children, params }) => {
/*... 後のコード*/
};
export default LocaleLayout;
generateStaticParamsは、アプリケーションがすべてのロケールの必要なページを事前にビルドすることを保証し、ランタイム計算を減少させ、ユーザーエクスペリエンスを向上させます。詳細については、Next.jsのgenerateStaticParamsに関するドキュメントを参照してください。
ステップ6: コンテンツを宣言する
翻訳を保存するためのコンテンツ宣言を作成して管理します:
import { t, type DeclarationContent } from "intlayer";
const pageContent = {
key: "page",
content: {
getStarted: {
main: t({
ja: "編集を始めるには",
fr: "Commencez par éditer",
es: "Comience por editar",
}),
pageLink: "src/app/page.tsx",
},
},
} satisfies DeclarationContent;
export default pageContent;
コンテンツ宣言は、アプリケーション内の任意の場所で定義できますが、contentDirディレクトリに含まれている必要があります(デフォルトは./src)。また、コンテンツ宣言ファイルの拡張子と一致する必要があります(デフォルトは.content.{ts,tsx,js,jsx,mjs,cjs})。 詳細については、コンテンツ宣言のドキュメントを参照してください。
ステップ7: コード内のコンテンツを利用
アプリケーション全体でコンテンツ辞書にアクセスします:
import type { FC } from "react";
import { ClientComponentExample } from "@components/ClientComponentExample";
import { ServerComponentExample } from "@components/ServerComponentExample";
import { type NextPageIntlayer, IntlayerClientProvider } from "next-intlayer";
import { IntlayerServerProvider, useIntlayer } from "next-intlayer/server";
const PageContent: FC = () => {
const { title, content } = useIntlayer("page");
return (
<>
<p>{content.getStarted.main}</p>
<code>{content.getStarted.pageLink}</code>
</>
);
};
const Page: NextPageIntlayer = async ({ params }) => {
const { locale } = await params;
return (
<>
<IntlayerServerProvider locale={locale}>
<PageContent />
<ServerComponentExample />
<IntlayerClientProvider locale={locale}>
<ClientComponentExample />
</IntlayerClientProvider>
</IntlayerServerProvider>
</>
);
};
export default Page;
- IntlayerClientProviderは、クライアントサイドコンポーネントにロケールを提供するために使用されます。親コンポーネントの中であれば、どこにでも配置できますが、レイアウトに配置することが推奨されます。これにより、Next.jsはページ間でレイアウトコードを共有し、効率が向上します。レイアウトでIntlayerClientProviderを使用すると、各ページで再初期化することを避け、パフォーマンスが向上し、アプリケーション全体で一貫したローカライズコンテキストを維持できます。
IntlayerServerProviderは、サーバーの子要素にロケールを提供するために使用されます。レイアウト内で設定することはできません。
レイアウトとページで共通のサーバーコンテキストを共有することはできません。なぜなら、サーバーコンテキストシステムはリクエストごとのデータストア(Reactのキャッシュメカニズム経由)のために基づいているからです。これにより、アプリケーションの異なるセグメントに対して各「コンテキスト」が再作成されます。プロバイダを共有レイアウトに配置すると、この隔離が壊れ、サーバーコンテキストの値がサーバーコンポーネントに正しく伝播されなくなります。
"use client";
import type { FC } from "react";
import { useIntlayer } from "next-intlayer";
export const ClientComponentExample: FC = () => {
const content = useIntlayer("client-component-example"); // 関連するコンテンツ宣言を作成
return (
<div>
<h2>{content.title} </h2>
<p>{content.content}</p>
</div>
);
};
import type { FC } from "react";
import { useIntlayer } from "next-intlayer/server";
export const ServerComponentExample: FC = () => {
const content = useIntlayer("server-component-example"); // 関連するコンテンツ宣言を作成
return (
<div>
<h2>{content.title} </h2>
<p>{content.content}</p>
</div>
);
};
もし、alt、title、href、aria-labelなどのstring属性でコンテンツを使用したい場合は、関数の値を呼び出す必要があります。例えば:
jsx<img src={content.image.src.value} alt={content.image.value} />
useIntlayerフックの詳細については、ドキュメントを参照してください。
(オプション) ステップ8: メタデータの国際化
ページのタイトルなどのメタデータを国際化したい場合は、Next.jsが提供するgenerateMetadata関数を使用できます。この関数の中でgetTranslationContent関数を使用してメタデータを翻訳します。
import {
type IConfigLocales,
getTranslationContent,
getMultilingualUrls,
} from "intlayer";
import type { Metadata } from "next";
import type { LocalParams } from "next-intlayer";
export const generateMetadata = ({
params: { locale },
}: LocalParams): Metadata => {
const t = <T>(content: IConfigLocales<T>) =>
getTranslationContent(content, locale);
/**
* 各ロケールのすべてのURLを含むオブジェクトを生成します。
*
* 例:
* ```ts
* getMultilingualUrls('/about');
*
* // 返り値
* // {
* // ja: '/about',
* // fr: '/fr/about',
* // es: '/es/about',
* // }
* ```
*/
const multilingualUrls = getMultilingualUrls("/");
return {
title: t<string>({
ja: "私のタイトル",
fr: "Mon titre",
es: "Mi título",
}),
description: t({
ja: "私の説明",
fr: "Ma description",
es: "Mi descripción",
}),
alternates: {
canonical: "/",
languages: { ...multilingualUrls, "x-default": "/" },
},
openGraph: {
url: multilingualUrls[locale],
},
};
};
// ... 後のコード
メタデータの最適化については、Next.jsの公式ドキュメントを参照してください。
(オプション) ステップ9: sitemap.xmlとrobots.txtの国際化
sitemap.xmlとrobots.txtを国際化するために、Intlayerが提供するgetMultilingualUrls関数を使用できます。この関数を用いることで、サイトマップ用の多言語URLを生成できます。
import { getMultilingualUrls } from "intlayer";
import type { MetadataRoute } from "next";
const sitemap = (): MetadataRoute.Sitemap => [
{
url: "https://example.com",
alternates: {
languages: getMultilingualUrls("https://example.com"),
},
},
{
url: "https://example.com/login",
alternates: {
languages: getMultilingualUrls("https://example.com/login"),
},
},
{
url: "https://example.com/register",
alternates: {
languages: getMultilingualUrls("https://example.com/register"),
},
},
];
export default sitemap;
import type { MetadataRoute } from "next";
import { getMultilingualUrls } from "intlayer";
const getAllMultilingualUrls = (urls: string[]) =>
urls.flatMap((url) => Object.values(getMultilingualUrls(url)) as string[]);
const robots = (): MetadataRoute.Robots => ({
rules: {
userAgent: "*",
allow: ["/"],
disallow: getAllMultilingualUrls(["/login", "/register"]),
},
host: "https://example.com",
sitemap: `https://example.com/sitemap.xml`,
});
export default robots;
サイトマップの最適化に関する詳細は、Next.jsの公式ドキュメントを参照してください。robots.txtの最適化に関する詳細は、Next.jsの公式ドキュメントを参照してください。
(オプション) ステップ10: コンテンツの言語を変更
コンテンツの言語を変更するには、useLocaleフックが提供するsetLocale関数を使用できます。この関数を使用すると、アプリケーションのロケールを設定し、それに応じてコンテンツを更新できます。
"use client";
import type { FC } from "react";
import {
Locales,
getHTMLTextDir,
getLocaleName,
getLocalizedUrl,
} from "intlayer";
import { useLocale } from "next-intlayer";
import Link from "next/link";
export const LocaleSwitcher: FC = () => {
const { locale, pathWithoutLocale, availableLocales, setLocale } =
useLocale();
return (
<ol>
{availableLocales.map((localeItem) => (
<li key={localeItem}>
<Link
href={getLocalizedUrl(pathWithoutLocale, localeItem)}
hrefLang={localeItem}
aria-current={locale === localeItem ? "page" : undefined}
onClick={(e) => {
e.preventDefault();
setLocale(localeItem);
}}
>
<span>
{/* 自国のロケールでの言語名 - 例: 日本語 */}
{getLocaleName(localeItem, locale)}
</span>
<span dir={getHTMLTextDir(localeItem)} lang={localeItem}>
{/* 現在のロケールでの言語名 - 例: 日本語がLocales.SPANISHに設定されているときのEspañol */}
{getLocaleName(localeItem)}
</span>
<span dir="ltr" lang={Locales.ENGLISH}>
{/* 英語での言語名 - 例: Japanese */}
{getLocaleName(localeItem, Locales.ENGLISH)}
</span>
<span>
{/* 自国のロケールでの言語名 - 例: JA */}
{localeItem}
</span>
</Link>
</li>
))}
</ol>
);
};
ドキュメント参照:
TypeScriptの設定
Intlayerは、TypeScriptの利点を活用し、コードベースを強化するためにモジュール拡張を使用します。
TypeScript設定に自動生成された型が含まれていることを確認してください。
{
// ... 既存のTypeScript構成
"include": [
// ... 既存のTypeScript構成
"types", // 自動生成された型を含める
],
}
Gitの設定
Intlayerによって生成されたファイルを無視することが推奨されます。これにより、それらをGitリポジトリにコミットすることを避けることができます。
これを行うには、.gitignoreファイルに次の指示を追加します:
# Intlayerによって生成されたファイルを無視
.intlayer
このドキュメントを改善するアイデアがある場合は、GitHubでプルリクエストを送信することで自由に貢献してください。
ドキュメントへのGitHubリンク