Next.js で国際化を実装する方法
Next.js は v10.0.0 以降、国際化 ( i18n ) ルーティングを組み込みでサポートしています。ロケールのリスト、デフォルトロケール、ドメイン固有のロケールを提供すると、Next.js がルーティングを自動的に処理します。
i18n ルーティングサポートは、現在、react-intl、react-i18next、lingui、rosetta、next-intl、next-translate、next-multilingual、tolgee、paraglide-next、next-intlayer、gt-react、その他多くのライブラリを、ルーティングとロケール解析の合理化によって補完することを目的としています。
はじめに
開始するには、next.config.js ファイルに i18n 設定を追加します。
ロケールは、UTS ロケール識別子 です。これはロケールを定義するための標準化された形式です。
通常、ロケール識別子は、言語、地域、スクリプトをダッシュで区切ったものです: language-region-script。地域とスクリプトはオプションです。例:
en-US- アメリカ合衆国で話されている英語nl-NL- オランダで話されているオランダ語nl- オランダ語、地域指定なし
ユーザーのロケールが nl-BE で、設定に含まれていない場合、利用可能な nl にリダイレクトされるか、それでも見つからない場合はデフォルトロケールにリダイレクトされます。国のすべての地域をサポートしない場合は、フォールバックとして機能する国ロケールを含めることが良い習慣です。
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,
},
],
},
}ロケール戦略
ロケール処理戦略は 2 つあります: サブパスルーティングとドメインルーティングです。
サブパスルーティング
サブパスルーティングでは、URL パスにロケールが配置されます。
module.exports = {
i18n: {
locales: ['en-US', 'fr', 'nl-NL'],
defaultLocale: 'en-US',
},
}上記の構成 en-US、fr、nl-NL でルーティング可能になり、en-US がデフォルトロケールです。pages/blog.js がある場合、次の URL が利用可能になります。
/blog/fr/blog/nl-nl/blog
デフォルトロケールにはプレフィックスがありません。
ドメインルーティング
ドメインルーティングを使用することで、異なるドメインからロケールを提供できるように設定できます。
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/blogwww.example.com/blogexample.fr/blogexample.nl/blogexample.nl/nl-BE/blog
自動ロケール検出
ユーザーがアプリケーションのルート (通常は /) にアクセスすると、Next.js は Accept-Language ヘッダー と現在のドメインに基づいて、ユーザーが好むロケールを自動的に検出しようとします。
デフォルトロケール以外のロケールが検出された場合、ユーザーは以下にリダイレクトされます。
- サブパスルーティングを使用する場合: ロケールプレフィックス付きのパス
- ドメインルーティングを使用する場合: そのロケールがデフォルトとして指定されたドメイン
ドメインルーティングを使用する場合、Accept-Language ヘッダーが fr;q=0.9 のユーザーが example.com にアクセスすると、そのドメインがデフォルトで fr ロケールを処理するため、example.fr にリダイレクトされます。
サブパスルーティングを使用する場合、ユーザーは /fr にリダイレクトされます。
デフォルトロケールのプレフィックス
Next.js 12 と Proxy により、デフォルトロケールにカスタムプレフィックスを追加できます。回避策。
例えば、いくつかの言語をサポートする next.config.js ファイルを次に示します。"default" ロケールが意図的に追加されていることに注意してください。
module.exports = {
i18n: {
locales: ['default', 'en', 'de', 'fr'],
defaultLocale: 'default',
localeDetection: false,
},
trailingSlash: true,
}次に、Proxy を使用してカスタムルーティングルールを追加できます。
import { NextRequest, NextResponse } from 'next/server'
const PUBLIC_FILE = /\.(.*)$/
export async function proxy(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)
)
}
}このProxyは、API Routes および public ファイル (フォントや画像など) へのデフォルトプレフィックスの追加をスキップします。デフォルトロケールへのリクエストがあった場合、プレフィックス /en にリダイレクトします。
自動ロケール検出の無効化
自動ロケール検出は、以下で無効にできます。
module.exports = {
i18n: {
localeDetection: false,
},
}localeDetection が false に設定されている場合、Next.js はユーザーの好みのロケールに基づいて自動的にリダイレクトしなくなり、上記で説明したロケールベースのドメインまたはロケールパスから検出されたロケール情報のみを提供します。
ロケール情報のアクセス
Next.js ルーターからロケール情報にアクセスできます。例えば、useRouter() フックを使用すると、次のプロパティが利用可能になります。
locale: 現在アクティブなロケールが含まれています。locales: 設定されているすべてのロケールが含まれています。defaultLocale: 設定されているデフォルトロケールが含まれています。
getStaticProps または getServerSideProps を使用してページをプリレンダリングする場合、ロケール情報は関数に渡されるコンテキストで提供されます。
getStaticPaths を利用する場合、設定されたロケールは、関数のコンテキストパラメータの locales および設定された defaultLocale の下で提供されます。
ロケールの切り替え
next/link または next/router を使用してロケールを切り替えることができます。
next/link の場合、現在アクティブなロケールから別のロケールに切り替えるために locale プロップを提供できます。locale プロップが提供されていない場合、クライアント遷移中に現在アクティブな locale が使用されます。例:
import Link from 'next/link'
export default function IndexPage(props) {
return (
<Link href="/another" locale="fr">
To /fr/another
</Link>
)
}next/router メソッドを直接使用する場合、遷移オプションを通じて使用される 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 のみを切り替えて、動的ルートのクエリ値や非表示の href クエリ値などのルーティング情報をすべて維持するには、href パラメータをオブジェクトとして提供できることに注意してください。
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 のオブジェクト構造の詳細については、こちらを参照してください。
すでにロケールが含まれている href がある場合、ロケールプレフィックスの自動処理をオプトアウトできます。
import Link from 'next/link'
export default function IndexPage(props) {
return (
<Link href="/fr/another" locale={false}>
To /fr/another
</Link>
)
}NEXT_LOCALE Cookie の活用
Next.js では、NEXT_LOCALE=the-locale Cookie を設定できます。これは accept-language ヘッダーよりも優先されます。この Cookie は言語セレクターを使用して設定でき、ユーザーがサイトに戻ってきたときに、/ から正しいロケール場所へのリダイレクト時に Cookie に指定されたロケールを活用します。
例えば、ユーザーが accept-language ヘッダーで fr ロケールを好むが、NEXT_LOCALE=en Cookie が設定されている場合、/ にアクセスしたときに en ロケールが使用され、Cookie が削除または期限切れになるまで en ロケール場所にリダイレクトされます。
検索エンジン最適化
Next.js はユーザーがどの言語でアクセスしているかを知っているため、<html> タグに自動的に lang 属性を追加します。
Next.js はページのバリエーションを認識しないため、next/head を使用して hreflang メタタグを追加するのはユーザーの責任です。hreflang についての詳細は、Google Search Console のドキュメント を参照してください。
静的生成との連携方法
国際化ルーティングは
output: 'export'と統合されません。これは Next.js ルーティングレイヤーを利用しないためです。output: 'export'を使用しないハイブリッド Next.js アプリケーションは完全にサポートされています。
動的ルーティングと getStaticProps ページ
getStaticProps と動的ルーティングを使用するページの場合、プリレンダリングしたいすべてのロケールバリエーションは、getStaticPaths から返される必要があります。paths の params オブジェクトに加えて、レンダリングしたいロケールを指定する 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,
}
}自動静的最適化 されたページおよび非動的 getStaticProps ページの場合、各ロケールに対してページのバージョンが生成されます。これは、getStaticProps 内で設定されているロケールの数によっては、ビルド時間が長くなる可能性があるため、考慮することが重要です。
例えば、50 のロケールが設定されており、10 の非動的ページが getStaticProps を使用している場合、getStaticProps は 500 回呼び出されます。10 ページのうち 50 バージョンが各ビルド中に生成されます。
getStaticProps を使用する動的ページのビルド時間を短縮するには、fallback モードを使用します。これにより、ビルド中にプリレンダリングする最も人気のあるパスとロケールのみを getStaticPaths から返すことができます。その後、Next.js はリクエストされたときに残りのページをランタイムでビルドします。
自動静的最適化ページ
自動静的最適化 されたページの場合、各ロケールに対してページのバージョンが生成されます。
非動的 getStaticProps ページ
非動的 getStaticProps ページの場合、上記のように各ロケールに対してバージョンが生成されます。getStaticProps は、レンダリングされる各 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,
},
}
}i18n 設定の制限
locales: 合計 100 ロケールdomains: 合計 100 ロケールドメイン項目
知っておくと便利: これらの制限は、ビルド時のパフォーマンスの問題を防ぐために当初追加されました。Next.js 12 の Proxy を使用したカスタムルーティングで、これらの制限を回避できます。
役に立ちましたか?