このページのコンテンツはAIを使用して翻訳されました。

    英語の元のコンテンツの最新バージョンを見る

    Getting Started Internationalizing (i18n) with Intlayer and Next.js using Page Router

    Intlayerとは?

    Intlayerは、モダンなWebアプリケーションにおける多言語対応を簡素化するために設計された、革新的でオープンソースの国際化(i18n)ライブラリです。Intlayerは、従来のPage Routerを含む最新のNext.jsフレームワークとシームレスに統合されます。

    Intlayerを使用すると、以下のことが可能です:

    • コンポーネントレベルで宣言的な辞書を使用して簡単に翻訳を管理
    • メタデータ、ルート、コンテンツを動的にローカライズ
    • 自動生成された型によるTypeScriptサポートで、オートコンプリートとエラー検出を向上。
    • 動的なロケール検出や切り替えなどの高度な機能を活用。

    IntlayerはNext.js 12、13、14、15に対応しています。Next.js App Routerを使用している場合は、App Routerガイドを参照してください。Next.js 15の場合は、このガイドを参照してください。


    Page Routerを使用したNext.jsアプリケーションでのIntlayerセットアップ手順

    ステップ1: 依存関係をインストール

    お好みのパッケージマネージャーを使用して必要なパッケージをインストールします:

    bash
    npm install intlayer next-intlayer
    • intlayer

      設定管理、翻訳、コンテンツ宣言、トランスパイル、CLIコマンドを提供する国際化ツールのコアパッケージ。

    • next-intlayer

      IntlayerをNext.jsと統合するためのパッケージ。Next.jsの国際化のためのコンテキストプロバイダーとフックを提供します。また、IntlayerをWebpackまたはTurbopackと統合するためのNext.jsプラグインや、ユーザーの優先ロケールを検出し、クッキーを管理し、URLリダイレクションを処理するためのミドルウェアも含まれています。

    ステップ2: プロジェクトを設定

    アプリケーションでサポートされる言語を定義する設定ファイルを作成します:

    intlayer.config.ts
    import { Locales, type IntlayerConfig } from "intlayer";const config: IntlayerConfig = {  internationalization: {    locales: [      Locales.ENGLISH,      Locales.FRENCH,      Locales.SPANISH,      // 他のロケールをここに追加    ],    defaultLocale: Locales.ENGLISH,  },};export default config;

    この設定ファイルを通じて、ローカライズされたURL、ミドルウェアリダイレクション、クッキー名、コンテンツ宣言の場所と拡張子、コンソールでのIntlayerログの無効化などを設定できます。利用可能なパラメータの完全なリストについては、設定ドキュメントを参照してください。

    ステップ3: Next.js設定にIntlayerを統合

    Next.js設定を変更してIntlayerを組み込みます:

    next.config.mjs
    import { withIntlayer } from "next-intlayer/server";/** @type {import('next').NextConfig} */const nextConfig = {  // 既存のNext.js設定};export default withIntlayer(nextConfig);

    withIntlayer() Next.jsプラグインは、IntlayerをNext.jsと統合するために使用されます。コンテンツ宣言ファイルのビルドを保証し、開発モードでそれらを監視します。WebpackまたはTurbopack環境内でIntlayer環境変数を定義します。また、パフォーマンスを最適化するエイリアスを提供し、サーバーコンポーネントとの互換性を保証します。

    ステップ4: ロケール検出のためのミドルウェアを設定

    ユーザーの優先ロケールを自動的に検出して処理するミドルウェアを設定します:

    src/middleware.ts
    export { intlayerMiddleware as middleware } from "next-intlayer/middleware";export const config = {  matcher:    "/((?!api|static|assets|robots|sitemap|sw|service-worker|manifest|.*\..*|_next).*)",};

    matcherパラメータをアプリケーションのルートに合わせて調整してください。詳細については、Next.jsのミドルウェア設定に関するドキュメントを参照してください。

    ステップ5: 動的ロケールルートを定義

    ユーザーのロケールに基づいてローカライズされたコンテンツを提供するための動的ルーティングを実装します。

    1. ロケール固有のページを作成:

      メインページファイルの名前を[locale]動的セグメントを含むように変更します。

      bash
      mv src/pages/index.tsx src/pages/[locale]/index.tsx
    2. _app.tsxをローカリゼーションに対応:

      _app.tsxを変更してIntlayerプロバイダーを含めます。

      src/pages/_app.tsx
      import type { FC } from "react";import type { AppProps } from "next/app";import { IntlayerClientProvider } from "next-intlayer";const App = FC<AppProps>({ Component, pageProps }) => {  const { locale } = pageProps;  return (    <IntlayerClientProvider locale={locale}>      <Component {...pageProps} />    </IntlayerClientProvider>  );}export default MyApp;
    3. getStaticPathsgetStaticPropsを設定:

      [locale]/index.tsxで、異なるロケールを処理するためのパスとプロップスを定義します。

      src/pages/[locale]/index.tsx
      import type { FC } from "react";import type { GetStaticPaths, GetStaticProps } from "next";import { type Locales, getConfiguration } from "intlayer";const HomePage: FC = () => <div>{/* コンテンツをここに記述 */}</div>;export const getStaticPaths: GetStaticPaths = () => {  const { internationalization } = getConfiguration();  const { locales } = internationalization;  const paths = locales.map((locale) => ({    params: { locale },  }));  return { paths, fallback: false };};export const getStaticProps: GetStaticProps = ({ params }) => {  const locale = params?.locale as string;  return {    props: {      locale,    },  };};export default HomePage;

    getStaticPathsgetStaticPropsは、Next.js Page Routerでアプリケーションがすべてのロケールに必要なページを事前にビルドすることを保証します。このアプローチは、実行時の計算を減らし、ユーザーエクスペリエンスを向上させます。詳細については、Next.jsのgetStaticPathsgetStaticPropsに関するドキュメントを参照してください。

    ステップ6: コンテンツを宣言

    翻訳を保存するためのコンテンツ宣言を作成して管理します。

    src/pages/[locale]/home.content.ts
    import { t, type Dictionary } from "intlayer";const homeContent = {  key: "home",  content: {    title: t({      en: "Welcome to My Website",      fr: "Bienvenue sur mon site Web",      es: "Bienvenido a mi sitio web",    }),    description: t({      en: "Get started by editing this page.",      fr: "Commencez par éditer cette page.",      es: "Comience por editar esta página.",    }),  },} satisfies Dictionary;export default homeContent;

    コンテンツ宣言に関する詳細は、コンテンツ宣言ガイドを参照してください。

    ステップ7: コード内でコンテンツを利用

    アプリケーション全体でコンテンツ辞書にアクセスして翻訳されたコンテンツを表示します。

    src/pages/[locale]/index.tsx
    import type { FC } from "react";import { useIntlayer } from "next-intlayer";import { ComponentExample } from "@components/ComponentExample";const HomePage: FC = () => {  const content = useIntlayer("home");  return (    <div>      <h1>{content.title}</h1>      <p>{content.description}</p>      <ComponentExample />      {/* 他のコンポーネント */}    </div>  );};// ... 残りのコード(getStaticPathsとgetStaticPropsを含む)export default HomePage;
    src/components/ComponentExample.tsx
    import type { FC } from "react";import { useIntlayer } from "next-intlayer";export const ComponentExample: FC = () => {  const content = useIntlayer("component-example"); // 対応するコンテンツ宣言があることを確認  return (    <div>      <h2>{content.title}</h2>      <p>{content.content}</p>    </div>  );};

    string属性(例:alttitlehrefaria-label)で翻訳を使用する場合、次のように値を呼び出します:

    jsx
    <img src={content.image.src.value} alt={content.image.value} />

    useIntlayerフックの詳細については、ドキュメントを参照してください。

    (オプション) ステップ8: メタデータを国際化

    ページタイトルや説明などのメタデータを国際化するには、IntlayerのgetTranslation関数とgetStaticProps関数を組み合わせて使用します。

    src/pages/[locale]/index.tsx
    import { GetStaticPaths, GetStaticProps } from "next";import { type IConfigLocales, getTranslation, Locales } from "intlayer";import { useIntlayer } from "next-intlayer";interface HomePageProps {  locale: string;  metadata: Metadata;}const HomePage = ({ metadata }: HomePageProps) => {  // メタデータは必要に応じてheadや他のコンポーネントで使用可能  return (    <div>      <Head>        <title>{metadata.title}</title>        <meta name="description" content={metadata.description} />      </Head>      {/* 追加コンテンツ */}    </div>  );};export const getStaticProps: GetStaticProps = async ({ params }) => {  const locale = params?.locale as string;  const t = <T,>(content: IConfigLocales<T>) => getTranslation(content, locale);  const metadata = {    title: t({      en: "My Website",      fr: "Mon Site Web",      es: "Mi Sitio Web",    }),    description: t({      en: "Welcome to my website.",      fr: "Bienvenue sur mon site Web.",      es: "Bienvenido a mi sitio web.",    }),  };  return {    props: {      locale,      metadata,    },  };};export default HomePage;// ... 残りのコード(getStaticPathsを含む)

    (オプション) ステップ9: コンテンツの言語を変更

    ユーザーが動的に言語を切り替えられるようにするには、useLocaleフックが提供するsetLocale関数を使用します。

    src/components/LanguageSwitcher.tsx
    import {  Locales,  getHTMLTextDir,  getLocaleName,  getLocalizedUrl,} from "intlayer";import { useLocalePageRouter } from "next-intlayer";import { type FC } from "react";import Link from "next/link";const LocaleSwitcher: FC = () => {  const { locale, pathWithoutLocale, availableLocales, setLocale } =    useLocalePageRouter();  return (    <div>      <button popoverTarget="localePopover">{getLocaleName(locale)}</button>      <div id="localePopover" popover="auto">        {availableLocales.map((localeItem) => (          <Link            href={getLocalizedUrl(pathWithoutLocale, localeItem)}            hrefLang={localeItem}            key={localeItem}            aria-current={locale === localeItem ? "page" : undefined}            onClick={(e) => {              e.preventDefault();              setLocale(localeItem);            }}          >            <span>              {/* ロケール - 例: FR */}              {localeItem}            </span>            <span>              {/* 自身のロケールでの言語 - 例: Français */}              {getLocaleName(localeItem, locale)}            </span>            <span dir={getHTMLTextDir(localeItem)} lang={localeItem}>              {/* 現在のロケールでの言語 - 例: Francés(現在のロケールがLocales.SPANISHの場合) */}              {getLocaleName(localeItem)}            </span>            <span dir="ltr" lang={Locales.ENGLISH}>              {/* 英語での言語 - 例: French */}              {getLocaleName(localeItem, Locales.ENGLISH)}            </span>          </Link>        ))}      </div>    </div>  );};

    useLocalePageRouter APIはuseLocaleと同じです。useLocaleフックの詳細については、ドキュメントを参照してください。

    ドキュメント参照:

    (オプション) ステップ10: ローカライズされたリンクコンポーネントの作成

    アプリケーションのナビゲーションが現在のロケールを尊重するようにするために、カスタムLinkコンポーネントを作成します。このコンポーネントは、内部URLを自動的に現在の言語でプレフィックスします。たとえば、フランス語を話すユーザーが「About」ページへのリンクをクリックすると、/aboutではなく/fr/aboutにリダイレクトされます。

    この動作は以下の理由で役立ちます:

    • SEOとユーザーエクスペリエンス:ローカライズされたURLは、検索エンジンが言語固有のページを正しくインデックスし、ユーザーに好みの言語でコンテンツを提供するのに役立ちます。
    • 一貫性:アプリケーション全体でローカライズされたリンクを使用することで、ナビゲーションが現在のロケール内に留まり、予期しない言語切り替えを防ぎます。
    • 保守性:ローカライズロジックを1つのコンポーネントに集中させることで、URLの管理が簡素化され、アプリケーションが成長するにつれてコードベースの保守性が向上します。

    以下は、TypeScriptでのローカライズされたLinkコンポーネントの実装です:

    src/components/Link.tsx
    "use client";import { getLocalizedUrl } from "intlayer";import NextLink, { type LinkProps as NextLinkProps } from "next/link";import { useLocale } from "next-intlayer";import { forwardRef, PropsWithChildren, type ForwardedRef } from "react";/** * 指定されたURLが外部リンクかどうかを確認するユーティリティ関数。 * URLがhttp://またはhttps://で始まる場合、外部リンクと見なされます。 */export const checkIsExternalLink = (href?: string): boolean =>  /^https?:///.test(href ?? "");/** * 現在のロケールに基づいてhref属性を適応させるカスタムLinkコンポーネント。 * 内部リンクの場合、`getLocalizedUrl`を使用してURLにロケールをプレフィックスします(例:/fr/about)。 * これにより、ナビゲーションが同じロケールコンテキスト内に留まることが保証されます。 */export const Link = forwardRef<  HTMLAnchorElement,  PropsWithChildren<NextLinkProps>>(({ href, children, ...props }, ref: ForwardedRef<HTMLAnchorElement>) => {  const { locale } = useLocale();  const isExternalLink = checkIsExternalLink(href.toString());  // リンクが内部リンクで有効なhrefが提供されている場合、ローカライズされたURLを取得します。  const hrefI18n: NextLinkProps["href"] =    href && !isExternalLink ? getLocalizedUrl(href.toString(), locale) : href;  return (    <NextLink href={hrefI18n} ref={ref} {...props}>      {children}    </NextLink>  );});Link.displayName = "Link";

    動作の仕組み

    • 外部リンクの検出
      ヘルパー関数checkIsExternalLinkは、URLが外部リンクかどうかを判定します。外部リンクはローカライズを必要としないため、そのままにしておきます。

    • 現在のロケールの取得
      useLocaleフックは現在のロケール(例:フランス語の場合はfr)を提供します。

    • URLのローカライズ
      内部リンク(つまり外部ではないリンク)の場合、getLocalizedUrlを使用してURLに現在のロケールを自動的にプレフィックスします。これにより、ユーザーがフランス語を使用している場合、/abouthrefとして渡すと、/fr/aboutに変換されます。

    • リンクの返却
      コンポーネントはローカライズされたURLを持つ<a>要素を返し、ナビゲーションがロケールと一貫性を保つことを保証します。

    このLinkコンポーネントをアプリケーション全体で統合することで、言語に配慮した一貫性のあるユーザーエクスペリエンスを維持しながら、SEOと使いやすさを向上させることができます。

    TypeScriptを設定

    Intlayerはモジュール拡張を使用してTypeScriptの利点を活用し、コードベースを強化します。

    alt text

    alt text

    自動生成された型を含めるようにTypeScript設定を確認してください。

    tsconfig.json
    {  // ... 既存のTypeScript設定  "include": [    // ... 既存のTypeScript設定    ".intlayer/**/*.ts", // 自動生成された型を含める  ],}

    Git設定

    リポジトリをクリーンに保ち、生成されたファイルをコミットしないようにするには、Intlayerによって作成されたファイルを無視することをお勧めします。

    以下の行を.gitignoreファイルに追加してください:

    .gitignore
    # Intlayerによって生成されたファイルを無視.intlayer

    追加リソース

    このガイドに従うことで、IntlayerをNext.jsアプリケーションに効果的に統合し、Webプロジェクトに対して堅牢でスケーラブルな国際化サポートを実現できます。

    さらに進む

    さらに進むために、ビジュアルエディタを実装するか、CMSを使用してコンテンツを外部化することができます。

    このドキュメントを改善するアイデアがある場合は、GitHubでプルリクエストを送信することで自由に貢献してください。

    ドキュメントへのGitHubリンク