🌐

コンポーネント単位での多言語管理を可能にする”Intlayer”

に公開
3

こんにちは。AI ShiftでWebフロントエンドエンジニアをしている安井です。今回はコンポーネント単位での多言語対応を行うIntlayerというライブラリを触った感想を整理したいと思います。

https://github.com/aymericzip/intlayer?tab=readme-ov-file

はじめに

多言語対応は様々なプロダクトにおいて必要になる機能です。その一方で、リリース後のコンテンツ更新やUI変更が頻繁な場合は、継続的な管理が大きな負担となりがちです。

Reactで多言語対応をする際によく利用されるライブラリとしてreact-i18nextが挙げられます。react-i18nextはi18nextのReact拡張で豊富なプラグインエコシステムに支えられたライブラリという印象を持っています。今回はこのreact-i18nextとの比較を踏まえて解説します。

https://react.i18next.com/

*多言語対応のライブラリの1つとして検討をしている段階で、実際にプロダクトに組み込んでいる状況ではありません。

前提

多言語対応の実装については誰が管理するのか、どのような方法で提供するのかによって前提が大きく変わってきます。そのため、本記事では以下の前提に従って解説します。

  1. 多言語対応の管理者は開発者自身

プロダクトによっては多言語対応の文言をエンジニア以外のメンバーが責任を持つケースがあります。その場合は文言ファイルの管理に対して開発者以外の体験を考慮する必要が生じるため、ここでは開発者自身が多言語対応の文言に責任を持つ組織を想定します。

  1. パスによる多言語のルーティングはしない

https://homepage/enといったパスに多言語情報を含める実装は、検索エンジンが各言語コンテンツを正確に認識・インデックスし、適切なユーザーに最適なページを表示するのに役立ちます。しかし、AI ShiftのようなBtoBのサービスではSEOを意識する必要はないため、ここではSPAの構成でReact + Viteを前提に、状態管理で多言語情報を切り替える実装を想定します。

react-i18nextで感じていた課題

まずは私が以前から使用していたreact-i18nextで感じていた課題を整理します。

JSON形式による多言語ファイルの管理

1つ目が、「JSON形式による多言語ファイルの管理」です。

Exampleにもあるように、react-i18nextではJSONファイルで多言語文言を管理し、resourcesに追加することで多言語対応が可能になります。補足として、yamlでも多言語文言の管理は可能です。

https://github.com/i18next/react-i18next/blob/v15.6.0/example/react-typescript/simple/src/i18n/en/translation.json

https://github.com/i18next/react-i18next/blob/v15.6.0/example/react-typescript/simple/src/i18n/config.ts

JSON形式による多言語ファイル管理の課題感として、一方の多言語ファイルに不足があっても認識することが難しい点があります。

日本語と英語の多言語対応を想定した場合、日本語(ja.json)で新たに追加した文言を英語(en.json)に追加し忘れる可能性が考えられます。そのような不足があったとしても、開発時に気づくこともできなければ、ランタイムでエラーが発生することもないため、QAの負担が増加してしまいます。

この課題はTypeScriptで多言語ファイルを管理することによって解決できます。日本語を正とするケースでは日本語の多言語ファイルを軸に型アノテーションすることで他言語ファイルの構造を型レベルで保証できます。

ja.ts
const ja = {
  common: {
    hello: "こんにちは",
    goodbye: "さようなら",
  },
};
en.ts
const en: typeof ja = {
  common: {
    hello: "Hello",
    // goodbyeが不足していると型エラーになる
    // goodbye: "Goodbye", 
  },
};

i18n-allyのVSCode拡張機能がTypeScript未対応

一見この運用方法によって問題は解消するかと思われるのですが、i18n-allyのVSCode拡張機能がTypeScript未対応であるという課題が残っていました。

https://github.com/lokalise/i18n-ally

i18n-allyはVSCodeの拡張機能で、添付画像のようにtfunctionを使用した箇所で多言語内容をプレビューしてくれます。また、tfunctionの中の文字列リテラルから多言語ファイルの該当箇所にコードジャンプすることもできます。


