@intlayer/docs 8.9.4-canary.0 → 8.9.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/generated/docs.entry.cjs +20 -0
- package/dist/cjs/generated/docs.entry.cjs.map +1 -1
- package/dist/esm/generated/docs.entry.mjs +20 -0
- package/dist/esm/generated/docs.entry.mjs.map +1 -1
- package/dist/types/generated/docs.entry.d.ts +1 -0
- package/dist/types/generated/docs.entry.d.ts.map +1 -1
- package/docs/ar/benchmark/index.md +0 -3
- package/docs/ar/benchmark/nextjs.md +15 -6
- package/docs/ar/benchmark/solid.md +155 -0
- package/docs/ar/benchmark/svelte.md +148 -0
- package/docs/ar/benchmark/tanstack.md +12 -3
- package/docs/ar/benchmark/vue.md +160 -0
- package/docs/ar/configuration.md +16 -12
- package/docs/ar/dictionary/content_file.md +51 -1
- package/docs/ar/mcp_server.md +30 -17
- package/docs/ar/plugins/sync-po.md +333 -0
- package/docs/bn/configuration.md +16 -12
- package/docs/cs/configuration.md +16 -12
- package/docs/de/benchmark/index.md +0 -3
- package/docs/de/benchmark/nextjs.md +15 -6
- package/docs/de/benchmark/solid.md +155 -0
- package/docs/de/benchmark/svelte.md +148 -0
- package/docs/de/benchmark/tanstack.md +12 -3
- package/docs/de/benchmark/vue.md +160 -0
- package/docs/de/configuration.md +16 -12
- package/docs/de/dictionary/content_file.md +52 -2
- package/docs/de/mcp_server.md +29 -16
- package/docs/de/plugins/sync-po.md +332 -0
- package/docs/en/benchmark/nextjs.md +11 -2
- package/docs/en/benchmark/solid.md +22 -4
- package/docs/en/benchmark/svelte.md +17 -5
- package/docs/en/benchmark/tanstack.md +18 -3
- package/docs/en/benchmark/vue.md +17 -11
- package/docs/en/configuration.md +16 -13
- package/docs/en/dictionary/content_file.md +51 -1
- package/docs/en/mcp_server.md +31 -18
- package/docs/en/plugins/sync-po.md +333 -0
- package/docs/en-GB/benchmark/index.md +0 -3
- package/docs/en-GB/benchmark/nextjs.md +15 -6
- package/docs/en-GB/benchmark/solid.md +155 -0
- package/docs/en-GB/benchmark/svelte.md +148 -0
- package/docs/en-GB/benchmark/tanstack.md +12 -3
- package/docs/en-GB/benchmark/vue.md +160 -0
- package/docs/en-GB/configuration.md +15 -11
- package/docs/en-GB/dictionary/content_file.md +51 -1
- package/docs/en-GB/mcp_server.md +31 -18
- package/docs/en-GB/plugins/sync-po.md +333 -0
- package/docs/es/benchmark/index.md +0 -3
- package/docs/es/benchmark/nextjs.md +15 -6
- package/docs/es/benchmark/solid.md +155 -0
- package/docs/es/benchmark/svelte.md +148 -0
- package/docs/es/benchmark/tanstack.md +12 -3
- package/docs/es/benchmark/vue.md +160 -0
- package/docs/es/configuration.md +16 -12
- package/docs/es/dictionary/content_file.md +51 -1
- package/docs/es/mcp_server.md +30 -17
- package/docs/es/plugins/sync-po.md +333 -0
- package/docs/fr/benchmark/index.md +0 -3
- package/docs/fr/benchmark/nextjs.md +15 -6
- package/docs/fr/benchmark/solid.md +155 -0
- package/docs/fr/benchmark/svelte.md +148 -0
- package/docs/fr/benchmark/tanstack.md +12 -3
- package/docs/fr/benchmark/vue.md +160 -0
- package/docs/fr/configuration.md +16 -12
- package/docs/fr/dictionary/content_file.md +51 -1
- package/docs/fr/mcp_server.md +30 -17
- package/docs/fr/plugins/sync-po.md +333 -0
- package/docs/hi/benchmark/nextjs.md +15 -6
- package/docs/hi/benchmark/solid.md +155 -0
- package/docs/hi/benchmark/svelte.md +148 -0
- package/docs/hi/benchmark/tanstack.md +12 -3
- package/docs/hi/benchmark/vue.md +160 -0
- package/docs/hi/configuration.md +16 -12
- package/docs/hi/dictionary/content_file.md +51 -1
- package/docs/hi/mcp_server.md +31 -18
- package/docs/hi/plugins/sync-po.md +333 -0
- package/docs/id/benchmark/index.md +0 -3
- package/docs/id/benchmark/nextjs.md +15 -6
- package/docs/id/benchmark/solid.md +155 -0
- package/docs/id/benchmark/svelte.md +148 -0
- package/docs/id/benchmark/tanstack.md +12 -3
- package/docs/id/benchmark/vue.md +160 -0
- package/docs/id/configuration.md +16 -12
- package/docs/id/dictionary/content_file.md +51 -1
- package/docs/id/mcp_server.md +30 -17
- package/docs/id/plugins/sync-po.md +333 -0
- package/docs/it/benchmark/index.md +1 -4
- package/docs/it/benchmark/nextjs.md +15 -6
- package/docs/it/benchmark/solid.md +155 -0
- package/docs/it/benchmark/svelte.md +148 -0
- package/docs/it/benchmark/tanstack.md +12 -3
- package/docs/it/benchmark/vue.md +160 -0
- package/docs/it/configuration.md +16 -12
- package/docs/it/dictionary/content_file.md +51 -1
- package/docs/it/mcp_server.md +30 -17
- package/docs/it/plugins/sync-po.md +333 -0
- package/docs/ja/benchmark/index.md +5 -5
- package/docs/ja/benchmark/nextjs.md +15 -6
- package/docs/ja/benchmark/solid.md +155 -0
- package/docs/ja/benchmark/svelte.md +148 -0
- package/docs/ja/benchmark/tanstack.md +12 -3
- package/docs/ja/benchmark/vue.md +160 -0
- package/docs/ja/configuration.md +16 -12
- package/docs/ja/dictionary/content_file.md +50 -2
- package/docs/ja/intlayer_with_nextjs_no_locale_path.md +4 -3
- package/docs/ja/mcp_server.md +29 -16
- package/docs/ja/plugins/sync-po.md +333 -0
- package/docs/ko/benchmark/nextjs.md +15 -6
- package/docs/ko/benchmark/solid.md +155 -0
- package/docs/ko/benchmark/svelte.md +148 -0
- package/docs/ko/benchmark/tanstack.md +12 -3
- package/docs/ko/benchmark/vue.md +160 -0
- package/docs/ko/configuration.md +16 -12
- package/docs/ko/dictionary/content_file.md +51 -1
- package/docs/ko/intlayer_with_nextjs_no_locale_path.md +3 -2
- package/docs/ko/mcp_server.md +31 -18
- package/docs/ko/plugins/sync-po.md +333 -0
- package/docs/nl/configuration.md +16 -12
- package/docs/pl/benchmark/index.md +0 -3
- package/docs/pl/benchmark/nextjs.md +15 -6
- package/docs/pl/benchmark/solid.md +155 -0
- package/docs/pl/benchmark/svelte.md +148 -0
- package/docs/pl/benchmark/tanstack.md +12 -3
- package/docs/pl/benchmark/vue.md +160 -0
- package/docs/pl/configuration.md +16 -12
- package/docs/pl/dictionary/content_file.md +51 -1
- package/docs/pl/mcp_server.md +30 -17
- package/docs/pl/plugins/sync-po.md +333 -0
- package/docs/pt/benchmark/index.md +0 -3
- package/docs/pt/benchmark/nextjs.md +16 -7
- package/docs/pt/benchmark/solid.md +155 -0
- package/docs/pt/benchmark/svelte.md +148 -0
- package/docs/pt/benchmark/tanstack.md +13 -4
- package/docs/pt/benchmark/vue.md +160 -0
- package/docs/pt/configuration.md +16 -12
- package/docs/pt/dictionary/content_file.md +51 -1
- package/docs/pt/mcp_server.md +30 -17
- package/docs/pt/plugins/sync-po.md +333 -0
- package/docs/ru/benchmark/nextjs.md +15 -6
- package/docs/ru/benchmark/solid.md +155 -0
- package/docs/ru/benchmark/svelte.md +148 -0
- package/docs/ru/benchmark/tanstack.md +12 -3
- package/docs/ru/benchmark/vue.md +160 -0
- package/docs/ru/configuration.md +16 -12
- package/docs/ru/dictionary/content_file.md +52 -2
- package/docs/ru/mcp_server.md +30 -17
- package/docs/ru/plugins/sync-po.md +333 -0
- package/docs/tr/benchmark/index.md +0 -3
- package/docs/tr/benchmark/nextjs.md +15 -6
- package/docs/tr/benchmark/solid.md +155 -0
- package/docs/tr/benchmark/svelte.md +148 -0
- package/docs/tr/benchmark/tanstack.md +12 -3
- package/docs/tr/benchmark/vue.md +160 -0
- package/docs/tr/configuration.md +16 -12
- package/docs/tr/dictionary/content_file.md +51 -1
- package/docs/tr/mcp_server.md +31 -18
- package/docs/tr/plugins/sync-po.md +333 -0
- package/docs/uk/benchmark/nextjs.md +15 -6
- package/docs/uk/benchmark/solid.md +155 -0
- package/docs/uk/benchmark/svelte.md +148 -0
- package/docs/uk/benchmark/tanstack.md +12 -3
- package/docs/uk/benchmark/vue.md +160 -0
- package/docs/uk/configuration.md +16 -12
- package/docs/uk/dictionary/content_file.md +51 -1
- package/docs/uk/mcp_server.md +29 -16
- package/docs/uk/plugins/sync-po.md +333 -0
- package/docs/ur/configuration.md +16 -12
- package/docs/vi/benchmark/index.md +0 -3
- package/docs/vi/benchmark/nextjs.md +15 -6
- package/docs/vi/benchmark/solid.md +155 -0
- package/docs/vi/benchmark/svelte.md +148 -0
- package/docs/vi/benchmark/tanstack.md +12 -3
- package/docs/vi/benchmark/vue.md +160 -0
- package/docs/vi/configuration.md +16 -12
- package/docs/vi/dictionary/content_file.md +51 -1
- package/docs/vi/intlayer_with_nextjs_15.md +10 -57
- package/docs/vi/mcp_server.md +30 -17
- package/docs/vi/plugins/sync-po.md +333 -0
- package/docs/zh/benchmark/nextjs.md +15 -6
- package/docs/zh/benchmark/solid.md +155 -0
- package/docs/zh/benchmark/svelte.md +148 -0
- package/docs/zh/benchmark/tanstack.md +12 -3
- package/docs/zh/benchmark/vue.md +160 -0
- package/docs/zh/configuration.md +16 -12
- package/docs/zh/dictionary/content_file.md +51 -3
- package/docs/zh/mcp_server.md +31 -18
- package/docs/zh/plugins/sync-po.md +333 -0
- package/frequent_questions/ar/intlayerNode.md +3 -3
- package/frequent_questions/de/intlayerNode.md +3 -3
- package/frequent_questions/en/intlayerNode.md +3 -3
- package/frequent_questions/en-GB/intlayerNode.md +3 -3
- package/frequent_questions/es/intlayerNode.md +3 -3
- package/frequent_questions/fr/intlayerNode.md +3 -3
- package/frequent_questions/hi/intlayerNode.md +3 -3
- package/frequent_questions/id/intlayerNode.md +3 -3
- package/frequent_questions/it/intlayerNode.md +3 -3
- package/frequent_questions/ja/intlayerNode.md +3 -3
- package/frequent_questions/ko/intlayerNode.md +3 -3
- package/frequent_questions/pl/intlayerNode.md +3 -3
- package/frequent_questions/pt/intlayerNode.md +3 -3
- package/frequent_questions/ru/intlayerNode.md +3 -3
- package/frequent_questions/tr/intlayerNode.md +3 -3
- package/frequent_questions/uk/intlayerNode.md +3 -3
- package/frequent_questions/vi/intlayerNode.md +3 -3
- package/frequent_questions/zh/intlayerNode.md +3 -3
- package/package.json +8 -8
- package/src/generated/docs.entry.ts +20 -0
|
@@ -61,6 +61,13 @@ history:
|
|
|
61
61
|
|
|
62
62
|
Intlayerは、これらの各側面において最適化を試みています。
|
|
63
63
|
|
|
64
|
+
## TL;DR
|
|
65
|
+
|
|
66
|
+
- **Intlayer** & **next-translate**: Next.jsのパフォーマンスにおいて最適な選択肢。最小のフットプリントと最高の静的レンダリングサポートを提供。
|
|
67
|
+
- **next-intl**: 最もトレンドのオプションだが、大規模なアプリケーション向けに最適化するには重く、複雑。
|
|
68
|
+
- **next-i18next**: 人気がありプラグインも豊富だが、バンドル重量が非常に大きい(Intlayer의約3倍)。
|
|
69
|
+
- **避けるべき**: **gt-next** と **lingo.dev**。深刻なパフォーマンスの問題、ベンダーロックイン、ビルドを破壊するバグのため。
|
|
70
|
+
|
|
64
71
|
## アプリをテストする
|
|
65
72
|
|
|
66
73
|
これらの問題を顕在化させるために、無料のスキャナーを作成しました。[こちら](https://intlayer.org/i18n-seo-scanner)で試すことができます。
|
|
@@ -99,14 +106,14 @@ WebpackやTurbopackを使用し、`[locale]/page.tsx`のようなルートを宣
|
|
|
99
106
|
このベンチマークでは、以下のライブラリを比較しました。
|
|
100
107
|
|
|
101
108
|
- `Base App`(i18nライブラリなし)
|
|
102
|
-
- `next-intlayer` (v8.7.
|
|
109
|
+
- `next-intlayer` (v8.7.12)
|
|
103
110
|
- `next-i18next` (v16.0.5)
|
|
104
111
|
- `next-intl` (v4.9.1)
|
|
105
112
|
- `@lingui/core` (v5.3.0)
|
|
106
113
|
- `next-translate` (v3.1.2)
|
|
107
114
|
- `next-international` (v1.3.1)
|
|
108
115
|
- `@inlang/paraglide-js` (v2.15.1)
|
|
109
|
-
-
|
|
116
|
+
- `@tolgee/react` (v7.0.0)
|
|
110
117
|
- `@lingo.dev/compiler` (v0.4.0)
|
|
111
118
|
- `wuchale` (v0.22.11)
|
|
112
119
|
- `gt-next` (v6.16.5)
|
|
@@ -161,10 +168,10 @@ Next.jsのバージョンは`16.2.4`(App Router)を使用しました。
|
|
|
161
168
|
|
|
162
169
|
**(General Translation)** (`gt-next@6.16.5`):
|
|
163
170
|
|
|
164
|
-
- 110kbのアプリに対して、`gt-
|
|
171
|
+
- 110kbのアプリに対して、`gt-next`は440kb以上の余分なデータを追加します。
|
|
165
172
|
- General Translationを使用した最初のビルドで「Quota Exceeded, please upgrade your plan(クォータ超過、プランをアップグレードしてください)」と表示されました。
|
|
166
173
|
- 翻訳がレンダリングされません。`Error: <T> used on the client-side outside of <GTProvider>`というエラーが発生しましたが、これはライブラリのバグのようです。
|
|
167
|
-
- **gt-
|
|
174
|
+
- **gt-next**を実装中、ライブラリの[問題](https://github.com/generaltranslation/gt/issues/1210#event-24510646961)にも遭遇しました。`does not provide an export named 'printAST' - @formatjs/icu-messageformat-parser`というエラーでアプリケーションが壊れました。この問題を報告した後、メンテナは24時間以内に修正しました。
|
|
168
175
|
- このライブラリはNext.jsページの静的レンダリングをブロックします。
|
|
169
176
|
|
|
170
177
|
**(Lingo.dev)** (`@lingo.dev/compiler@0.4.0`):
|
|
@@ -186,9 +193,11 @@ Next.jsのバージョンは`16.2.4`(App Router)を使用しました。
|
|
|
186
193
|
個人的には、プッシュのたびにJSファイルを再生成しなければならないのが嫌いです。これはPRを通じて常にマージ競合のリスクを生み出します。また、このツールはNext.jsよりもViteにフォーカスしているように見えます。
|
|
187
194
|
最後に、他のソリューションと比較して、Paraglideはコンテンツをレンダリングするために現在のロケールを取得するためのストア(例:Reactコンテキスト)を使用しません。パースされる各ノードについて、localStorageやクッキーなどからロケールをリクエストします。これにより、コンポーネントの反応性に影響を与える不要なロジックが実行されます。
|
|
188
195
|
|
|
196
|
+
> paraglideについての注意:このソリューションは、インポートのためにコードベースにコードを注入します。その結果、ベンチマークレポートの「ライブラリサイズ」指標はほぼ0になります。コード生成は良いことです。なぜなら、使用される関数には必要なロジック(すべてのプレフィックス対プレフィックスなし、クッキー対ストレージなど)のみが含まれるからです。対照的に、Intlayerはビルド時に環境変数を注入して、ロジックに応じてコンテンツをツリーシェイキングするようバンドラーに強制します。このおかげで、paraglideとintlayerは、i18nextやnext-intlよりも6〜10倍軽量なソリューションとなっています。
|
|
197
|
+
|
|
189
198
|
### 3 — 許容できるソリューション
|
|
190
199
|
|
|
191
|
-
**(Tolgee)** (
|
|
200
|
+
**(Tolgee)** (`@tolgee/react@7.0.0`):
|
|
192
201
|
|
|
193
202
|
`Tolgee`は前述の問題の多くに対処しています。しかし、同様のツールよりも導入が難しいと感じました。型安全性が提供されていないため、コンパイル時に紛失したキーを見つけることも困難です。キーの不備を検出するために、Tolgeeの関数を自前の関数でラップする必要がありました。
|
|
194
203
|
|
|
@@ -216,7 +225,7 @@ Next.jsのバージョンは`16.2.4`(App Router)を使用しました。
|
|
|
216
225
|
|
|
217
226
|
`t()`スタイルのAPIがお好みなら、`next-translate`が私の主な推奨事項です。`next-translate-plugin`を介して優雅に動作し、Webpack / Turbopackローダーを使用して`getStaticProps`経由でネームスペースをロードします。また、今回の中で最も軽量な選択肢です(約2.5kb)。ネームスぺーシングについては、設定ファイルでページやルートごとにネームスペースを定義する方法がよく考えられており、**next-intl**や**next-i18next**のような主要な選択肢よりもメンテナンスが容易です。バージョン`3.1.2`では、静的レンダリングが機能せず、Next.jsが動的レンダリングにフォールバックすることに気づきました。
|
|
218
227
|
|
|
219
|
-
**(Intlayer)** (`next-intlayer@8.7.
|
|
228
|
+
**(Intlayer)** (`next-intlayer@8.7.12`):
|
|
220
229
|
|
|
221
230
|
客観性を保つため、自分自身のソリューションである`next-intlayer`については個人的な判断を控えさせていただきます。
|
|
222
231
|
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2026-04-20
|
|
3
|
+
updatedAt: 2026-04-21
|
|
4
|
+
title: 2026年 Solid向けの最高のi18nソリューション - ベンチマークレポート
|
|
5
|
+
description: solid-primitives、solid-i18next、IntlayerなどのSolid国際化(i18n)ライブラリを比較します。バンドルサイズ、リーク、反応性に関する詳細なパフォーマンスレポート。
|
|
6
|
+
keywords:
|
|
7
|
+
- benchmark
|
|
8
|
+
- i18n
|
|
9
|
+
- intl
|
|
10
|
+
- solid
|
|
11
|
+
- パフォーマンス
|
|
12
|
+
- intlayer
|
|
13
|
+
slugs:
|
|
14
|
+
- doc
|
|
15
|
+
- benchmark
|
|
16
|
+
- solid
|
|
17
|
+
author: Aymeric PINEAU
|
|
18
|
+
applicationTemplate: https://github.com/intlayer-org/benchmark-i18n-solid-template
|
|
19
|
+
history:
|
|
20
|
+
- version: 8.7.12
|
|
21
|
+
date: 2026-01-06
|
|
22
|
+
changes: "ベンチマークの初期化"
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
# Solid i18nライブラリ - 2026年ベンチマークレポート
|
|
26
|
+
|
|
27
|
+
このページは、Solidにおけるi18nソリューションのベンチマークレポートです。
|
|
28
|
+
|
|
29
|
+
## 目次
|
|
30
|
+
|
|
31
|
+
<Toc/>
|
|
32
|
+
|
|
33
|
+
## インタラクティブベンチマーク
|
|
34
|
+
|
|
35
|
+
<I18nBenchmark framework="vite-solid" vertical/>
|
|
36
|
+
|
|
37
|
+
## 結果のリファレンス:
|
|
38
|
+
|
|
39
|
+
<iframe
|
|
40
|
+
src="https://intlayer.org/markdown?url=https%3A%2F%2Fraw.githubusercontent.com%2Fintlayer-org%2Fbenchmark-i18n%2Fmain%2Freport%2Fscripts%2Fsummarize-vite_solid.md"
|
|
41
|
+
width="100%"
|
|
42
|
+
height="600px"
|
|
43
|
+
style="border:none;">
|
|
44
|
+
</iframe>
|
|
45
|
+
|
|
46
|
+
> https://intlayer.org/markdown?url=https%3A%2F%2Fraw.githubusercontent.com%2Fintlayer-org%2Fbenchmark-i18n%2Fmain%2Freport%2Fscripts%2Fsummarize-vite_solid.md
|
|
47
|
+
|
|
48
|
+
完全なベンチマークリポジトリは[こちら](https://github.com/intlayer-org/benchmark-i18n/tree/main)でご覧いただけます。
|
|
49
|
+
|
|
50
|
+
## はじめに
|
|
51
|
+
|
|
52
|
+
国際化ソリューションは、Solidアプリにおいて最も重い依存関係の一つです。主なリスクは、不必要なコンテンツ(単一のルートのバンドルに含まれる他のページや他のロケールの翻訳)を送信してしまうことです。
|
|
53
|
+
|
|
54
|
+
アプリが成長するにつれて、この問題はクライアントに送信されるJavaScriptを急速に増大させ、ナビゲーションを遅くする可能性があります。
|
|
55
|
+
|
|
56
|
+
実際、最適化が不十分な実装では、国際化されたページがi18nなしのバージョンよりも数倍重くなることがあります。
|
|
57
|
+
|
|
58
|
+
もう一つの影響は、開発者エクスペリエンス(DX)です。コンテンツの宣言方法、型、名前空間の構成、動的ロード、ロケール変更時の反応性などが含まれます。
|
|
59
|
+
|
|
60
|
+
## TL;DR
|
|
61
|
+
|
|
62
|
+
- **Intlayer**: 高度な機能と最適化を必要とするプロフェッショナルなSolidアプリケーションに推奨される選択肢(v8.7.12)。
|
|
63
|
+
- **@solid-primitives/i18n**: シンプルなプロジェクトには優れた軽量な代替案ですが、遅延ロードなどの高度な機能に欠けます。
|
|
64
|
+
- **solid-i18next**: 標準的ですが重い選択肢(Intlayerの約4.7倍)で、React i18nextと同じ欠点があります。
|
|
65
|
+
- **Paraglide**: 革新的なアプローチですが、一部のセットアップではDXが複雑で、ツリーシェイキングの問題があります。
|
|
66
|
+
|
|
67
|
+
## アプリをテストする
|
|
68
|
+
|
|
69
|
+
i18nリークの問題を素早く特定するために、無料のスキャナーを用意しました。[こちら](https://intlayer.org/i18n-seo-scanner)でお試しいただけます。
|
|
70
|
+
|
|
71
|
+
<iframe src="https://intlayer.org/i18n-seo-scanner" width="100%" height="600px" style="border:none;"/>
|
|
72
|
+
|
|
73
|
+
## 問題点
|
|
74
|
+
|
|
75
|
+
多言語アプリのコストを抑えるためには、2つのレバーが不可欠です。
|
|
76
|
+
|
|
77
|
+
- ページ/名前空間ごとにコンテンツを分割し、不要な時に辞書全体をロードしないようにする。
|
|
78
|
+
- 必要な時にだけ、適切なロケールを動的にロードする。
|
|
79
|
+
|
|
80
|
+
これらのアプローチの技術的限界を理解する:
|
|
81
|
+
|
|
82
|
+
**動的ロード**
|
|
83
|
+
|
|
84
|
+
動的ロードがない場合、ほとんどのソリューションは最初のレンダリングからメッセージをメモリに保持するため、ルートやロケールが多いアプリでは大きなオーバーヘッドとなります。
|
|
85
|
+
|
|
86
|
+
動的ロードを使用する場合、トレードオフを受け入れることになります。初期JSは減りますが、言語切り替え時などに追加のリクエストが発生することがあります。
|
|
87
|
+
|
|
88
|
+
**コンテンツの分割**
|
|
89
|
+
|
|
90
|
+
`t('a.b.c')` を中心に構築された構文は非常に便利ですが、実行時に大きなJSONオブジェクトを保持することを助長しがちです。このモデルでは、ライブラリがページごとの分割戦略を提供していない限り、ツリーシェイキングが難しくなります。
|
|
91
|
+
|
|
92
|
+
## 研究方法
|
|
93
|
+
|
|
94
|
+
このベンチマークでは、以下のライブラリを比較しました。
|
|
95
|
+
|
|
96
|
+
- `Base App` (i18nライブラリなし)
|
|
97
|
+
- `solid-intlayer` (v8.7.12)
|
|
98
|
+
- `@solid-primitives/i18n` (v2.2.1)
|
|
99
|
+
- `solid-i18next` (v17.0.2)
|
|
100
|
+
- `@inlang/paraglide-js` (v2.17.0)
|
|
101
|
+
|
|
102
|
+
フレームワークは `Solid` で、**10ページ**と**10言語**を持つ多言語アプリを使用しました。
|
|
103
|
+
|
|
104
|
+
**4つのロード戦略**を比較しました。
|
|
105
|
+
|
|
106
|
+
| 戦略 | 名前空間なし(グローバル) | 名前空間あり(スコープ) |
|
|
107
|
+
| :------------- | :---------------------------------------------- | :--------------------------------------------------------- |
|
|
108
|
+
| **静的ロード** | **Static**: 起動時にすべてをメモリに保持。 | **Scoped static**: 名前空間で分割。起動時にすべてロード。 |
|
|
109
|
+
| **動的ロード** | **Dynamic**: ロケールごとのオンデマンドロード。 | **Scoped dynamic**: 名前空間とロケールごとの詳細なロード。 |
|
|
110
|
+
|
|
111
|
+
## 戦略のまとめ
|
|
112
|
+
|
|
113
|
+
- **静的(Static)**: シンプル。初期ロード後のネットワーク遅延なし。欠点:バンドルサイズが大きい。
|
|
114
|
+
- **動的(Dynamic)**: 初期重量を削減(遅延ロード)。ロケールが多い場合に理想的。
|
|
115
|
+
- **名前空間付き静的(Scoped static)**: 複雑な追加リクエストなしで、コードを整理(論理的分離)した状態に保つ。
|
|
116
|
+
- **名前空間付き動的(Scoped dynamic)**: コード分割とパフォーマンスのための最善のアプローチ。現在のビューとアクティブなロケールに必要なものだけをロードし、メモリ使用量を最小限に抑える。
|
|
117
|
+
|
|
118
|
+
## 結果の詳細
|
|
119
|
+
|
|
120
|
+
### 1 - 避けるべきソリューション
|
|
121
|
+
|
|
122
|
+
> Solidエコシステムにおいて、明確に避けるべきソリューションはありません。
|
|
123
|
+
|
|
124
|
+
### 2 - 許容できるソリューション
|
|
125
|
+
|
|
126
|
+
**(solid-i18next)** (`solid-i18next@17.0.2`):
|
|
127
|
+
|
|
128
|
+
`solid-i18next` は、JavaScriptアプリのi18nニーズに応えた最初のソリューションの一つであったため、おそらく最も人気のあるオプションです。また、特定の問題を解決するためのコミュニティプラグインも幅広く揃っています。
|
|
129
|
+
|
|
130
|
+
パッケージは重いです(~14.6kb。これは `solid-intlayer` の約4.7倍です)。
|
|
131
|
+
|
|
132
|
+
それでも、`t('a.b.c')` 上に構築されたスタックと同じ主要な欠点を共有しています。最適化は可能ですが非常に時間がかかり、大規模なプロジェクトでは悪い習慣(名前空間 + 動的ロード + 型)に陥るリスクがあります。
|
|
133
|
+
|
|
134
|
+
**(@solid-primitives/i18n)** (`@solid-primitives/i18n@2.2.1`):
|
|
135
|
+
|
|
136
|
+
Solid primitive は非常に軽量で効率的です。小規模なプロジェクトにはこのソリューションを推奨しますが、クッキー管理、プロキシリダイレクト、フォーマッタなどを含むプロフェッショナルなソリューションには機能が不足しがちです。
|
|
137
|
+
また、ページサイズの最適化のための遅延ロードや名前空間のスコーピングも欠けています。
|
|
138
|
+
|
|
139
|
+
**(Paraglide)** (`@inlang/paraglide-js@2.17.0`):
|
|
140
|
+
|
|
141
|
+
`Paraglide` は革新的でよく考えられたアプローチを提供しています。それでも、このベンチマークでは、彼らが宣伝しているツリーシェイキングは私の実装では機能しませんでした。ワークフローとDXも他のオプションより複雑です。
|
|
142
|
+
個人的には、プッシュする前に毎回JSファイルを再生成しなければならないのが好きではありません。
|
|
143
|
+
最後に、他のソリューションと比較して、Paraglide はコンテンツをレンダリングするための現在のロケールを取得するためにストア(例:Solid signal)を使用しません。パースされる各ノードに対して、localStorage / cookie などからロケールを要求します。これにより、コンポーネントの反応性に影響を与える不要なロジックの実行が発生します。
|
|
144
|
+
|
|
145
|
+
### 3 - 推奨事項
|
|
146
|
+
|
|
147
|
+
**(Intlayer)** (`solid-intlayer@8.7.12`):
|
|
148
|
+
|
|
149
|
+
客観性を保つため、`solid-intlayer` については私自身のソリューションであるため、個人的な評価は控えます。
|
|
150
|
+
|
|
151
|
+
### 個人メモ
|
|
152
|
+
|
|
153
|
+
このメモは個人的なものであり、ベンチマーク結果には影響しません。それでも、i18nの世界では翻訳されたコンテンツに対して `const t = useTranslation('xx')` + `<>{t('xx.xx')}</>` のようなパターンが一般的です。
|
|
154
|
+
|
|
155
|
+
Solidアプリにおいて、関数を `JSX.Element` として注入することは、私の考えではアンチパターンです。また、回避可能な複雑さとJavaScriptの実行オーバーヘッド(たとえほとんど目立たなくても)を追加することになります。
|
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2026-04-20
|
|
3
|
+
updatedAt: 2026-04-21
|
|
4
|
+
title: 2026年 Svelte向けの最高のi18nソリューション - ベンチマークレポート
|
|
5
|
+
description: svelte-i18n、Paraglide、IntlayerなどのSvelte国際化(i18n)ライブラリを比較します。バンドルサイズ、リーク、反応性に関する詳細なパフォーマンスレポート。
|
|
6
|
+
keywords:
|
|
7
|
+
- benchmark
|
|
8
|
+
- i18n
|
|
9
|
+
- intl
|
|
10
|
+
- svelte
|
|
11
|
+
- パフォーマンス
|
|
12
|
+
- intlayer
|
|
13
|
+
slugs:
|
|
14
|
+
- doc
|
|
15
|
+
- benchmark
|
|
16
|
+
- svelte
|
|
17
|
+
author: Aymeric PINEAU
|
|
18
|
+
applicationTemplate: https://github.com/intlayer-org/benchmark-i18n-svelte-template
|
|
19
|
+
history:
|
|
20
|
+
- version: 8.7.12
|
|
21
|
+
date: 2026-01-06
|
|
22
|
+
changes: "ベンチマークの初期化"
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
# Svelte i18nライブラリ - 2026年ベンチマークレポート
|
|
26
|
+
|
|
27
|
+
このページは、Svelteにおけるi18nソリューションのベンチマークレポートです。
|
|
28
|
+
|
|
29
|
+
## 目次
|
|
30
|
+
|
|
31
|
+
<Toc/>
|
|
32
|
+
|
|
33
|
+
## インタラクティブベンチマーク
|
|
34
|
+
|
|
35
|
+
<I18nBenchmark framework="vite-svelte" vertical/>
|
|
36
|
+
|
|
37
|
+
## 結果のリファレンス:
|
|
38
|
+
|
|
39
|
+
<iframe
|
|
40
|
+
src="https://intlayer.org/markdown?url=https%3A%2F%2Fraw.githubusercontent.com%2Fintlayer-org%2Fbenchmark-i18n%2Fmain%2Freport%2Fscripts%2Fsummarize-vite_svelte.md"
|
|
41
|
+
width="100%"
|
|
42
|
+
height="600px"
|
|
43
|
+
style="border:none;">
|
|
44
|
+
</iframe>
|
|
45
|
+
|
|
46
|
+
> https://intlayer.org/markdown?url=https%3A%2F%2Fraw.githubusercontent.com%2Fintlayer-org%2Fbenchmark-i18n%2Fmain%2Freport%2Fscripts%2Fsummarize-vite_svelte.md
|
|
47
|
+
|
|
48
|
+
完全なベンチマークリポジトリは[こちら](https://github.com/intlayer-org/benchmark-i18n/tree/main)でご覧いただけます。
|
|
49
|
+
|
|
50
|
+
## はじめに
|
|
51
|
+
|
|
52
|
+
国際化ソリューションは、Svelteアプリにおいて最も重い依存関係の一つです。主なリスクは、不必要なコンテンツ(単一のルートのバンドルに含まれる他のページや他のロケールの翻訳)を送信してしまうことです。
|
|
53
|
+
|
|
54
|
+
アプリが成長するにつれて、この問題はクライアントに送信されるJavaScriptを急速に増大させ、ナビゲーションを遅くする可能性があります。
|
|
55
|
+
|
|
56
|
+
実際、最適化が不十分な実装では、国際化されたページがi18nなしのバージョンよりも数倍重くなることがあります。
|
|
57
|
+
|
|
58
|
+
もう一つの影響は、開発者エクスペリエンス(DX)です。コンテンツの宣言方法、型、名前空間の構成、動的ロード、ロケール変更時の反応性などが含まれます。
|
|
59
|
+
|
|
60
|
+
## TL;DR
|
|
61
|
+
|
|
62
|
+
- **Intlayer**: 最もパフォーマンス効率が高く、フットプリントが最も小さい選択肢(v8.7.12)。
|
|
63
|
+
- **Paraglide**: ツリーシェイキング(tree-shaking)の強力な候補ですが、開発者エクスペリエンスがより複雑で、反応性のオーバーヘッドがあります。
|
|
64
|
+
- **svelte-i18n**: Svelte向けの標準的で機能が充実したソリューションですが、バンドル重量が非常に大きくなります(Intlayerの約7倍)。
|
|
65
|
+
|
|
66
|
+
## アプリをテストする
|
|
67
|
+
|
|
68
|
+
i18nリークの問題を素早く特定するために、無料のスキャナーを用意しました。[こちら](https://intlayer.org/i18n-seo-scanner)でお試しいただけます。
|
|
69
|
+
|
|
70
|
+
<iframe src="https://intlayer.org/i18n-seo-scanner" width="100%" height="600px" style="border:none;"/>
|
|
71
|
+
|
|
72
|
+
## 問題点
|
|
73
|
+
|
|
74
|
+
多言語アプリのコストを抑えるためには、2つのレバーが不可欠です。
|
|
75
|
+
|
|
76
|
+
- ページ/名前空間ごとにコンテンツを分割し、不要な時に辞書全体をロードしないようにする。
|
|
77
|
+
- 必要な時にだけ、適切なロケールを動的にロードする。
|
|
78
|
+
|
|
79
|
+
これらのアプローチの技術的限界を理解する:
|
|
80
|
+
|
|
81
|
+
**動的ロード**
|
|
82
|
+
|
|
83
|
+
動的ロードがない場合、ほとんどのソリューションは最初のレンダリングからメッセージをメモリに保持するため、ルートやロケールが多いアプリでは大きなオーバーヘッドとなります。
|
|
84
|
+
|
|
85
|
+
動的ロードを使用する場合、トレードオフを受け入れることになります。初期JSは減りますが、言語切り替え時などに追加のリクエストが発生することがあります。
|
|
86
|
+
|
|
87
|
+
**コンテンツの分割**
|
|
88
|
+
|
|
89
|
+
`t('a.b.c')` を中心に構築された構文は非常に便利ですが、実行時に大きなJSONオブジェクトを保持することを助長しがちです。このモデルでは、ライブラリがページごとの分割戦略を提供していない限り、ツリーシェイキングが難しくなります。
|
|
90
|
+
|
|
91
|
+
## 研究方法
|
|
92
|
+
|
|
93
|
+
このベンチマークでは、以下のライブラリを比較しました。
|
|
94
|
+
|
|
95
|
+
- `Base App` (i18nライブラリなし)
|
|
96
|
+
- `svelte-intlayer` (v8.7.12)
|
|
97
|
+
- `svelte-i18n` (v4.0.1)
|
|
98
|
+
- `@inlang/paraglide-js` (v2.17.0)
|
|
99
|
+
|
|
100
|
+
フレームワークは `Svelte` で、**10ページ**と**10言語**を持つ多言語アプリを使用しました。
|
|
101
|
+
|
|
102
|
+
**4つのロード戦略**を比較しました。
|
|
103
|
+
|
|
104
|
+
| 戦略 | 名前空間なし(グローバル) | 名前空間あり(スコープ) |
|
|
105
|
+
| :------------- | :---------------------------------------------- | :--------------------------------------------------------- |
|
|
106
|
+
| **静的ロード** | **Static**: 起動時にすべてをメモリに保持。 | **Scoped static**: 名前空間で分割。起動時にすべてロード。 |
|
|
107
|
+
| **動的ロード** | **Dynamic**: ロケールごとのオンデマンドロード。 | **Scoped dynamic**: 名前空間とロケールごとの詳細なロード。 |
|
|
108
|
+
|
|
109
|
+
## 戦略のまとめ
|
|
110
|
+
|
|
111
|
+
- **静的(Static)**: シンプル。初期ロード後のネットワーク遅延なし。欠点:バンドルサイズが大きい。
|
|
112
|
+
- **動的(Dynamic)**: 初期重量を削減(遅延ロード)。ロケールが多い場合に理想的。
|
|
113
|
+
- **名前空間付き静的(Scoped static)**: 複雑な追加リクエストなしで、コードを整理(論理的分離)した状態に保つ。
|
|
114
|
+
- **名前空間付き動的(Scoped dynamic)**: コード分割とパフォーマンスのための最善のアプローチ。現在のビューとアクティブなロケールに必要なものだけをロードし、メモリ使用量を最小限に抑える。
|
|
115
|
+
|
|
116
|
+
## 結果の詳細
|
|
117
|
+
|
|
118
|
+
### 1 - 避けるべきソリューション
|
|
119
|
+
|
|
120
|
+
> Svelteエコシステムにおいて、明確に避けるべきソリューションはありません。
|
|
121
|
+
|
|
122
|
+
### 2 - 許容できるソリューション
|
|
123
|
+
|
|
124
|
+
**(Paraglide)** (`@inlang/paraglide-js@2.17.0`):
|
|
125
|
+
|
|
126
|
+
`Paraglide` は革新的でよく考えられたアプローチを提供しています。Vite + Svelte アプリの文脈では、彼らが宣伝しているツリーシェイキングは期待通りに機能しており、素晴らしいことです。
|
|
127
|
+
しかし、React + TanStack Start の場合、ツリーシェイキングは期待通りに機能せず、Next.jsでも同様でした。とはいえ、Svelte および TanStack Start プロジェクトにおける Paraglide の使用は再確認する価値があるでしょう。
|
|
128
|
+
ワークフローとDXも他のオプションより複雑です。
|
|
129
|
+
個人的には、プッシュする前に毎回JSファイルを再生成しなければならないのが好きではありません。これはPRを通じた開発者間の絶え間ないマージコンフリクトのリスクを生みます。また、このツールはNext.jsよりもViteに重点を置いているようです。
|
|
130
|
+
最後に、他のソリューションと比較して、Paraglide はコンテンツをレンダリングするための現在のロケールを取得するためにストア(例:Svelte store)を使用しません。パースされる各ノードに対して、localStorage / cookie などからロケールを要求します。これにより、コンポーネントの反応性に影響を与える不要なロジックの実行が発生します。
|
|
131
|
+
|
|
132
|
+
> paraglideに関する注意:このソリューションはインポートのためにコードベースにコードを注入するため、ベンチマークレポートの「ライブラリサイズ(lib size)」メトリックはほぼ0になります。コード生成は、使用される関数に必要なロジック(接頭辞あり vs 接頭辞なし、クッキー vs ストレージなど)のみが含まれるため、良いことです。比較すると、Intlayer はビルド時に環境変数を注入することでこのフィルタリングを行い、ロジックに応じてコンテンツをツリーシェイクするようにバンドラーに強制します。このおかげで、paraglide と intlayer は i18next や next-intl よりも 6〜10倍軽量なソリューションとなります。
|
|
133
|
+
|
|
134
|
+
**(svelte-i18n)** (`svelte-i18n@3.4.0`):
|
|
135
|
+
|
|
136
|
+
このソリューションは、Svelteプロジェクトにおけるi18nのすべてのニーズに応えます。しかし、i18nextや他の主要なi18nソリューションと同様に、少し重いです(~15.9kb。これは `svelte-intlayer` の約7倍です)。
|
|
137
|
+
|
|
138
|
+
### 3 - 推奨事項
|
|
139
|
+
|
|
140
|
+
**(Intlayer)** (`svelte-intlayer@8.7.12`):
|
|
141
|
+
|
|
142
|
+
客観性を保つため、`svelte-intlayer` については私自身のソリューションであるため、個人的な評価は控えます。
|
|
143
|
+
|
|
144
|
+
### 個人メモ
|
|
145
|
+
|
|
146
|
+
このメモは個人的なものであり、ベンチマーク結果には影響しません。それでも、i18nの世界では翻訳されたコンテンツに対して `const t = useTranslation('xx')` + `<>{t('xx.xx')}</>` のようなパターンが一般的です。
|
|
147
|
+
|
|
148
|
+
Svelteアプリにおいて、関数を `Slot` として注入することは、私の考えではアンチパターンです。また、回避可能な複雑さとJavaScriptの実行オーバーヘッド(たとえほとんど目立たなくても)を追加することになります。
|
|
@@ -57,6 +57,13 @@ history:
|
|
|
57
57
|
|
|
58
58
|
もう一つの影響は開発体験(DX)への影響です。コンテンツの宣言方法、型、ネームスペースの構成、動的ロード、およびロケール変更時の反応性などが挙げられます。
|
|
59
59
|
|
|
60
|
+
## TL;DR
|
|
61
|
+
|
|
62
|
+
- **Intlayer**: TanStack Startにおいて最高のパフォーマンスと最小のバンドルサイズ(v8.7.12)を提供します。
|
|
63
|
+
- **react-i18next** & **use-intl**: 大規模なエコシステムを持つ成熟した代替案ですが、大幅に重く、最適化がより複雑です。
|
|
64
|
+
- **Paraglide**: 革新的なツリーシェイキングのアイデアですが、実際には機能しません。TanStack StartにおいてはDXが複雑で、反応性のオーバーヘッドがあります。
|
|
65
|
+
- **避けるべき**: **General Translation (GT)** と **Lingo.dev**。深刻なパフォーマンスの問題、AIクォータの制限、およびベンダーロックインのためです。
|
|
66
|
+
|
|
60
67
|
## アプリをテストする
|
|
61
68
|
|
|
62
69
|
i18nのリーク問題を素早く特定するために、無料のスキャナーを用意しました。[こちら](https://intlayer.org/i18n-seo-scanner)で利用可能です。
|
|
@@ -87,12 +94,12 @@ i18nのリーク問題を素早く特定するために、無料のスキャナ
|
|
|
87
94
|
このベンチマークでは、以下のライブラリを比較しました。
|
|
88
95
|
|
|
89
96
|
- `Base App`(i18nライブラリなし)
|
|
90
|
-
- `react-intlayer` (v8.7.
|
|
97
|
+
- `react-intlayer` (v8.7.12)
|
|
91
98
|
- `react-i18next` (v17.0.2)
|
|
92
99
|
- `use-intl` (v4.9.1)
|
|
93
100
|
- `@lingui/core` (v5.3.0)
|
|
94
101
|
- `@inlang/paraglide-js` (v2.15.1)
|
|
95
|
-
-
|
|
102
|
+
- `@tolgee/react` (v7.0.0)
|
|
96
103
|
- `react-intl` (v10.1.1)
|
|
97
104
|
- `wuchale` (v0.22.11)
|
|
98
105
|
- `gt-react` (vlatest)
|
|
@@ -150,7 +157,9 @@ i18nのリーク問題を素早く特定するために、無料のスキャナ
|
|
|
150
157
|
|
|
151
158
|
`Paraglide`は革新的でよく考えられたアプローチを提供しています。それにもかかわらず、このベンチマークでは、Next.jsの実装やTanStack Startにおいて、彼らが宣伝していたツリーシェイキングは機能しませんでした。ワークフローとDXも他の選択肢より複雑です。個人的には、プッシュのたびにJSファイルを再生成しなければならないのが好きではありません。これはPRを通じて常にマージ競合のリスクを生み出します。
|
|
152
159
|
|
|
153
|
-
|
|
160
|
+
> paraglideに関する注意:このソリューションはインポートのためにコードベースにコードを注入するため、ベンチマークレポートの「lib size」メトリクスはほぼ0になります。コード生成は、使用される関数に必要なロジック(すべてのプレフィックス対プレフィックスなし、クッキー対ストレージなど)のみが含まれるため、良いことです。対照的に、Intlayerはビルド時に環境変数を注入してこのフィルタリングを行い、ロケールに応じたコンテンツをバンドラーにツリーシェイクさせます。このおかげで、paraglideとintlayerは、i18nextやnext-intlよりも6〜10倍軽量なソリューションとなります。
|
|
161
|
+
|
|
162
|
+
**(Tolgee)** (`@tolgee/react@7.0.0`):
|
|
154
163
|
|
|
155
164
|
`Tolgee`は前述の問題の多くに対処しています。しかし、同様のアプローチを持つ他のツールよりも導入が難しいと感じました。型安全性が提供されていないため、コンパイル時に紛失したキーを見つけることが非常に困難です。キーの不備を検出するために、TolgeeのAPIを自前のAPIでラップする必要がありました。
|
|
156
165
|
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2026-04-20
|
|
3
|
+
updatedAt: 2026-04-21
|
|
4
|
+
title: 2026年 Vue向けの最高のi18nソリューション - ベンチマークレポート
|
|
5
|
+
description: vue-i18n、fluent-vue、IntlayerなどのVue国際化(i18n)ライブラリを比較します。バンドルサイズ、リーク、反応性に関する詳細なパフォーマンスレポート。
|
|
6
|
+
keywords:
|
|
7
|
+
- benchmark
|
|
8
|
+
- i18n
|
|
9
|
+
- intl
|
|
10
|
+
- vue
|
|
11
|
+
- パフォーマンス
|
|
12
|
+
- intlayer
|
|
13
|
+
slugs:
|
|
14
|
+
- doc
|
|
15
|
+
- benchmark
|
|
16
|
+
- vue
|
|
17
|
+
author: Aymeric PINEAU
|
|
18
|
+
applicationTemplate: https://github.com/intlayer-org/benchmark-i18n-vue-template
|
|
19
|
+
history:
|
|
20
|
+
- version: 8.7.12
|
|
21
|
+
date: 2026-01-06
|
|
22
|
+
changes: "ベンチマークの初期化"
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
# Vue i18nライブラリ - 2026年ベンチマークレポート
|
|
26
|
+
|
|
27
|
+
このページは、Vueにおけるi18nソリューションのベンチマークレポートです。
|
|
28
|
+
|
|
29
|
+
## 目次
|
|
30
|
+
|
|
31
|
+
<Toc/>
|
|
32
|
+
|
|
33
|
+
## インタラクティブベンチマーク
|
|
34
|
+
|
|
35
|
+
<I18nBenchmark framework="vite-vue" vertical/>
|
|
36
|
+
|
|
37
|
+
## 結果のリファレンス:
|
|
38
|
+
|
|
39
|
+
<iframe
|
|
40
|
+
src="https://intlayer.org/markdown?url=https%3A%2F%2Fraw.githubusercontent.com%2Fintlayer-org%2Fbenchmark-i18n%2Fmain%2Freport%2Fscripts%2Fsummarize-vite_vue.md"
|
|
41
|
+
width="100%"
|
|
42
|
+
height="600px"
|
|
43
|
+
style="border:none;">
|
|
44
|
+
</iframe>
|
|
45
|
+
|
|
46
|
+
> https://intlayer.org/markdown?url=https%3A%2F%2Fraw.githubusercontent.com%2Fintlayer-org%2Fbenchmark-i18n%2Fmain%2Freport%2Fscripts%2Fsummarize-vite_vue.md
|
|
47
|
+
|
|
48
|
+
完全なベンチマークリポジトリは[こちら](https://github.com/intlayer-org/benchmark-i18n/tree/main)でご覧いただけます。
|
|
49
|
+
|
|
50
|
+
## はじめに
|
|
51
|
+
|
|
52
|
+
国際化ソリューションは、Vueアプリにおいて最も重い依存関係の一つです。主なリスクは、不必要なコンテンツ(単一のルートのバンドルに含まれる他のページや他のロケールの翻訳)を送信してしまうことです。
|
|
53
|
+
|
|
54
|
+
アプリが成長するにつれて、この問題はクライアントに送信されるJavaScriptを急速に増大させ、ナビゲーションを遅くする可能性があります。
|
|
55
|
+
|
|
56
|
+
実際、最適化が不十分な実装では、国際化されたページがi18nなしのバージョンよりも数倍重くなることがあります。
|
|
57
|
+
|
|
58
|
+
もう一つの影響は、開発者エクスペリエンス(DX)です。コンテンツの宣言方法、型、名前空間の構成、動的ロード、ロケール変更時の反応性などが含まれます。
|
|
59
|
+
|
|
60
|
+
## TL;DR
|
|
61
|
+
|
|
62
|
+
- **Intlayer**: スコーピング(scoping)と動的ロードを内蔵した、最も軽量なソリューション(v8.7.12)。
|
|
63
|
+
- **vue-i18n**: 豊かなエコシステムを持つ業界標準ですが、非常に重くなる可能性があり、大規模アプリケーションでのコード分割の最適化が難しい場合があります。
|
|
64
|
+
- **fluent-vue**: 革新的なメッセージ構成ですが、型安全性が欠けており、非常に重いソリューションです。
|
|
65
|
+
|
|
66
|
+
## アプリをテストする
|
|
67
|
+
|
|
68
|
+
i18nリークの問題を素早く特定するために、無料のスキャナーを用意しました。[こちら](https://intlayer.org/i18n-seo-scanner)でお試しいただけます。
|
|
69
|
+
|
|
70
|
+
<iframe src="https://intlayer.org/i18n-seo-scanner" width="100%" height="600px" style="border:none;"/>
|
|
71
|
+
|
|
72
|
+
## 問題点
|
|
73
|
+
|
|
74
|
+
多言語アプリのコストを抑えるためには、2つのレバーが不可欠です。
|
|
75
|
+
|
|
76
|
+
- ページ/名前空間ごとにコンテンツを分割し、不要な時に辞書全体をロードしないようにする。
|
|
77
|
+
- 必要な時にだけ、適切なロケールを動的にロードする。
|
|
78
|
+
|
|
79
|
+
これらのアプローチの技術的限界を理解する:
|
|
80
|
+
|
|
81
|
+
**動的ロード**
|
|
82
|
+
|
|
83
|
+
動的ロードがない場合、ほとんどのソリューションは最初のレンダリングからメッセージをメモリに保持するため、ルートやロケールが多いアプリでは大きなオーバーヘッドとなります。
|
|
84
|
+
|
|
85
|
+
動的ロードを使用する場合、トレードオフを受け入れることになります。初期JSは減りますが、言語切り替え時などに追加のリクエストが発生することがあります。
|
|
86
|
+
|
|
87
|
+
**コンテンツの分割**
|
|
88
|
+
|
|
89
|
+
`const { t } = useI18n()` + `t('a.b.c')` を中心に構築された構文は非常に便利ですが、実行時に大きなJSONオブジェクトを保持することを助長しがちです。このモデルでは、ライブラリがページごとの分割戦略を提供していない限り、ツリーシェイキング(tree-shaking)が難しくなります。
|
|
90
|
+
|
|
91
|
+
## 研究方法
|
|
92
|
+
|
|
93
|
+
このベンチマークでは、以下のライブラリを比較しました。
|
|
94
|
+
|
|
95
|
+
- `Base App` (i18nライブラリなし)
|
|
96
|
+
- `vue-intlayer` (v8.7.12)
|
|
97
|
+
- `vue-i18n` (v11.4.0)
|
|
98
|
+
- `fluent-vue` (v3.8.2)
|
|
99
|
+
|
|
100
|
+
フレームワークは `Vue` で、**10ページ**と**10言語**を持つ多言語アプリを使用しました。
|
|
101
|
+
|
|
102
|
+
**4つのロード戦略**を比較しました。
|
|
103
|
+
|
|
104
|
+
| 戦略 | 名前空間なし(グローバル) | 名前空間あり(スコープ) |
|
|
105
|
+
| :------------- | :---------------------------------------------- | :--------------------------------------------------------- |
|
|
106
|
+
| **静的ロード** | **Static**: 起動時にすべてをメモリに保持。 | **Scoped static**: 名前空間で分割。起動時にすべてロード。 |
|
|
107
|
+
| **動的ロード** | **Dynamic**: ロケールごとのオンデマンドロード。 | **Scoped dynamic**: 名前空間とロケールごとの詳細なロード。 |
|
|
108
|
+
|
|
109
|
+
## 戦略のまとめ
|
|
110
|
+
|
|
111
|
+
- **静的(Static)**: シンプル。初期ロード後のネットワーク遅延なし。欠点:バンドルサイズが大きい。
|
|
112
|
+
- **動的(Dynamic)**: 初期重量を削減(遅延ロード)。ロケールが多い場合に理想的。
|
|
113
|
+
- **名前空間付き静的(Scoped static)**: 複雑な追加リクエストなしで、コードを整理(論理的分離)した状態に保つ。
|
|
114
|
+
- **名前空間付き動的(Scoped dynamic)**: コード分割とパフォーマンスのための最善のアプローチ。現在のビューとアクティブなロケールに必要なものだけをロードし、メモリ使用量を最小限に抑える。
|
|
115
|
+
|
|
116
|
+
### 測定項目:
|
|
117
|
+
|
|
118
|
+
各スタックについて実際のブラウザで同じ多言語アプリを実行し、実際にネットワーク上を流れたデータ量と時間を記録しました。サイズは**通常のWeb圧縮後**の数値です。これは、生のソースコード量よりもユーザーが実際にダウンロードする量に近いからです。
|
|
119
|
+
|
|
120
|
+
- **i18nライブラリのサイズ**: バンドル、ツリーシェイキング、ミニファイ後のi18nライブラリのサイズです。空のコンポーネントにおけるプロバイダーやコンポーザブル(composables)のコードサイズを指し、翻訳ファイルのロードは含みません。コンテンツが入る前に、ライブラリ自体がどれほど「高価」であるかを示します。
|
|
121
|
+
|
|
122
|
+
- **1ページあたりのJavaScript**: 各ベンチマークルートにおいて、ブラウザが読み込むスクリプトの量です。テストスイート内のページの平均値(およびロケールごとの平均値)です。重いページは遅いページです。
|
|
123
|
+
|
|
124
|
+
- **他のロケールからのリーク(Leakage)**: 同じページの内容ですが、別の言語のコンテンツが誤って監査対象のページにロードされてしまうことです。このコンテンツは不要であり、避けるべきです(例:`/en/about` ページのバンドルに含まれる `/fr/about` ページの内容)。
|
|
125
|
+
|
|
126
|
+
- **他のルートからのリーク**: アプリ内の**他の画面**についても同様です。1つのページしか開いていないのに、他の画面のテキストが一緒に運ばれていないかを示します(例:`/en/contact` ページのバンドルに含まれる `/en/about` ページの内容)。数値が高い場合は、分割が不十分であるか、バンドルが広範すぎることを示唆しています。
|
|
127
|
+
|
|
128
|
+
- **コンポーネントの平均バンドルサイズ**: 一般的なUI要素を**一つずつ**測定します。これにより、国際化が日常的なコンポーネントをひっそりと肥大化させていないかを確認できます。例えば、コンポーネントが再レンダリングされる際、それらすべてのデータをメモリからロードすることになります。巨大なJSONをコンポーネントに紐付けることは、未使用のデータの大きなストアを接続するようなもので、コンポーネントのパフォーマンスを低下させます。
|
|
129
|
+
|
|
130
|
+
- **言語切り替えの反応性**: アプリ自身のコントロールを使用して言語を切り替え、ページが明確に切り替わるまでの時間を測定します。これはユーザーが気づく時間です。
|
|
131
|
+
|
|
132
|
+
- **言語変更後のレンダリング作業**: 言語が切り替わり始めた後に、インターフェースが新しい言語で再描画するために費やした労力です。「体感」時間とフレームワークのコストが異なる場合に役立ちます。
|
|
133
|
+
|
|
134
|
+
- **初期ページロード時間**: ナビゲーションから、ブラウザがページを完全にロードしたと判断するまでの時間です。コールドスタートの比較に役立ちます。
|
|
135
|
+
|
|
136
|
+
- **ハイドレーション時間(Hydration)**: クライアントがサーバーからのHTMLをインタラクティブなものに変えるのに費やす時間です。表内のダッシュ(-)は、その実装がこのベンチマークで信頼できるハイドレーションの数値を提供しなかったことを意味します。
|
|
137
|
+
|
|
138
|
+
## 結果の詳細
|
|
139
|
+
|
|
140
|
+
### 1 - 避けるべきソリューション
|
|
141
|
+
|
|
142
|
+
> Vueエコシステムにおいて、明確に避けるべきソリューションはありません。
|
|
143
|
+
|
|
144
|
+
### 2 - 許容できるソリューション
|
|
145
|
+
|
|
146
|
+
**(vue-i18n)** (`vue-i18n@11.4.0`):
|
|
147
|
+
|
|
148
|
+
- **vue-i18n** は間違いなくVueで最も使用されているi18nライブラリであり、多くの機能と巨大なエコシステムを持っています。しかし、内部的にはかなり重いソリューションです。メッセージの遅延ロードを統合していても、スコーピング(scoping)機能が欠けています。標準的なVue SPAアプリの場合は問題ありませんが、@nuxt/i18nを使用するNuxtアプリの場合、すべてのページのメッセージが単一のページに含まれてしまうことになります。10ページを超える大規模なNuxtアプリでは、これが深刻な問題になる可能性があります。
|
|
149
|
+
|
|
150
|
+
パッケージは非常に重いです(~24.3kb。これは `vue-intlayer` の約9倍です)。
|
|
151
|
+
|
|
152
|
+
**(fluent-vue)** (`fluent-vue@0.5.0`):
|
|
153
|
+
|
|
154
|
+
- **fluent-vue** は .ftl 形式を通じて革新を試みています。メッセージの構成は素晴らしく、始めやすいです。しかし実際には、型安全性の欠如によりエラーのリスクが高まり、デバッグに時間がかかる可能性があります。さらに、このソリューションはViteプラグインを使用してメッセージをロードしますが、これによりすべての言語の全コンテンツが各ページに強制的にロードされます。加えて、これは極めて重いソリューションです(~92.7kb。これは `vue-intlayer` の約34倍です)。
|
|
155
|
+
|
|
156
|
+
### 3 - 推奨事項
|
|
157
|
+
|
|
158
|
+
**(Intlayer)** (`vue-intlayer@8.7.12`):
|
|
159
|
+
|
|
160
|
+
客観性を保つため、`vue-intlayer` については私自身のソリューションであるため、個人的な評価は控えます。
|