Lang x Lang

Internationalization (i18n) Routing

Examples

Next.js は、v10.0.0から国際化された(i18n )ルーティングを組み込みサポートしています。locales のリスト、default locale、ドメイン固有の locales を提供でき、Next.js は自動的にルーティングを処理します。

現在、i18n library ルーティングサポートは、react-intl react-i18next lingui rosetta next-intl next-translate next-multilingual tolgee などの既存の i18n ライブラリソリューションを補完することを目的としています。routes および locale の解析を合理化します。

Getting started

始めるには、i18nの config をあなたのnext.config.jsファイルに追加してください。

Locales はUTS Locale Identifiers として、locales を定義するための標準化された形式です。

一般的に、Locale 識別子は言語、地域、スクリプトから成り、ダッシュで区切られます:language-region-script。地域とスクリプトはオプションです。例:

  • en-US - アメリカ合衆国で話される英語
  • nl-NL - オランダで話されるオランダ語
  • nl - オランダ語、特定の地域なし

もしユーザーの locale が nl-BEで、それが設定に記載されていない場合、利用可能であれば nlにリダイレクトされ、そうでない場合は default locale にリダイレクトされます。国のすべての地域をサポートするつもりがない場合、フォールバックとして機能する国の locales を含めることは良い習慣となります。

next.config.js
module.exports = {
  i18n: {
    // These are all the locales you want to support in
    // your application
    locales: ['en-US', 'fr', 'nl-NL'],
    // This is the default locale you want to be used when visiting
    // a non-locale prefixed path e.g. `/hello`
    defaultLocale: 'en-US',
    // This is a list of locale domains and the default locale they
    // should handle (these are only required when setting up domain routing)
    // Note: subdomains must be included in the domain value to be matched e.g. "fr.example.com".
    domains: [
      {
        domain: 'example.com',
        defaultLocale: 'en-US',
      },
      {
        domain: 'example.nl',
        defaultLocale: 'nl-NL',
      },
      {
        domain: 'example.fr',
        defaultLocale: 'fr',
        // an optional http field can also be used to test
        // locale domains locally with http instead of https
        http: true,
      },
    ],
  },
}

Locale Strategies

次の二つの locale 取り扱い戦略があります: サブ path ルーティングとドメインルーティング。

サブ path ルーティング

サブ path ルーティングは、url path の中に locale を置く。

next.config.js
module.exports = {
  i18n: {
    locales: ['en-US', 'fr', 'nl-NL'],
    defaultLocale: 'en-US',
  },
}

上記の設定では、en-USfrnl-NLがルーティング可能となり、en-USが default locale となります。pages/blog.jsがある場合、以下の URL が利用可能になります:

  • /blog
  • /fr/blog
  • /nl-nl/blog

default の localedefault locale には接頭辞がありません。

ドメインルーティング

domain routing を使用することで、異なる domains から locales を配信するように設定できます。

next.config.js
module.exports = {
  i18n: {
    locales: ['en-US', 'fr', 'nl-NL', 'nl-BE'],
    defaultLocale: 'en-US',

    domains: [
      {
        // Note: subdomains must be included in the domain value to be matched
        // e.g. www.example.com should be used if that is the expected hostname
        domain: 'example.com',
        defaultLocale: 'en-US',
      },
      {
        domain: 'example.fr',
        defaultLocale: 'fr',
      },
      {
        domain: 'example.nl',
        defaultLocale: 'nl-NL',
        // specify other locales that should be redirected
        // to this domain
        locales: ['nl-BE'],
      },
    ],
  },
}

たとえば、あなたが pages/blog.jsを持っている場合、以下の URL が利用可能になります。

  • example.com/blog
  • www.example.com/blog
  • example.fr/blog
  • example.nl/blog
  • example.nl/nl-BE/blog

Automatic Locale Detection

ユーザーがアプリケーションの root(一般的には/)を訪れると、 Next.js は Accept-Language header と現在のドメインに基づいて、ユーザーが好む locale を自動的に検出しようとします。

default locale 以外の locale が検出された場合、ユーザーは次のいずれかに Redirect されます:

  • サブパスルーティングを使用する場合: locale 接頭辞付きの path
  • ドメインルーティングを使用する場合: その locale が default として指定されたドメイン

