0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

ぼっちアドベントカレンダー by bon10Advent Calendar 2024

Day 12

Next.js14 App Routerでi18nをしようとしているのならnext-intlのほうがよさそう

Last updated at Posted at 2024-12-12

結論

設計思想にこだわりがないのならApp Router + SSR のi18n対応はnext-intl が楽だと思います。
zod を使ってバリデーションもi18n対応場合は next-i18next のほうが親和性は高いですが、工夫次第で next-intl でも問題なし。


Next.jsでi18nするぞーとなってググったとき、最初に見つかったのが next-i18next でした。このときは next-intl の存在すら知らずreact-i18next と何が違うかわからんけどnextだしいっか、と使い始め、結果良くできてたライブラリで安心してました。

ここまではいいんです。問題はApp Routerです。

App Router with SSR

next-i18next自体はSSRでのレンダリングに対応しているらしいのですが、素人TypeScriptエンジニアである私からすると、設定方法がよくわからず大変そうだなという印象でした。(そもそもSSRとCSR/SSGの根本の違いを理解していない前提もあり)

結果的にプロエンジニアの力を借りて実装そのものはできたのですが、自分が理解するまでに骨が折れそうだなと今は思っています。

そして実際骨が折れつつもこの課題について素晴らしくまとめてある記事もあります。

代替手段 next-intl

これからi18n対応するという前提で、もう少し楽にi18nする方法はないのかなと改めて検索すると、以下のWebサイトが引っかかりました。

先程のZennの記事と似てるのですが、こちらは多言語ファイルをWebで管理できる i18nexus というツールのチュートリアル記事のようでした。
ここに見覚えのない単語があります。

それが 「next-intl」 Who Are You?

Githubのスター数は現時点(2024/12)で3Kほど next-i18next のほうが上ですが、Googleトレンドではすでに next-intl のほうが上です。

image.png

おそらく導入時、SSG/SSRによって実装手順に大きな違いがないという容易性がウケてるんだと思います。(少なくとも私は簡単だなと感じました)
これはi18nexusのチュートリアルをみても自明だと思います。

SSRでさえ以下のように宣言するだけで、SSGと同じように非同期翻訳が使えます。

const t = await getTranslations("Week");

参考:

Zodのバリデーションとi18n対応

別の観点としてよく使うユースケースだと思われる Zod のバリデーションを多言語化するという例で next-i18nextnext-intl を比較してみます。

Zodのi18nは以下で対応されています。

exampleにあるように、 next-i18next での使い方は以下のような感じです。

const { t } = useTranslation();
z.setErrorMap(makeZodI18nMap({ t }));

が、これをそのままApp Routerで使うことはできません。先述どおりSSR用の useTranslation を自分で実装・定義する必要があります。

next-intl はどうでしょうか。
こちらは標準で zod-i18n には対応していないため、以下のブログのように組み込み方を少し工夫する必要があります。

どちらも一長一短ありますが、個人的には next-intl だと 項目名のi18nも簡単そうにみえますね。
例えば入力欄ではなく、画面上部にエラーメッセージをまとめて表示するというユースケースのとき、「username は必須です」と出力されるよりも「ユーザー名は必須です」と出てほしいっていうやつです。 ここでの username は以下のようなZodのスキーマを前提としたときのキー名です。

const schema = z.object({
  username: z.string().min(3),
  age: z.number().min(18),
});

まとめ

Next.jsでのi18n対応に1つ選択肢が増えたので、プロダクトの方向性やエンジニアチームの趣味趣向、アーキテクチャの具合や今後を踏まえてどちらかを選択すると良いかと思います。
色々面倒なことを省き、これからのエコシステムの発展に期待するという側面では、 next-intl が有利かなと個人的には思います。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?