@intlayer/docs 8.7.4 → 8.7.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.
Files changed (81) hide show
  1. package/blog/de/next-i18next_vs_next-intl_vs_intlayer.md +0 -2
  2. package/blog/en-GB/next-i18next_vs_next-intl_vs_intlayer.md +0 -2
  3. package/blog/es/next-i18next_vs_next-intl_vs_intlayer.md +0 -2
  4. package/blog/fr/next-i18next_vs_next-intl_vs_intlayer.md +0 -2
  5. package/blog/id/list_i18n_technologies/frameworks/svelte.md +0 -2
  6. package/blog/it/next-i18next_vs_next-intl_vs_intlayer.md +0 -2
  7. package/blog/ja/next-i18next_vs_next-intl_vs_intlayer.md +0 -2
  8. package/blog/ko/next-i18next_vs_next-intl_vs_intlayer.md +0 -2
  9. package/blog/pl/list_i18n_technologies/frameworks/svelte.md +0 -2
  10. package/blog/pt/next-i18next_vs_next-intl_vs_intlayer.md +0 -2
  11. package/blog/ru/next-i18next_vs_next-intl_vs_intlayer.md +0 -2
  12. package/blog/vi/list_i18n_technologies/frameworks/svelte.md +0 -2
  13. package/blog/zh/next-i18next_vs_next-intl_vs_intlayer.md +0 -2
  14. package/dist/cjs/generated/docs.entry.cjs +60 -0
  15. package/dist/cjs/generated/docs.entry.cjs.map +1 -1
  16. package/dist/esm/generated/docs.entry.mjs +60 -0
  17. package/dist/esm/generated/docs.entry.mjs.map +1 -1
  18. package/dist/types/generated/docs.entry.d.ts +3 -0
  19. package/dist/types/generated/docs.entry.d.ts.map +1 -1
  20. package/docs/ar/benchmark/index.md +29 -0
  21. package/docs/ar/benchmark/nextjs.md +227 -0
  22. package/docs/ar/benchmark/tanstack.md +193 -0
  23. package/docs/ar/intlayer_with_tanstack.md +0 -2
  24. package/docs/de/benchmark/index.md +29 -0
  25. package/docs/de/benchmark/nextjs.md +227 -0
  26. package/docs/de/benchmark/tanstack.md +193 -0
  27. package/docs/en/benchmark/___NOTE.md +82 -0
  28. package/docs/en/benchmark/___nextjs.md +195 -0
  29. package/docs/en/benchmark/___tanstack.md +187 -0
  30. package/docs/en/benchmark/index.md +29 -0
  31. package/docs/en/benchmark/nextjs.md +228 -0
  32. package/docs/en/benchmark/tanstack.md +217 -0
  33. package/docs/en-GB/benchmark/index.md +29 -0
  34. package/docs/en-GB/benchmark/nextjs.md +228 -0
  35. package/docs/en-GB/benchmark/tanstack.md +193 -0
  36. package/docs/es/benchmark/index.md +29 -0
  37. package/docs/es/benchmark/nextjs.md +226 -0
  38. package/docs/es/benchmark/tanstack.md +193 -0
  39. package/docs/fr/benchmark/index.md +29 -0
  40. package/docs/fr/benchmark/nextjs.md +227 -0
  41. package/docs/fr/benchmark/tanstack.md +193 -0
  42. package/docs/hi/benchmark/index.md +29 -0
  43. package/docs/hi/benchmark/nextjs.md +227 -0
  44. package/docs/hi/benchmark/tanstack.md +193 -0
  45. package/docs/id/benchmark/index.md +29 -0
  46. package/docs/id/benchmark/nextjs.md +227 -0
  47. package/docs/id/benchmark/tanstack.md +193 -0
  48. package/docs/id/intlayer_with_react_native+expo.md +0 -2
  49. package/docs/it/benchmark/index.md +29 -0
  50. package/docs/it/benchmark/nextjs.md +227 -0
  51. package/docs/it/benchmark/tanstack.md +193 -0
  52. package/docs/ja/benchmark/index.md +29 -0
  53. package/docs/ja/benchmark/nextjs.md +227 -0
  54. package/docs/ja/benchmark/tanstack.md +193 -0
  55. package/docs/ko/benchmark/index.md +29 -0
  56. package/docs/ko/benchmark/nextjs.md +227 -0
  57. package/docs/ko/benchmark/tanstack.md +193 -0
  58. package/docs/ko/intlayer_with_tanstack.md +0 -2
  59. package/docs/pl/benchmark/index.md +29 -0
  60. package/docs/pl/benchmark/nextjs.md +227 -0
  61. package/docs/pl/benchmark/tanstack.md +193 -0
  62. package/docs/pt/benchmark/index.md +29 -0
  63. package/docs/pt/benchmark/nextjs.md +227 -0
  64. package/docs/pt/benchmark/tanstack.md +193 -0
  65. package/docs/ru/benchmark/index.md +29 -0
  66. package/docs/ru/benchmark/nextjs.md +227 -0
  67. package/docs/ru/benchmark/tanstack.md +193 -0
  68. package/docs/tr/benchmark/index.md +29 -0
  69. package/docs/tr/benchmark/nextjs.md +227 -0
  70. package/docs/tr/benchmark/tanstack.md +193 -0
  71. package/docs/uk/benchmark/index.md +29 -0
  72. package/docs/uk/benchmark/nextjs.md +227 -0
  73. package/docs/uk/benchmark/tanstack.md +193 -0
  74. package/docs/vi/benchmark/index.md +29 -0
  75. package/docs/vi/benchmark/nextjs.md +227 -0
  76. package/docs/vi/benchmark/tanstack.md +193 -0
  77. package/docs/zh/benchmark/index.md +29 -0
  78. package/docs/zh/benchmark/nextjs.md +227 -0
  79. package/docs/zh/benchmark/tanstack.md +193 -0
  80. package/package.json +6 -6
  81. package/src/generated/docs.entry.ts +60 -0