Domain Routing を使用すると、Accept-Language header fr;q=0.9を持つユーザーが example.comを訪れると、そのドメインが fr locale を default で処理するため、example.frに redirect されます。

Sub-path Routing を使用すると、ユーザーは/frに Redirect されます。

Default Locale を接頭辞としてつける

Next.js 12 とMiddlewareを使用すると、workaround で default locale に接頭辞を追加することができます。

例えば、いくつかの言語をサポートするnext.config.jsファイルがあります。"default" locale が意図的に追加されていることに注意してください。

next.config.js
module.exports = {
  i18n: {
    locales: ['default', 'en', 'de', 'fr'],
    defaultLocale: 'default',
    localeDetection: false,
  },
  trailingSlash: true,
}

次に、Middlewareを使用してカスタムルーティングルールを追加することができます:

middleware.ts
import { NextRequest, NextResponse } from 'next/server'

const PUBLIC_FILE = /\.(.*)$/

export async function middleware(req: NextRequest) {
  if (
    req.nextUrl.pathname.startsWith('/_next') ||
    req.nextUrl.pathname.includes('/api/') ||
    PUBLIC_FILE.test(req.nextUrl.pathname)
  ) {
    return
  }

  if (req.nextUrl.locale === 'default') {
    const locale = req.cookies.get('NEXT_LOCALE')?.value || 'en'

    return NextResponse.redirect(
      new URL(`/${locale}${req.nextUrl.pathname}${req.nextUrl.search}`, req.url)
    )
  }
}

この Middlewareは、API Routespublicファイル(フォントや画像など)への default プレフィックスの追加をスキップします。 default locale への request があった場合、私たちは /enのプレフィックスへ redirect します。

自動 Locale 検出の無効化

自動的な locale 検出は次のように無効にすることができます:

next.config.js
module.exports = {
  i18n: {
    localeDetection: false,
  },
}

localeDetectionfalseに設定されているとき、Next.js はもはやユーザーの優先 locale に基づいて自動的に redirect することはなく、上記のように、locale ベースのドメインまたは locale path から検出された locale 情報のみを提供します。

Accessing the locale information

Next.js router を通じて locale 情報にアクセスすることができます。例えば、useRouter() hook を使用すると以下のプロパティが利用可能になります:

  • localeは現在有効な locale を含んでいます。
  • localesは、設定されたすべての locales を含んでいます。
  • defaultLocaleは設定された default locale を含んでいます。

getStaticPropsまたはgetServerSidePropsを使用して事前レンダリングページを作成する際、locale 情報は、関数に提供されたcontext内に提供されます。

getStaticPathsを利用する際、設定された locales は関数のlocales内の context パラメータに提供され、設定された defaultLocale はdefaultLocaleの下に提供されます。

Transition between locales

あなたはnext/linkまたはnext/routerを使用して、locales 間の遷移ができます。

next/linkには、locale prop を提供して、現在アクティブなものから異なる locale に遷移することができます。locale prop が提供されていない場合、クライアント遷移中に現在アクティブなlocaleが使用されます。例えば:

import Link from "next/link";

export default function IndexPage(props) {
  return (
    <Link href="/another" locale="fr">
      To /fr/another
    </Link>
  );
}

next/router の Method を直接使用するとき、遷移 options を介して使用するべき locale を指定できます。例えば:

import { useRouter } from "next/router";

export default function IndexPage(props) {
  const router = useRouter();

  return (
    <div
      onClick={() => {
        router.push("/another", "/another", { locale: "fr" });
      }}
    >
      to /fr/another
    </div>
  );
}

localeの切り替えのみを扱うために、dynamic routeの query 値や非表示の href query 値など、すべてのルーティング情報を保持することができます。hrefパラメータを object として提供することができます。注意してください:

import { useRouter } from "next/router";
const router = useRouter();
const { pathname, asPath, query } = router;
// change just the locale and maintain all other route information including href's query
router.push({ pathname, query }, asPath, { locale: nextLocale });

詳細な情報や、router.push用の object 構造については、こちらを参照してください。

あなたがすでに locale を含むhrefを持っている場合、locale のプレフィックスを自動的に処理するのをオプトアウトすることができます。

