LoginSignup
3
2

Next.jsのアプリを国際化対応する

Last updated at Posted at 2023-07-28

こんにちは。dendeです。

今回はNext.js製のアプリを国際化対応したので、その備忘録です。

SEO対策やアドセンス審査でも英語のサイトが有利ということで、私のアプリも対応させることにしました!

Re:teratureという小説作成アプリを公開しています。

今回は色々調べましたが、汎用性の高そうな下記の記事の方法を参考させて頂きました。

参考記事

Next.jsで多言語対応のサイトを作るのが簡単すぎた件
たった10分で Next.js アプリを日本語対応させた話
Next.jsでi18n対応する方法

i18nのルーティング設定

国際化対応のためのi18nNext.jsにビルトインされていますのでそれを使います。

公式

特に特別なライブラリをインストールするわけではなく、next.congig.jsに設定を追加するだけで利用できます。

// next.config.js
module.exports = {
  i18n: {
    locales: ['en', 'ja'],
    defaultLocale: 'en',
  },
}

上記のように設定するとルーティングの際にロケールが判定されます。

例えばRe:teratureのトップにアクセスする場合

https://novel-editor-ver2.vercel.app/ja/

https://novel-editor-ver2.vercel.app/en/

というパスアクセスされるようになります。

useRouterでロケールを判定するカスタムフックを使う

色々調べると、Next.js用のライブラリを使った方法が良く出てきます。

Next.jsでi18n対応する方法

こちらも試しましたが、今回紹介するカスタムフックを使った方法が簡単に実装できて特に余計なライブラリをインストールする必要がないのでそちらを実施します。

カスタムフックの詳細は下記の記事を参考にしています。

たった10分でNext.jsアプリを日本語対応させた話

カスタムフックのコード

import { useRouter } from "next/router";
import en from "../../locales/en/en";
import ja from "../../locales/ja/ja";

export const useLocale = () => {
	const { locale } = useRouter();
	const t = locale === "en" ? en : ja;
	return { locale, t };
};

上記のカスタムフックはuseRouterを使用してロケールを取得し、その取得したロケール、もしくはインポートした翻訳を定義したオブジェクトtとして返すカスタムフックです。

翻訳ファイルはそれぞれ下記のように作成

///locales/ja/ja.ts
export default {
	errorPage: {
		error: "送信エラーが発生しました。",
		afterShortTime: "暫く経ってからお問い合わせください。"
	},

///locales/en/en.ts
export default {
	errorPage: {
		error: "A transmission error has occurred.",
		afterShortTime: "Please contact us after a while."
	},

ページでカスタムフックを使ってt.errorPage.errorとオブジェクトへアクセス

import { Heading, Text } from "@chakra-ui/react";
import { useLocale } from "../hooks/useLocale";

export default function Error() {
	const { t } = useLocale();
	return (
		<>
				 <Heading as="h1" fontSize="3xl" mb="4">
						Error!
					</Heading>
					<Text>{t.errorPage.error}</Text>
					<Text>{t.errorPage.afterShortTime}</Text>
		</>
	);
}

ちなみにこんな感じで日本語と英語のコンポーネントをあらかじめ二つ作って出し分けも使えます。

import { EnPolicy } from "../components/policy/EnPolicy";
import { JaPolicy } from "../components/policy/JaPolicy";
import { useLocale } from "../hooks/useLocale";

export default function PrivacyPolicy() {
	const { locale } = useLocale();

	return (
		<>
			{locale === "ja" && <JaPolicy />}
			{locale === "en" && <EnPolicy />}
		</>
	);
}

上記はPolicyのページで、文章量が多く一つ一つの置き換えが大変+普段あまり更新しない箇所ですので全部まとめて翻訳したコンポーネントにしてしまいました。

ISRSSGなどでダイナミックルーティングを利用する場合

こちらは私のサイトだと該当しないため実際に行っていませんが、参考した記事の中で解説されています。

Next.jsで多言語対応のサイトを作るのが簡単すぎた件

以下引用

getStaticPropsを使ってる場合は以下のようにpathsを余計に返すことに注意する必要がありました。

// 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' },
      { params: { slug: 'post-1' }, locale: 'ja' },
    ],
    fallback: true,
  }
}

以下のように初めに一つの言語でpathを作っておいてそれを元に別の言語を複製する方法が楽でおすすめです。

export const getStaticPaths: GetStaticPaths = async () => {
  const paths = categories.map(c => ({
    params: {
      slug: c.slug as string,
    },
    locale: 'ja',
  }))
  // 英語に対してもpathを作成
  paths.push(...paths.map(p => ({ ...p, locale: 'en' })))

  return {
    paths,
    fallback: false
  }
}

最後にアプリ紹介

ここまで読んで頂いた方はありがとうございました

最後に公開しているアプリを載せておきますのでもしよろしければ拝見いただき、改善のアドバイスなど頂けると幸いです。

小説作成アプリ『Re:terature

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2