@@ -0,0 +1,227 @@
1
+ ---
2
+ createdAt: 2026-04-20
3
+ updatedAt: 2026-04-21
4
+ title: Najlepsze rozwiązanie i18n dla Next.js w 2026 r. - Raport Benchmark
5
+ description: Porównaj biblioteki internacjonalizacji (i18n) dla Next.js, takie jak next-intl, next-i18next i Intlayer. Szczegółowy raport wydajności dotyczący rozmiaru pakietu, wycieków i reaktywności.
6
+ keywords:
7
+ - benchmark
8
+ - i18n
9
+ - intl
10
+ - nextjs
11
+ - wydajność
12
+ - intlayer
13
+ slugs:
14
+ - doc
15
+ - benchmark
16
+ - nextjs
17
+ author: Aymeric PINEAU
18
+ applicationTemplate: https://github.com/intlayer-org/benchmark-i18n
19
+ history:
20
+ - version: 8.7.5
21
+ date: 2026-01-06
22
+ changes: "Inicjalizacja benchmarka"
23
+ ---
24
+
25
+ # Biblioteki i18n dla Next.js — Raport Benchmark 2026
26
+
27
+ Ta strona to raport z benchmarku rozwiązań i18n w Next.js.
28
+
29
+ ## Spis Treści
30
+
31
+ <Toc/>
32
+
33
+ ## Interaktywny Benchmark
34
+
35
+ <I18nBenchmark framework="nextjs" vertical/>
36
+
37
+ ## Referencja wyników:
38
+
39
+ <iframe
40
+ src="https://intlayer.org/markdown?url=https%3A%2F%2Fraw.githubusercontent.com%2Fintlayer-org%2Fbenchmark-i18n%2Fmain%2Freport%2Fscripts%2Fsummarize-nextjs.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-nextjs.md
47
+
48
+ Zobacz pełne repozytorium benchmarka [tutaj](https://github.com/intlayer-org/benchmark-i18n).
49
+
50
+ ## Wprowadzenie
51
+
52
+ Biblioteki internacjonalizacji mają ogromny wpływ na Twoją aplikację. Głównym ryzykiem jest ładowanie treści dla każdej strony i każdego języka, gdy użytkownik odwiedza tylko jedną stronę.
53
+
54
+ W miarę rozwoju aplikacji rozmiar pakietu może rosnąć wykładniczo, co może zauważalnie obniżyć wydajność.
55
+
56
+ Jako przykład: w najgorszych przypadkach, po internacjonalizacji Twoja strona może stać się niemal 4 razy większa.
57
+
58
+ Innym skutkiem bibliotek i18n jest wolniejszy rozwój. Przekształcanie komponentów w wielojęzyczne treści w wielu językach jest czasochłonne.
59
+
60
+ Ponieważ problem jest trudny, istnieje wiele rozwiązań — niektóre koncentrują się na DX (Developer Experience), inne na wydajności lub skalowalności itd.
61
+
62
+ Intlayer stara się optymalizować we wszystkich tych wymiarach.
63
+
64
+ ## Przetestuj swoją aplikację
65
+
66
+ Aby ujawnić te problemy, zbudowałem darmowy skaner, który możesz wypróbować [tutaj](https://intlayer.org/i18n-seo-scanner).
67
+
68
+ <iframe src="https://intlayer.org/i18n-seo-scanner" width="100%" height="600px" style="border:none;"/>
69
+
70
+ ## Problem
71
+
72
+ Istnieją dwa główne sposoby na ograniczenie wpływu aplikacji wielojęzycznej na rozmiar pakietu:
73
+
74
+ - Podział plików JSON (lub treści) na pliki / zmienne / przestrzenie nazw (namespaces), aby bundler mógł usunąć (tree-shake) nieużywaną treść dla danej strony.
75
+ - Dynamiczne ładowanie treści strony tylko w języku użytkownika.
76
+
77
+ Ograniczenia techniczne tych podejść:
78
+
79
+ **Ładowanie dynamiczne**
80
+
81
+ Nawet gdy deklarujesz ścieżki typu `[locale]/page.tsx`, korzystając z Webpacka lub Turbopacka, i nawet jeśli zdefiniowano `generateStaticParams`, bundler nie traktuje `locale` jako stałej statycznej. Oznacza to, że może on pobrać treść dla wszystkich języków do każdej strony. Głównym sposobem na ograniczenie tego jest ładowanie treści poprzez import dynamiczny (np. `import('./locales/${locale}.json')`).
82
+
83
+ To, co dzieje się w czasie budowania (build time), to fakt, że Next.js generuje jeden pakiet JS na lokalizację (np. `./locales_pl_12345.js`). Po wysłaniu strony do klienta, gdy strona jest uruchamiana, przeglądarka wykonuje dodatkowe żądanie HTTP o potrzebny plik JS (np. `./locales_pl_12345.js`).
84
+
85
+ > Innym sposobem na rozwiązanie tego samego problemu jest użycie `fetch()` do dynamicznego ładowania plików JSON. Tak działa `Tolgee`, gdy pliki JSON znajdują się w `/public`, lub `next-translate`, który polega na `getStaticProps` do ładowania treści. Przepływ jest taki sam: przeglądarka wysyła dodatkowe żądanie HTTP, aby załadować zasób.
86
+
87
+ **Podział treści (Content splitting)**
88
+
89
+ Jeśli używasz składni typu `const t = useTranslation()` + `t('moj-obiekt.moj-podobiekt.moj-klucz')`, cały plik JSON musi zazwyczaj znajdować się w pakiecie, aby biblioteka mogła go przeanalizować i rozwiązać klucz. Duża część tej treści jest wysyłana nawet wtedy, gdy nie jest używana na stronie.
90
+
91
+ Aby to złagodzić, niektóre biblioteki proszą o zadeklarowanie na poziomie strony, które przestrzenie nazw należy załadować — np. `next-i18next`, `next-intl`, `lingui`, `next-translate`, `next-international`.
92
+
93
+ Z kolei `Paraglide` dodaje dodatkowy krok przed budowaniem, aby zamienić pliki JSON na proste symbole, takie jak `const en_my_var = () => 'moja wartosc'`. Teoretycznie umożliwia to usuwanie (tree-shaking) nieużywanej treści na stronie. Jak zobaczymy, ta metoda wciąż ma swoje wady.
94
+
95
+ Wreszcie, `Intlayer` stosuje optymalizację w czasie budowania, dzięki czemu `useIntlayer('moj-klucz')` jest zastępowany bezpośrednio odpowiednią treścią.
96
+
97
+ ## Metodologia
98
+
99
+ W tym benchmarku porównaliśmy następujące biblioteki:
100
+
101
+ - `Base App` (Brak biblioteki i18n)
102
+ - `next-intlayer` (v8.7.5)
103
+ - `next-i18next` (v16.0.5)
104
+ - `next-intl` (v4.9.1)
105
+ - `@lingui/core` (v5.3.0)
106
+ - `next-translate` (v3.1.2)
107
+ - `next-international` (v1.3.1)
108
+ - `@inlang/paraglide-js` (v2.15.1)
109
+ - `tolgee` (v7.0.0)
110
+ - `@lingo.dev/compiler` (v0.4.0)
111
+ - `wuchale` (v0.22.11)
112
+ - `gt-next` (v6.16.5)
113
+
114
+ Użyłem `Next.js` w wersji `16.2.4` z App Routerem.
115
+
116
+ Zbudowałem wielojęzyczną aplikację z **10 stronami** i **10 językami**.
117
+
118
+ Porównałem **cztery strategie ładowania**:
119
+
120
+ | Strategia | Brak przestrzeni nazw (globalna) | Z przestrzeniami nazw (scoped) |
121
+ | :----------------------- | :------------------------------------------------ | :------------------------------------------------------------------------------- |
122
+ | **Ładowanie statyczne** | **Static**: Wszystko w pamięci przy starcie. | **Scoped static**: Podział na przestrzenie nazw; wszystko ładowane przy starcie. |
123
+ | **Ładowanie dynamiczne** | **Dynamic**: Ładowanie na żądanie na lokalizację. | **Scoped dynamic**: Szczegółowe ładowanie na przestrzeń nazw i lokalizację. |
124
+
125
+ ## Podsumowanie strategii
126
+
127
+ - **Static**: Prosta; brak opóźnień sieciowych po początkowym załadowaniu. Minus: duży rozmiar pakietu.
128
+ - **Dynamic**: Redukuje początkową wagę (lazy-loading). Idealna w przypadku wielu lokalizacji.
129
+ - **Scoped static**: Utrzymuje porządek w kodzie (separacja logiczna) bez skomplikowanych dodatkowych żądań sieciowych.
130
+ - **Scoped dynamic**: Najlepsze podejście pod kątem dzielenia kodu (code splitting) i wydajności. Minimalizuje zużycie pamięci, ładując tylko to, czego potrzebuje bieżący widok i aktywna lokalizacja.
131
+
132
+ ### Co mierzyłem:
133
+
134
+ Uruchomiłem tę samą wielojęzyczną aplikację w prawdziwej przeglądarce dla każdego stosu technologicznego, a następnie zanotowałem, co faktycznie zostało wysłane przez sieć i ile czasu zajęły operacje. Rozmiary są podawane **po normalnej kompresji internetowej**, ponieważ jest to bliższe temu, co faktycznie pobierają użytkownicy.
135
+
136
+ - **Rozmiar biblioteki internacjonalizacji**: Po spakowaniu, tree-shakingu i minifikacji, rozmiar biblioteki i18n to rozmiar kodu dostawców (np. `NextIntlClientProvider`) + hooków (np. `useTranslations`) w pustym komponencie. Nie obejmuje ładowania plików tłumaczeń. Odpowiada na pytanie, jak "droga" jest biblioteka, zanim Twoja treść znajdzie się w projekcie.
137
+
138
+ - **JavaScript na stronę**: Dla każdej trasy benchmarku, ile skryptów przeglądarka pobiera podczas tej wizyty, uśrednione dla wszystkich stron w zestawie (i we wszystkich lokalizacjach). Ciężkie strony to wolne strony.
139
+
140
+ - **Wyciek z innych lokalizacji (Leakage)**: To treść tej samej strony, ale w innym języku, która została omyłkowo załadowana na badanej stronie. Treść ta jest zbędna i należy jej unikać (np. treść strony `/fr/about` w pakiecie strony `/en/about`).
141
+
142
+ - **Wyciek z innych ścieżek**: Ta sama idea dla **innych ekranów** w aplikacji: czy ich teksty są dołączone, gdy otworzyłeś tylko jedną stronę (np. treść strony `/en/about` w pakiecie strony `/en/contact`). Wysoki wynik sugeruje słaby podział lub zbyt szerokie pakiety.
143
+
144
+ - **Średni rozmiar pakietu komponentu**: Typowe elementy interfejsu są mierzone **pojedynczo**, zamiast ukrywać się wewnątrz jednej gigantycznej liczby dla aplikacji. Pokazuje to, czy internacjonalizacja po cichu „pompuje” codzienne komponenty. Na przykład, jeśli Twój komponent renderuje się ponownie, załaduje wszystkie te dane z pamięci. Dołączanie gigantycznego pliku JSON do dowolnego komponentu jest jak podłączanie wielkiego magazynu nieużywanych danych, który spowolni wydajność Twoich komponentów.
145
+
146
+ - **Responsywność zmiany języka**: Przełączam język za pomocą własnego mechanizmu aplikacji i mierzę czas, aż strona wyraźnie się przełączy — to, co zauważyłby użytkownik, a nie mikrokrok laboratoryjny.
147
+
148
+ - **Praca renderowania po zmianie języka**: Bardziej szczegółowa analiza: ile wysiłku kosztowało interfejs ponowne odrysowanie dla nowego języka po rozpoczęciu zmiany. Przydatne, gdy „odczuwalny” czas i koszt frameworka się różnią.
149
+
150
+ - **Początkowy czas ładowania strony**: Od nawigacji do momentu, w którym przeglądarka uzna stronę za w pełni załadowaną dla testowanych przeze mnie scenariuszy. Dobre do porównywania „zimnych startów” (cold starts).
151
+
152
+ - **Czas hydratacji (Hydration)**: Gdy aplikacja to udostępnia, ile czasu klient spędza na zamianie kodu HTML z serwera w coś, co można faktycznie kliknąć. Myślnik w tabelach oznacza, że dana implementacja nie dostarczyła wiarygodnej wartości hydratacji w tym benchmarku.
153
+
154
+ ## Szczegóły wyników
155
+
156
+ ### 1 — Rozwiązania, których należy unikać
157
+
158
+ Należy wyraźnie unikać niektórych rozwiązań, takich jak `gt-next` czy `lingo.dev`. Łączą one uzależnienie od dostawcy (vendor lock-in) z zaśmiecaniem bazy kodu. Mimo wielu godzin spędzonych na próbach ich wdrożenia, nigdy nie udało mi się sprawić, by działały poprawnie — ani w TanStack Start, ani w Next.js.
159
+
160
+ Napotkane problemy:
161
+
162
+ **(General Translation)** (`gt-next@6.16.5`):
163
+
164
+ - W przypadku aplikacji o rozmiarze 110 KB, `gt-react` dodaje ponad 440 KB ekstra.
165
+ - Komunikat `Quota Exceeded, please upgrade your plan` przy pierwszej próbie budowania z General Translation.
166
+ - Tłumaczenia nie są renderowane; otrzymuję błąd `Error: <T> used on the client-side outside of <GTProvider>`, co wydaje się być błędem w bibliotece.
167
+ - Podczas wdrażania **gt-tanstack-start-react** napotkałem również [problem](https://github.com/generaltranslation/gt/issues/1210#event-24510646961) z biblioteką: błąd `does not provide an export named 'printAST' - @formatjs/icu-messageformat-parser`, który powodował awarię aplikacji. Po zgłoszeniu tego problemu opiekun naprawił go w ciągu 24 godzin.
168
+ - Biblioteka blokuje statyczne renderowanie stron Next.js.
169
+
170
+ **(Lingo.dev)** (`@lingo.dev/compiler@0.4.0`):
171
+
172
+ - Przekroczenie limitu AI, co całkowicie blokuje budowanie — nie można zatem wdrożyć aplikacji na produkcję bez płacenia.
173
+ - Kompilator pomijał niemal 40% przetłumaczonej treści. Musiałem przepisać wszystkie struktury `.map` na płaskie bloki komponentów, aby go uruchomić.
174
+ - Ich CLI jest zabugowane i miało tendencję do resetowania pliku konfiguracyjnego bez powodu.
175
+ - Podczas budowania całkowicie wymazywało wygenerowane pliki JSON, gdy dodawana była nowa treść. W rezultacie kilka kluczy mogło wymazać ponad 300 istniejących kluczy.
176
+
177
+ ### 2 — Rozwiązania eksperymentalne
178
+
179
+ **(Wuchale)** (`wuchale@0.22.11`):
180
+
181
+ Idea stojąca za `Wuchale` jest interesująca, ale nie jest to jeszcze opłacalne rozwiązanie. Napotkałem problemy z reaktywnością i musiałem wymusić ponowne renderowanie dostawcy, aby aplikacja działała. Dokumentacja jest również dość niejasna, co utrudnia wdrożenie.
182
+
183
+ **(Paraglide)** (`@inlang/paraglide-js@2.15.1`):
184
+
185
+ `Paraglide` oferuje innowacyjne i przemyślane podejście. Mimo to w tym benchmarku reklamowany tree-shaking nie zadziałał w moich konfiguracjach Next.js ani TanStack Start. Przepływ pracy i DX są bardziej złożone niż w innych opcjach.
186
+ Osobiście nie podoba mi się konieczność regenerowania plików JS przed każdym przesłaniem kodu (push), co stwarza ciągłe ryzyko konfliktów scalania (merge conflicts) przy Pull Requestach. Narzędzie wydaje się również bardziej skoncentrowane na Vite niż na Next.js.
187
+ Wreszcie, w porównaniu z innymi rozwiązaniami, Paraglide nie używa magazynu (np. React context) do pobierania bieżącej lokalizacji w celu renderowania treści. Dla każdego przeanalizowanego węzła żąda lokalizacji z localStorage / cookie itp. Prowadzi to do wykonywania niepotrzebnej logiki, co wpływa na reaktywność komponentu.
188
+
189
+ ### 3 — Akceptowalne rozwiązania
190
+
191
+ **(Tolgee)** (`tolgee@7.0.0`):
192
+
193
+ `Tolgee` rozwiązuje wiele z wymienionych wcześniej problemów. Uznałem jednak, że trudniej go wdrożyć niż podobne narzędzia. Nie zapewnia on bezpieczeństwa typów (type safety), co utrudnia również wyłapywanie brakujących kluczy w czasie kompilacji. Musiałem opakować funkcje Tolgee we własne funkcje, aby dodać wykrywanie brakujących kluczy.
194
+
195
+ **(Next Intl)** (`next-intl@4.9.1`):
196
+
197
+ `next-intl` to obecnie najmodniejsza opcja i ta, którą agenci AI forsują najbardziej, ale moim zdaniem niesłusznie. Rozpoczęcie pracy jest łatwe. W praktyce optymalizacja pod kątem ograniczania wycieków jest złożona. Połączenie dynamicznego ładowania + przestrzeni nazw + typów TypeScript bardzo spowalnia rozwój. Pakiet jest również dość ciężki (~13 KB dla `NextIntlClientProvider` + `useTranslations`, co stanowi ponad 2-krotność `next-intlayer`). **next-intl** blokował niegdyś statyczne renderowanie stron Next.js. Udostępnia on funkcję pomocniczą o nazwie `setRequestLocale()`. Wydaje się, że zostało to częściowo rozwiązane w przypadku scentralizowanych plików, takich jak `en.json` / `fr.json`, ale statyczne renderowanie wciąż przestaje działać, gdy treść jest podzielona na przestrzenie nazw, takie jak `en/shared.json` / `fr/shared.json` / `es/shared.json`.
198
+
199
+ **(Next I18next)** (`next-i18next@16.0.5`):
200
+
201
+ `next-i18next` jest prawdopodobnie najpopularniejszą opcją, ponieważ był jednym z pierwszych rozwiązań i18n dla aplikacji JavaScript. Posiada on wiele wtyczek społecznościowych. Ma on te same główne wady co `next-intl`. Pakiet jest szczególnie ciężki (~18 KB dla `I18nProvider` + `useTranslation`, około 3-krotność `next-intlayer`).
202
+
203
+ Różnią się również formaty komunikatów: `next-intl` używa ICU MessageFormat, podczas gdy `i18next` używa własnego formatu.
204
+
205
+ **(Next International)** (`next-international@1.3.1`):
206
+
207
+ `next-international` również radzi sobie z powyższymi problemami, ale nie różni się zbytnio od `next-intl` czy `next-i18next`. Zawiera on funkcję `scopedT()` dla tłumaczeń specyficznych dla przestrzeni nazw, ale jej użycie nie ma praktycznie żadnego wpływu na rozmiar pakietu.
208
+
209
+ **(Lingui)** (`@lingui/core@5.3.0`):
210
+
211
+ `Lingui` jest często chwalony. Osobiście uznałem, że proces `lingui extract` / `lingui compile` jest bardziej złożony niż w przypadku alternatyw, bez wyraźnej przewagi. Zauważyłem również niespójne składnie, które mylą AI (np. `t()`, `t''`, `i18n.t()`, `<Trans>`).
212
+
213
+ ### 4 — Rekomendacje
214
+
215
+ **(Next Translate)** (`next-translate@3.1.2`):
216
+
217
+ `next-translate` to moja główna rekomendacja, jeśli lubisz API w stylu `t()`. Działa on elegancko poprzez `next-translate-plugin`, ładując przestrzenie nazw przez `getStaticProps` za pomocą loadera Webpack / Turbopack. Jest to również najlżejsza opcja w tym zestawieniu (~2.5 KB). Jeśli chodzi o przestrzenie nazw, definiowanie ich na poziomie strony lub trasy w konfiguracji jest przemyślane i łatwiejsze w utrzymaniu niż w przypadku głównych alternatyw, takich jak **next-intl** czy **next-i18next**. W wersji `3.1.2` zauważyłem, że statyczne renderowanie nie działało; Next.js powracał do renderowania dynamicznego.
218
+
219
+ **(Intlayer)** (`next-intlayer@8.7.5`):
220
+
221
+ Nie będę osobiście oceniał `next-intlayer` ze względu na obiektywizm, ponieważ jest to moje własne rozwiązanie.
222
+
223
+ ### Notatka osobista
224
+
225
+ Ta notatka jest osobista i nie wpływa na wyniki benchmarku. W świecie i18n często widać konsensus wokół wzorca `const t = useTranslation('xx')` + `<>{t('xx.xx')}</>`.
226
+
227
+ W aplikacjach React wstrzykiwanie funkcji jako `ReactNode` jest w mojej ocenie anty-wzorcem. Dodaje to również zbędną złożoność i narzut wykonania JavaScript (nawet jeśli prawie niezauważalny).
@@ -0,0 +1,193 @@
1
+ ---
2
+ createdAt: 2026-04-20
3
+ updatedAt: 2026-04-21
4
+ title: Najlepsze rozwiązanie i18n dla TanStack Start w 2026 r. - Raport Benchmark
5
+ description: Porównaj biblioteki internacjonalizacji dla TanStack Start, takie jak react-i18next, use-intl i Intlayer. Szczegółowy raport wydajności dotyczący rozmiaru pakietu, wycieków i reaktywności.
6
+ keywords:
7
+ - benchmark
8
+ - i18n
9
+ - intl
10
+ - tanstack
11
+ - wydajność
12
+ - intlayer
13
+ slugs:
14
+ - doc
15
+ - benchmark
16
+ - tanstack
17
+ author: Aymeric PINEAU
18
+ applicationTemplate: https://github.com/intlayer-org/benchmark-i18n-tanstack-start-template
19
+ history:
20
+ - version: 8.7.5
21
+ date: 2026-01-06
22
+ changes: "Inicjalizacja benchmarka"
23
+ ---
24
+
25
+ # Biblioteki i18n dla TanStack Start — Raport Benchmark 2026
26
+
27
+ Ta strona to raport z benchmarku rozwiązań i18n w TanStack Start.
28
+
29
+ ## Spis Treści
30
+
31
+ <Toc/>
32
+
33
+ ## Interaktywny Benchmark
34
+
35
+ <I18nBenchmark framework="tanstack" vertical/>
36
+
37
+ ## Referencja wyników:
38
+
39
+ <iframe
40
+ src="https://intlayer.org/markdown?url=https%3A%2F%2Fraw.githubusercontent.com%2Fintlayer-org%2Fbenchmark-i18n%2Fmain%2Freport%2Fscripts%2Fsummarize-tanstack.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-tanstack.md
47
+
48
+ Zobacz pełne repozytorium benchmarka [tutaj](https://github.com/intlayer-org/benchmark-i18n/tree/main).
49
+
50
+ ## Wprowadzenie
51
+
52
+ Rozwiązania internaucjonalizacji należą do najcięższych zależności w aplikacji React. W TanStack Start głównym ryzykiem jest przesyłanie niepotrzebnych treści: tłumaczeń dla innych stron i innych lokalizacji w pakiecie pojedynczej trasy.
53
+
54
+ W miarę rozwoju aplikacji problem ten może szybko spowodować gwałtowny wzrost ilości kodu JavaScript wysyłanego do klienta i spowolnić nawigację.
55
+
56
+ W praktyce, w przypadku najmniej zoptymalizowanych implementacji, strona zinternacjonalizowana może okazać się kilka razy cięższa niż wersja bez i18n.
57
+
58
+ Inny wpływ dotyczy doświadczenia programisty (DX): sposobu deklarowania treści, typów, organizacji przestrzeni nazw, ładowania dynamicznego i reaktywności przy zmianie lokalizacji.
59
+
60
+ ## Przetestuj swoją aplikację
61
+
62
+ Aby szybko wykryć problemy z wyciekami i18n, przygotowałem darmowy skaner dostępny [tutaj](https://intlayer.org/i18n-seo-scanner).
63
+
64
+ <iframe src="https://intlayer.org/i18n-seo-scanner" width="100%" height="600px" style="border:none;"/>
65
+
66
+ ## Problem
67
+
68
+ Dwie dźwignie są niezbędne do ograniczenia kosztów wielojęzycznej aplikacji:
69
+
70
+ - Podział treści na strony / przestrzenie nazw, aby nie ładować całych słowników, gdy nie są one potrzebne.
71
+ - Dynamiczne ładowanie odpowiedniej lokalizacji tylko wtedy, gdy jest to potrzebne.
72
+
73
+ Zrozumienie technicznych ograniczeń tych podejść:
74
+
75
+ **Ładowanie dynamiczne**
76
+
77
+ Bez dynamicznego ładowania większość rozwiązań przechowuje komunikaty w pamięci od pierwszego renderowania, co dodaje znaczny narzut w przypadku aplikacji z wieloma trasami i lokalizacjami.
78
+
79
+ Wraz z ładowaniem dynamicznym akceptujesz kompromis: mniej początkowego kodu JS, ale czasami dodatkowe żądanie przy zmianie języka.
80
+
81
+ **Podział treści (Content splitting)**
82
+
83
+ Składnie oparte na `const t = useTranslation()` + `t('a.b.c')` są bardzo wygodne, ale często zachęcają do utrzymywania dużych obiektów JSON w czasie wykonywania. Ten model utrudnia usuwanie kodu (tree-shaking), chyba że biblioteka oferuje realną strategię podziału na strony.
84
+
85
+ ## Metodologia
86
+
87
+ W tym benchmarku porównaliśmy następujące biblioteki:
88
+
89
+ - `Base App` (Brak biblioteki i18n)
90
+ - `react-intlayer` (v8.7.5-canary.0)
91
+ - `react-i18next` (v17.0.2)
92
+ - `use-intl` (v4.9.1)
93
+ - `@lingui/core` (v5.3.0)
94
+ - `@inlang/paraglide-js` (v2.15.1)
95
+ - `tolgee` (v7.0.0)
96
+ - `react-intl` (v10.1.1)
97
+ - `wuchale` (v0.22.11)
98
+ - `gt-react` (vlatest)
99
+ - `lingo.dev` (v0.133.9)
100
+
101
+ Frameworkiem jest `TanStack Start` z wielojęzyczną aplikacją składającą się z **10 stron** i **10 języków**.
102
+
103
+ Porównaliśmy **cztery strategie ładowania**:
104
+
105
+ | Strategia | Brak przestrzeni nazw (globalna) | Z przestrzeniami nazw (scoped) |
106
+ | :----------------------- | :------------------------------------------------ | :------------------------------------------------------------------------------- |
107
+ | **Ładowanie statyczne** | **Static**: Wszystko w pamięci przy starcie. | **Scoped static**: Podział na przestrzenie nazw; wszystko ładowane przy starcie. |
108
+ | **Ładowanie dynamiczne** | **Dynamic**: Ładowanie na żądanie na lokalizację. | **Scoped dynamic**: Szczegółowe ładowanie na przestrzeń nazw i lokalizację. |
109
+
110
+ ## Podsumowanie strategii
111
+
112
+ - **Static**: Prosta; brak opóźnień sieciowych po początkowym załadowaniu. Minus: duży rozmiar pakietu.
113
+ - **Dynamic**: Redukuje początkową wagę (lazy-loading). Idealna w przypadku wielu lokalizacji.
114
+ - **Scoped static**: Utrzymuje porządek w kodzie (separacja logiczna) bez skomplikowanych dodatkowych żądań sieciowych.
115
+ - **Scoped dynamic**: Najlepsze podejście pod kątem dzielenia kodu (code splitting) i wydajności. Minimalizuje zużycie pamięci, ładując tylko to, czego potrzebuje bieżący widok i aktywna lokalizacja.
116
+
117
+ ## Szczegóły wyników
118
+
119
+ ### 1 — Rozwiązania, których należy unikać
120
+
121
+ Należy wyraźnie unikać niektórych rozwiązań, takich jak `gt-react` czy `lingo.dev`. Łączą one uzależnienie od dostawcy z zaśmiecaniem bazy kodu. Co gorsza: mimo wielu godzin spędzonych na próbach ich wdrożenia, nigdy nie udało mi się sprawić, by działały poprawnie w TanStack Start (podobnie jak w przypadku `gt-next` w Next.js).
122
+
123
+ Napotkane problemy:
124
+
125
+ **(General Translation)** (`gt-react@latest`):
126
+
127
+ - W przypadku aplikacji o rozmiarze około 110 KB, `gt-react` może dodać ponad 440 KB ekstra (rząd wielkości zaobserwowany w implementacji Next.js w tym samym benchmarku).
128
+ - Komunikat `Quota Exceeded, please upgrade your plan` przy pierwszej próbie budowania z General Translation.
129
+ - Tłumaczenia nie są renderowane; otrzymuję błąd `Error: <T> used on the client-side outside of <GTProvider>`, co wydaje się być błędem w bibliotece.
130
+ - Podczas wdrażania **gt-tanstack-start-react** napotkałem również [problem](https://github.com/generaltranslation/gt/issues/1210#event-24510646961) z biblioteką: błąd `does not provide an export named 'printAST' - @formatjs/icu-messageformat-parser`, który powodował awarię aplikacji. Po zgłoszeniu opiekun naprawił go w ciągu 24 godzin.
131
+ - Biblioteki te stosują anty-wzorzec poprzez funkcję `initializeGT()`, blokując możliwość czystego usuwania kodu z pakietu (tree-shaking).
132
+
133
+ **(Lingo.dev)** (`lingo.dev@0.133.9`):
134
+
135
+ - Przekroczenie limitu AI (lub blokująca zależność serwerowa), co sprawia, że budowanie / produkcja są ryzykowne bez płacenia.
136
+ - Kompilator pomijał niemal 40% przetłumaczonej treści. Musiałem przepisać wszystkie struktury `.map` na płaskie bloki komponentów, aby go uruchomić.
137
+ - Ich CLI jest zabugowane i miało tendencję do resetowania pliku konfiguracyjnego bez powodu.
138
+ - Podczas budowania całkowicie wymazywało wygenerowane pliki JSON, gdy dodawana była nowa treść. W rezultacie kilka kluczy mogło wymazać setki istniejących kluczy.
139
+ - Napotkałem problemy z reaktywnością biblioteki w TanStack Start: przy zmianie lokalizacji musiałem wymusić ponowne renderowanie dostawcy, aby działała.
140
+
141
+ ### 2 — Rozwiązania eksperymentalne
142
+
143
+ **(Wuchale)** (`wuchale@0.22.11`):
144
+
145
+ Idea stojąca za `Wuchale` jest interesująca, ale nie jest to jeszcze opłacalne rozwiązanie. Napotkałem problemy z reaktywnością tej biblioteki i musiałem wymusić ponowne renderowanie dostawcy, aby aplikacja działała w TanStack Start. Dokumentacja jest również dość niejasna, co utrudnia wdrożenie.
146
+
147
+ ### 3 — Akceptowalne rozwiązania
148
+
149
+ **(Paraglide)** (`@inlang/paraglide-js@2.15.1`):
150
+
151
+ `Paraglide` oferuje innowacyjne i przemyślane podejście. Mimo to w tym benchmarku reklamowany przez firmę tree-shaking nie zadziałał w mojej implementacji Next.js ani w TanStack Start. Przepływ pracy i DX są również bardziej złożone niż w przypadku innych opcji. Osobiście nie jestem fanem konieczności regenerowania plików JS przed każdym przesłaniem kodu (push), co stwarza ciągłe ryzyko konfliktów scalania dla programistów przy Pull Requestach.
152
+
153
+ **(Tolgee)** (`tolgee@7.0.0`):
154
+
155
+ `Tolgee` rozwiązuje wiele z wymienionych wcześniej problemów. Uznałem jednak, że trudniej z nim zacząć niż z innymi narzędziami o podobnym podejściu. Nie zapewnia on bezpieczeństwa typów, co sprawia, że bardzo trudno jest wyłapać brakujące klucze w czasie kompilacji. Musiałem opakować API Tolgee we własne API, aby dodać wykrywanie brakujących kluczy.
156
+
157
+ W TanStack Start miałem również problemy z reaktywnością: przy zmianie lokalizacji musiałem wymusić ponowne renderowanie dostawcy i zasubskrybować zdarzenia zmiany lokalizacji, aby ładowanie w innym języku zachowywało się poprawnie.
158
+
159
+ **(use-intl)** (`use-intl@4.9.1`):
160
+
161
+ `use-intl` jest obecnie najmodniejszym elementem „intl” w ekosystemie React (z tej samej rodziny co `next-intl`) i jest często forsowany przez agentów AI, ale moim zdaniem niesłusznie w środowisku, w którym liczy się wydajność. Rozpoczęcie pracy jest dość proste. W praktyce proces optymalizacji i ograniczania wycieków jest dość złożony. Podobnie połączenie dynamicznego ładowania + przestrzeni nazw + typów TypeScript bardzo spowalnia rozwój.
162
+
163
+ W TanStack Start unikasz pułapek specyficznych dla Next.js (`setRequestLocale`, statyczne renderowanie), ale główny problem pozostaje ten sam: bez ścisłej dyscypliny pakiet szybko przenosi zbyt wiele komunikatów, a utrzymanie przestrzeni nazw dla każdej trasy staje się uciążliwe.
164
+
165
+ **(react-i18next)** (`react-i18next@17.0.2`):
166
+
167
+ `react-i18next` jest prawdopodobnie najpopularniejszą opcją, ponieważ był jedną z pierwszych, która zaspokoiła potrzeby i18n w aplikacjach JavaScript. Posiada on również szeroki zestaw wtyczek społecznościowych dla konkretnych problemów.
168
+
169
+ Mimo to ma on te same główne wady co stosy zbudowane na `t('a.b.c')`: optymalizacje są możliwe, ale bardzo czasochłonne, a duże projekty niosą ze sobą ryzyko wpadnięcia w złe praktyki (przestrzenie nazw + ładowanie dynamiczne + typy).
170
+
171
+ Różnią się również formaty komunikatów: `use-intl` używa ICU MessageFormat, podczas gdy `i18next` używa własnego formatu — co komplikuje narzędzia lub migracje, jeśli się je miesza.
172
+
173
+ **(Lingui)** (`@lingui/core@5.3.0`):
174
+
175
+ `Lingui` jest często chwalony. Osobiście uznałem, że proces pracy wokół `lingui extract` / `lingui compile` jest bardziej złożony niż w przypadku innych podejść, bez wyraźnej przewagi w tym benchmarku TanStack Start. Zauważyłem również niespójne składnie, które mylą AI (np. `t()`, `t''`, `i18n.t()`, `<Trans>`).
176
+
177
+ **(react-intl)** (`react-intl@10.1.1`):
178
+
179
+ `react-intl` to wydajna implementacja zespołu Format.js. DX pozostaje rozwlekły: `const intl = useIntl()` + `intl.formatMessage({ id: "xx.xx" })` dodaje złożoność, dodatkową pracę JavaScript i wiąże globalną instancję i18n z wieloma węzłami w drzewie React.
180
+
181
+ ### 4 — Rekomendacje
182
+
183
+ Ten benchmark TanStack Start nie ma bezpośredniego odpowiednika `next-translate` (wtyczka Next.js + `getStaticProps`). Dla zespołów, które naprawdę chcą API `t()` z dojrzałym ekosystemem, `react-i18next` i `use-intl` pozostają „rozsądnymi” wyborami, ale przygotuj się na zainwestowanie dużej ilości czasu w optymalizację, aby uniknąć wycieków.
184
+
185
+ **(Intlayer)** (`react-intlayer@8.7.5-canary.0`):
186
+
187
+ Nie będę osobiście oceniał `react-intlayer` ze względu na obiektywizm, ponieważ jest to moje własne rozwiązanie.
188
+
189
+ ### Notatka osobista
190
+
191
+ Ta notatka jest osobista i nie wpływa na wyniki benchmarku. Mimo to w świecie i18n często widać konsensus wokół wzorca takiego jak `const t = useTranslation('xx')` + `<>{t('xx.xx')}</>` dla treści tłumaczonych.
192
+
193
+ W aplikacjach React wstrzykiwanie funkcji jako `ReactNode` jest w mojej ocenie anty-wzorcem. Dodaje to również zbędną złożoność i narzut wykonania JavaScript (nawet jeśli prawie niezauważalny).
@@ -0,0 +1,29 @@
1
+ ---
2
+ createdAt: 2026-04-20
3
+ updatedAt: 2026-04-20
4
+ title: Benchmark das bibliotecas de i18n
5
+ description: Saiba como o Intlayer se compara a outras bibliotecas de i18n em termos de desempenho e tamanho do bundle.
6
+ keywords:
7
+ - benchmark
8
+ - i18n
9
+ - intl
10
+ - nextjs
11
+ - tanstack
12
+ - intlayer
13
+ slugs:
14
+ - doc
15
+ - benchmark
16
+ history:
17
+ - version: 8.7.5
18
+ date: 2026-01-06
19
+ changes: "Início do benchmark"
20
+ ---
21
+
22
+ # Benchmark - Relatório
23
+
24
+ O Benchmark Bloom é uma suíte de benchmarks de desempenho que mede o impacto real das bibliotecas de i18n (internacionalização) em vários frameworks React e estratégias de carregamento.
25
+
26
+ Abaixo estão os relatórios detalhados e a documentação técnica de cada framework:
27
+
28
+ - [**Relatório de benchmark do Next.js**](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pt/benchmark/nextjs.md)
29
+ - [**Relatório de benchmark do TanStack Start**](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pt/benchmark/tanstack.md)