import Link from "next/link";

export default function IndexPage(props) {
  return (
    <Link href="/fr/another" locale={false}>
      To /fr/another
    </Link>
  );
}

Next.js は accept-language の header を NEXT_LOCALE=the-locale の cookie で上書きすることをサポートします。この cookie は言語スイッチャーを使用して設定でき、そしてユーザーがサイトに戻ってきたときに、/から正しい locale の場所へ Redirect する際に、cookie に指定された locale を活用します。

たとえば、ユーザーが accept-language の header でfrの locale を優先している場合でも、NEXT_LOCALE=enの cookie が設定されていると、/にアクセスするときはenの locale に Redirect されます。そして、その cookie が削除されるか、有効期限が切れるまではenの locale の位置に Redirect され続けます。

Search Engine Optimization

Next.js はユーザーが訪れている言語を認識しているので、自動的にlang属性を<html>タグに追加します。

Next.js はページのバリエーションについて認識していませんので、hreflang meta タグを next/headを使って追加するのはあなたの役割です。hreflang については、 Google ウェブマスタードキュメント で詳しく学ぶことができます。

How does this work with Static Generation?

Internationalized Routing は output: 'export'と統合されません。それは Next.js のルーティング層を利用していないからです。output: 'export'を使用しないハイブリッド Next.js アプリケーションは完全にサポートされています。ということに注意してください。

Dynamic Routes と getStaticProps ページ

Dynamic RoutesgetStaticPropsを使用しているページでは、事前レンダリングを希望するページのすべての locale バリエーションがgetStaticPathsから返される必要があります。pathsparams object と共に、render したい locale を指定するlocaleフィールドを返すこともできます。例えば:

pages/blog/[slug].js
export const getStaticPaths = ({ locales }) => {
  return {
    paths: [
      // if no `locale` is provided only the defaultLocale will be generated
      { params: { slug: 'post-1' }, locale: 'en-US' },
      { params: { slug: 'post-1' }, locale: 'fr' },
    ],
    fallback: true,
  }
}

Automatically Statically Optimized または非動的な getStaticProps ページについては、ページの各 locales に対してversion のページが生成されます。これは重要なことです。なぜなら、getStaticProps 内で設定されている locale の数によって build の時間が長くなることがあるからです。

例えば、50 の locales が設定されており、10 の非動的なページでgetStaticPropsを使用している場合、これはgetStaticPropsが 500 回呼び出されることを意味します。10 ページの 50Version が、各 build 中に生成されます。

getStaticPropsを使用して build 時間を減らすために、fallback モードを使用します。これにより、getStaticPathsから最も人気のある paths や locales のみを build 時にプレ rendering するために返すことができます。その後、Next.js は request に応じて runtime で残りのページを build します。

自動的に静的に最適化されたページ

自動的に静的に最適化されるページでは、各 locale のページの version が生成されます。

非 Dynamic な getStaticProps ページ

非ダイナミックな getStaticProps ページでは、上記のように各 locale ごとに version が生成されます。 getStaticPropsは、レンダリングされる各 localeで呼び出されます。特定の locale をプレレンダリングから除外したい場合は、 getStaticPropsから notFound: trueを返すことで、そのページのバリアントは生成されません。

export async function getStaticProps({ locale }) {
  // Call an external API endpoint to get posts.
  // You can use any data fetching library
  const res = await fetch(`https://.../posts?locale=${locale}`);
  const posts = await res.json();

  if (posts.length === 0) {
    return {
      notFound: true,
    };
  }

  // By returning { props: posts }, the Blog component
  // will receive `posts` as a prop at build time
  return {
    props: {
      posts,
    },
  };
}

Limits for the i18n config

  • locales: 合計 100 の locales
  • domains: 合計 100 の locale ドメインアイテム

Good to know: この制限は、最初に build 時の潜在的なパフォーマンス問題を防ぐために追加されました。 Next.js 12 では、Middlewareを使ったカスタムルーティングでこれらの制限を回避することができます。

当社サイトでは、Cookie を使用しています。各規約をご確認の上ご利用ください:
Cookie Policy, Privacy Policy および Terms of Use