https://github.com/lokalise/i18n-ally/wiki#inline-annotations

特に後者の文字列リテラルから多言語ファイルの該当箇所にコードジャンプできる機能に関しては、多言語対応開発における必須の体験だと考えています。

多言語ファイルの中央管理

2つ目が、「多言語ファイルの中央管理」です。

react-i18nextのExampleなどを見ると、中央に配置された多言語ファイルをまとめるディレクトリ(/i18n)に各言語ごとで多言語ファイルを配置していました。

https://github.com/i18next/react-i18next/blob/v15.6.0/example/react-typescript/simple/src/i18n/en/translation.json

確かに、アプリケーションのページが少ないうちはこの実装でも問題はないですが、数十、数百ページと増えた際にその分だけ多言語情報も増加することが予想されます。

もし、各言語ごとに1ファイルでまとめて文言を管理していると膨大なコード量になり管理しきれなくなることが想像できます。react-i18nextにはnamespaceの機能があるため、一定スコープを閉じた管理もできますが、最終的にはnamespaceで分割したファイルの数だけconfigファイルでimportし、resourcesへの追加が発生します。

https://www.i18next.com/principles/namespaces

https://github.com/i18next/i18next/blob/master/examples/typescript/i18n/config.ts#L5-L15

このようにreact-i18nextでの多言語対応にはいくつかの課題点を感じており、特に開発初期は問題ないものの長期的なスケールを考えると解決するべきポイントが見られました。

Intlayerでコンポーネント単位での多言語対応を行う

そんな中で私が個人的に注目しているのがIntlayerです。まずは、ドキュメントに沿ってその使用方法を簡単に整理します。

https://intlayer.org/ja/doc/concept/how-works-intlayer

Intlayerはコンポーネントごとのコンテンツ管理を基本にしているため、コンポーネントファイルの隣に*.content.tsというファイル命名で多言語ファイルを配置します。(contentという命名規則は変更可能です)

.
└── Components
    └── MyComponent
        ├── index.content.ts
        └── index.tsx

するとIntlayerがBuild時に対象のディレクトリ内の多言語ファイル(*.content.ts)を探索して、.intlayer/dictionariesに辞書ファイルを作成します。同時に多言語ファイルから型定義(.intlayer/types)を生成することによってアプリケーションで型安全に多言語対応をすることが可能になります。

ではこの前提で特徴を整理します。

1. TypeScript Firstで型安全性が高い

Intlayerでは下記のような記法で多言語ファイルを管理します。

*.content.ts
import { t, type Dictionary } from "intlayer";

const componentContent = {
  key: "app",
  content: {
    greeting: t({
      en: "Hello World",
      fr: "Bonjour le monde",
      es: "Hola Mundo",
    }),
  },
} satisfies Dictionary;

export default componentContent;

コンポーネントで使用する際には、useIntlayerhookの引数に対象のkey名を指定することで型安全にコンテンツを使用することが可能になります。

app.tsx
const AppContent: FC = () => {
  const content = useIntlayer("app");

  return (
    <>
      <h1>{content.greeting}</h1>
    </>
  );
};

IntlayerはTypeScript Firstで型安全に多言語ファイルを管理できるため、先ほどJSONファイルによる管理で発生していた文言の過不足によるバグが発生しづらくなります。

2. コンポーネントにCo-Locateした多言語管理が可能

2つ目のIntlayerの特徴はコンポーネントにCo-Locateした管理が可能になる点です。仮に多言語ファイルを中央で管理している場合、以下のように実際に使用したいコンポーネントと多言語ファイルが離れてしまって関心が分散してしまいます。

.
├── Components
│   └── MyComponent
│       └── index.tsx // 多言語コンテンツを使用
└── i18n
    ├── en.json // 多言語コンテンツを追加
    └── ja.json // 多言語コンテンツを追加

