【Next.js + TypeScript】多言語対応(i18n)のやり方

本記事ではNext.jsのv10から組み込まれた国際化(i18n)用ルーティング機能を使って、オーソドックスに自前で翻訳ファイルを作成して多言語対応させる方法の一例を紹介します。

多言語対応にあたり翻訳ファイルをどのように持たせるかは色々やり方があると思いますが、Railsのように言語毎に翻訳ファイルを作る方法は翻訳ファイルが分散してしまい管理がたいへんです(以下は言語毎の翻訳ファイルの一例)。

# 日本語用翻訳ファイル(ja.json)
{
    "GREETING": "おはよう"
}

# 英語用翻訳ファイル(en.json)
{
    "GREETING": "hello"
}

 

そこで本記事では次のように1ファイルに翻訳情報を登録することにします。

# 日本語/英語用翻訳ファイル(langDict.json)
{
    "GREETING": {
        "ja": "おはよう",
        "en": "hello"
    }
}

 

なおNext.jsのi18nに関する公式ドキュメントは以下になります。

Next.js has built-in support for internationalized routing a…

 

ソフトウェア・バージョン

Next.js 10.2.3
React 17.0.2
TypeScript 4.3.2

 

next.config.jsの作成

Next.jsプロジェクトのルートディレクトリに「next.config.js」を作成して下記のように記述します。

Next.jsには「サブパス・ルーティング」と「ドメイン・ルーティング」の2種類あって、前者は「http://example.com/ja」や「http://example.com/en」のようにURLのディレクトリ部分でルーティングを切り分けられます。対して、後者は「http://ja.example.com/」や「http://en.example.com/」のようにドメインでルーティングを切り分けます。以下の記述だけだとサブパス・ルーティングになります(公式ドキュメント)。これに加えて「domains」についての記述を加えるとドメイン・ルーティングになります(公式ドキュメント)。

module.exports = {
  i18n: {
    locales: ['ja', 'en'],
    defaultLocale: 'ja',
  },
};

 

上記ではデフォルト・ロケールをja(日本語)に指定しているので、例えば「http://example.com/blog」は日本語ロケールになります。対して英語ロケールは「http://example.com/en/blog」のようにプレフィックス(en)が追加されます。

 

翻訳オブジェクトを取得する関数の作成

上記で紹介した日本語/英語用翻訳ファイル(langDict.json)をそのまま使ってもよいのですが、利用する際に簡単に呼び出せるように指定の言語に絞った翻訳オブジェクトを返す関数を次のように作成します。

import langsDict from './langDict.json';

// 翻訳ファイルのキーの型を取得
type KeyType = keyof typeof langsDict;

const getLangDict = (lang: 'ja' | 'en') => {
  // 引数の言語に絞った翻訳情報を格納する変数
  let langDict = {} as { [key in KeyType]: string };

  for (const key in langsDict) {
    langDict = { ...langDict, [key]: langsDict[key as KeyType][lang] };
  }

  return langDict;
};

export default getLangDict;

 

この関数は引数で例えば’ja’を渡してやると以下のような日本語だけに絞った翻訳情報(オブジェクト)を返します。利用する側はオブジェクトのキーを指定するだけで翻訳できます。

{
    GREETING: 'おはよう'
}

 

ロケールを識別して翻訳オブジェクトを返すカスタムフックの作成

ユーザーのロケールを取得して上記で作成した関数を使って翻訳オブジェクトを返すカスタムフックを次のように作成します。

Next.jsから提供されているフック(useRouter)を使えば簡単にロケールを取得できます(公式ドキュメント)。取得したロケールを先ほど作成した関数に渡して翻訳オブジェクトをreturnしています。

import { useRouter } from 'next/router';
import getLangDict from './getLangDict';

const useTranslate = () => {
  const { locale } = useRouter();
  return locale === 'ja' ? getLangDict('ja') : getLangDict('en');
};

export default useTranslate;

 

翻訳機能のコンポーネントでの利用

最後にコンポーネントで翻訳機能を組み込みます。

コンポーネントでは先ほど作ったカスタムフックを呼び出すことでロケールに応じた翻訳オブジェクトを取得できます。あとはオブジェクトのキーを指定すれば適切に翻訳された文字列を取得できます。

import React from 'react';
import useTranslate from './useTranslate';

const Home: React.FC = () => {
  const t = useTranslate();

  return (
    <h1>{t.GREETING}</h1>
  );
};

export default Home;

 

まとめ

Next.jsのv10から提供されたi18n用の機能を使えば外部モジュールを使わなくても手軽に国際化できるようになりました。

本記事ではその機能を使って翻訳ファイルを自作して多言語対応する方法の一例を示しました。もっと効率的なやり方もありますが、とっかかりの参考になれば幸いです。

sponsor