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 を含めることは良い習慣となります。
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 を置く。
module.exports = {
i18n: {
locales: ['en-US', 'fr', 'nl-NL'],
defaultLocale: 'en-US',
},
}
上記の設定では、en-US
、fr
、nl-NL
がルーティング可能となり、en-US
が default locale となります。pages/blog.js
がある場合、以下の URL が利用可能になります:
/blog
/fr/blog
/nl-nl/blog
default の localedefault locale には接頭辞がありません。
ドメインルーティング
domain routing を使用することで、異なる domains から locales を配信するように設定できます。
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 が意図的に追加されていることに注意してください。
module.exports = {
i18n: {
locales: ['default', 'en', 'de', 'fr'],
defaultLocale: 'default',
localeDetection: false,
},
trailingSlash: true,
}
次に、Middlewareを使用してカスタムルーティングルールを追加することができます:
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 Routesやpublicファイル(フォントや画像など)への default プレフィックスの追加をスキップします。 default locale への request があった場合、私たちは /en
のプレフィックスへ redirect します。
自動 Locale 検出の無効化
自動的な locale 検出は次のように無効にすることができます:
module.exports = {
i18n: {
localeDetection: false,
},
}
localeDetection
がfalse
に設定されているとき、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>
);
}
Leveraging the NEXT_LOCALE
cookie
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 Routes で getStaticProps
を使用しているページでは、事前レンダリングを希望するページのすべての locale バリエーションがgetStaticPaths
から返される必要があります。paths
のparams
object と共に、render したい locale を指定するlocale
フィールドを返すこともできます。例えば:
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 の localesdomains
: 合計 100 の locale ドメインアイテム
Good to know: この制限は、最初に build 時の潜在的なパフォーマンス問題を防ぐために追加されました。 Next.js 12 では、Middlewareを使ったカスタムルーティングでこれらの制限を回避することができます。