一方でコンポーネントにCo-Locateした多言語管理をする場合、CSS Moduleのように多言語ファイルを管理できるような感覚を抱いており、コンポーネントに対して関連の高い多言語情報をより関心を近く保つことができると考えています。

.
└── Components
    └── MyComponent
        ├── index.content.ts // 多言語コンテンツを追加
        └── index.tsx // 多言語コンテンツを使用

もちろん、すべての多言語情報がコンポーネント単位で分散してしまうと、共通管理したい文言が複製されてしまいます。そのような場合でも、下記の例のようにfeature単位で文言を共通化するなど適切なスコープで多言語ファイルをまとめることもできるので、非常に柔軟性を感じています。

.
└── Features
    └── auth
        ├── i18n
        |   └── auth.content.ts // featureで共通化した多言語コンテンツを追加
        └── Components
            └── MyComponent
                ├── index.content.ts // 多言語コンテンツを追加
                └── index.tsx // 多言語コンテンツを使用

3. アプリケーションのバンドルサイズを最適化

最後がアプリケーションのバンドルサイズ最適化です。前述したようなJSONファイルで一元管理している場合では、肥大化した多言語情報が分割されることなくLoadされてしまうケースがあります。

一方でIntlayerは@intlayer/babelのプラグインによってチャンクの最適化とバンドルサイズの削減を行ってくれるため、不要にファイルがLoadされる課題を解決できます。

他にも様々な利点がドキュメントには整理されています。

https://intlayer.org/ja/doc/concept/interest

補足

これまでで解説した通り、TypeScript Firstでコンポーネント単位の多言語管理を可能にするIntlayerですがプロダクトで採用するには懸念点があります。

一つ目が、実運用で必要になる機能がやや不足しているように感じる点です。例えば、2025/07現在だと下記の例のような動的にコンテンツを表示させることができません。これは、IntlayerがBuild時に全ての多言語ファイルをJSON形式で変換してしまうためです。

訂正(2025/07/31):上記のように動的にコンテンツを表示させるためにはインサーション(insertion)を使用することで対応が可能でした。

https://intlayer.org/ja/doc/concept/content/insertion

二つ目が、個人OSSのためContributeが属人化しており、まだStar数も多くない点です。一方で私が既存プロジェクトをIntlayerに移行するテストをした際には、問題なく移行ができたことからも現時点でプロダクションで利用しても十分な感覚はあります。

https://github.com/aymericzip/intlayer/graphs/contributors

まとめ

今回はIntlayerという多言語管理ライブラリについての紹介をしました。その際にreact-i18nextとの比較を行いましたが、やはりまだライブラリとしてのメンテナンス性やプラグインエコシステムの充実度などを見るとreact-i18nextに対しての安心感を感じる部分はあります。

一方で、コンポーネントごとのコンテンツ管理TypeScript Firstな型安全性アプリケーションビルドの最適化などは実際に試しても魅力に感じるポイントでした。

AI Shift Tech Blog

Discussion

aymericzipaymericzip

Ytaisei、シェアしてくれてありがとう!🫶
あなたの開発プロセスを加速できるツールを作れることを本当に願っています。

フィードバックお待ちしています!GitHubでのサポートもよろしくお願いします ⭐️

[このメッセージはAIによって翻訳されました]

aymericzipaymericzip

いくつか補足です:

2 - functionTest: (name) => \Hi ${name}`` は、Intlayer では インサーション(insertion) と呼ばれています。

3 - YAMLでのコンテンツ定義はまもなく対応予定です

どんなフィードバックや機能のアイデアでも大歓迎です!
しっかり時間をかけて実装していきます 💡

ytaisei(たいせー)ytaisei(たいせー)

日本語で失礼します!
コメントいただきありがとうござます!

また、Intlayerの設計思想がとてもいいなと思い、今回記事で取り上げさせていただきました

2 - functionTest: (name) => \Hi ${name}`` は、Intlayer では インサーション(insertion) と呼ばれています。

インサーション(insertion)の実装については知りませんでした!
こちら記事の方も訂正させていただきます