@intlayer/docs 9.5.7 → 9.5.8
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/blog/ar/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/de/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/en/is_intlayer_lighter_than_paraglide.md +288 -0
- package/blog/en-GB/is_intlayer_lighter_than_paraglide.md +285 -0
- package/blog/es/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/fr/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/hi/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/id/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/it/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/ja/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/ko/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/pl/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/pt/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/ru/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/tr/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/uk/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/vi/is_intlayer_lighter_than_paraglide.md +284 -0
- package/blog/zh/is_intlayer_lighter_than_paraglide.md +284 -0
- package/dist/cjs/generated/blog.entry.cjs +20 -0
- package/dist/cjs/generated/blog.entry.cjs.map +1 -1
- package/dist/cjs/generated/docs.entry.cjs +20 -0
- package/dist/cjs/generated/docs.entry.cjs.map +1 -1
- package/dist/cjs/index.cjs +2 -2
- package/dist/esm/generated/blog.entry.mjs +20 -0
- package/dist/esm/generated/blog.entry.mjs.map +1 -1
- package/dist/esm/generated/docs.entry.mjs +20 -0
- package/dist/esm/generated/docs.entry.mjs.map +1 -1
- package/dist/esm/index.mjs +2 -2
- package/dist/types/generated/blog.entry.d.ts +1 -0
- package/dist/types/generated/blog.entry.d.ts.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/nextjs.md +6 -3
- package/docs/ar/benchmark/solid.md +21 -4
- package/docs/ar/benchmark/svelte.md +18 -3
- package/docs/ar/benchmark/tanstack.md +6 -3
- package/docs/ar/benchmark/vue.md +14 -5
- package/docs/ar/cli/index.md +6 -1
- package/docs/ar/cli/upgrade.md +125 -0
- package/docs/de/benchmark/nextjs.md +6 -3
- package/docs/de/benchmark/solid.md +21 -4
- package/docs/de/benchmark/svelte.md +18 -3
- package/docs/de/benchmark/tanstack.md +6 -3
- package/docs/de/benchmark/vue.md +14 -5
- package/docs/de/cli/index.md +6 -1
- package/docs/de/cli/upgrade.md +125 -0
- package/docs/en/agent_skills.md +29 -1
- package/docs/en/benchmark/nextjs.md +6 -3
- package/docs/en/benchmark/solid.md +21 -4
- package/docs/en/benchmark/svelte.md +18 -3
- package/docs/en/benchmark/tanstack.md +7 -4
- package/docs/en/benchmark/vue.md +15 -6
- package/docs/en/cli/index.md +6 -1
- package/docs/en/cli/upgrade.md +125 -0
- package/docs/en-GB/benchmark/nextjs.md +6 -3
- package/docs/en-GB/benchmark/solid.md +21 -4
- package/docs/en-GB/benchmark/svelte.md +18 -3
- package/docs/en-GB/benchmark/tanstack.md +6 -3
- package/docs/en-GB/benchmark/vue.md +15 -6
- package/docs/en-GB/cli/index.md +6 -1
- package/docs/en-GB/cli/upgrade.md +125 -0
- package/docs/es/benchmark/nextjs.md +6 -3
- package/docs/es/benchmark/solid.md +21 -4
- package/docs/es/benchmark/svelte.md +18 -3
- package/docs/es/benchmark/tanstack.md +6 -3
- package/docs/es/benchmark/vue.md +14 -5
- package/docs/es/cli/index.md +6 -1
- package/docs/es/cli/upgrade.md +125 -0
- package/docs/fr/benchmark/nextjs.md +6 -3
- package/docs/fr/benchmark/solid.md +21 -4
- package/docs/fr/benchmark/svelte.md +18 -3
- package/docs/fr/benchmark/tanstack.md +6 -3
- package/docs/fr/benchmark/vue.md +15 -6
- package/docs/fr/cli/index.md +6 -1
- package/docs/fr/cli/upgrade.md +125 -0
- package/docs/hi/benchmark/nextjs.md +6 -3
- package/docs/hi/benchmark/solid.md +21 -4
- package/docs/hi/benchmark/svelte.md +18 -3
- package/docs/hi/benchmark/tanstack.md +6 -3
- package/docs/hi/benchmark/vue.md +15 -6
- package/docs/hi/cli/index.md +6 -1
- package/docs/hi/cli/upgrade.md +125 -0
- package/docs/id/benchmark/nextjs.md +6 -3
- package/docs/id/benchmark/solid.md +21 -4
- package/docs/id/benchmark/svelte.md +18 -3
- package/docs/id/benchmark/tanstack.md +6 -3
- package/docs/id/benchmark/vue.md +15 -6
- package/docs/id/cli/index.md +6 -1
- package/docs/id/cli/upgrade.md +125 -0
- package/docs/it/benchmark/nextjs.md +6 -3
- package/docs/it/benchmark/solid.md +21 -4
- package/docs/it/benchmark/svelte.md +18 -3
- package/docs/it/benchmark/tanstack.md +6 -3
- package/docs/it/benchmark/vue.md +14 -5
- package/docs/it/cli/index.md +6 -1
- package/docs/it/cli/upgrade.md +125 -0
- package/docs/ja/benchmark/nextjs.md +6 -3
- package/docs/ja/benchmark/solid.md +21 -4
- package/docs/ja/benchmark/svelte.md +18 -3
- package/docs/ja/benchmark/tanstack.md +5 -2
- package/docs/ja/benchmark/vue.md +14 -5
- package/docs/ja/cli/index.md +6 -1
- package/docs/ja/cli/upgrade.md +125 -0
- package/docs/ko/benchmark/nextjs.md +6 -3
- package/docs/ko/benchmark/solid.md +21 -4
- package/docs/ko/benchmark/svelte.md +18 -3
- package/docs/ko/benchmark/tanstack.md +6 -3
- package/docs/ko/benchmark/vue.md +15 -6
- package/docs/ko/cli/index.md +6 -1
- package/docs/ko/cli/upgrade.md +126 -0
- package/docs/pl/benchmark/nextjs.md +6 -3
- package/docs/pl/benchmark/solid.md +21 -4
- package/docs/pl/benchmark/svelte.md +18 -3
- package/docs/pl/benchmark/tanstack.md +6 -3
- package/docs/pl/benchmark/vue.md +15 -6
- package/docs/pl/cli/index.md +6 -1
- package/docs/pl/cli/upgrade.md +125 -0
- package/docs/pt/benchmark/nextjs.md +6 -3
- package/docs/pt/benchmark/solid.md +21 -4
- package/docs/pt/benchmark/svelte.md +18 -3
- package/docs/pt/benchmark/tanstack.md +6 -3
- package/docs/pt/benchmark/vue.md +14 -5
- package/docs/pt/cli/index.md +6 -1
- package/docs/pt/cli/upgrade.md +125 -0
- package/docs/ru/benchmark/nextjs.md +6 -3
- package/docs/ru/benchmark/solid.md +21 -4
- package/docs/ru/benchmark/svelte.md +18 -3
- package/docs/ru/benchmark/tanstack.md +6 -3
- package/docs/ru/benchmark/vue.md +15 -6
- package/docs/ru/cli/index.md +6 -1
- package/docs/ru/cli/upgrade.md +125 -0
- package/docs/tr/benchmark/nextjs.md +6 -3
- package/docs/tr/benchmark/solid.md +21 -4
- package/docs/tr/benchmark/svelte.md +18 -3
- package/docs/tr/benchmark/tanstack.md +6 -3
- package/docs/tr/benchmark/vue.md +15 -6
- package/docs/tr/cli/index.md +6 -1
- package/docs/tr/cli/upgrade.md +125 -0
- package/docs/uk/benchmark/nextjs.md +6 -3
- package/docs/uk/benchmark/solid.md +21 -4
- package/docs/uk/benchmark/svelte.md +18 -3
- package/docs/uk/benchmark/tanstack.md +6 -3
- package/docs/uk/benchmark/vue.md +15 -6
- package/docs/uk/cli/index.md +6 -1
- package/docs/uk/cli/upgrade.md +125 -0
- package/docs/vi/benchmark/nextjs.md +6 -3
- package/docs/vi/benchmark/solid.md +21 -4
- package/docs/vi/benchmark/svelte.md +18 -3
- package/docs/vi/benchmark/tanstack.md +6 -3
- package/docs/vi/benchmark/vue.md +15 -6
- package/docs/vi/cli/index.md +6 -1
- package/docs/vi/cli/upgrade.md +125 -0
- package/docs/zh/benchmark/nextjs.md +6 -3
- package/docs/zh/benchmark/solid.md +21 -4
- package/docs/zh/benchmark/svelte.md +18 -3
- package/docs/zh/benchmark/tanstack.md +5 -2
- package/docs/zh/benchmark/vue.md +15 -6
- package/docs/zh/cli/index.md +6 -1
- package/docs/zh/cli/upgrade.md +125 -0
- package/package.json +6 -6
- package/src/generated/blog.entry.ts +20 -0
- package/src/generated/docs.entry.ts +20 -0
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2026-09-23
|
|
3
|
+
updatedAt: 2026-09-23
|
|
4
|
+
title: Intlayer, Paraglide'dan daha mı hafif?
|
|
5
|
+
description: Paraglide, kodları doğrudan deponuza ürettiği için i18n kıyaslamalarında neredeyse sıfır maliyetli görünür. Bu boyutun gerçekte nereye gittiğini, düğüm başına dil çözümlemesinin neden maliyetli olduğunu ve Intlayer'ın dinamik yüklemesinin tüm diller yerine neden yalnızca tek bir dili istemciye gönderdiğini inceliyoruz.
|
|
6
|
+
keywords:
|
|
7
|
+
- Paraglide
|
|
8
|
+
- Intlayer
|
|
9
|
+
- Uluslararasılaştırma
|
|
10
|
+
- i18n
|
|
11
|
+
- Bundle size
|
|
12
|
+
- Tree shaking
|
|
13
|
+
- Benchmark
|
|
14
|
+
- Blog
|
|
15
|
+
slugs:
|
|
16
|
+
- blog
|
|
17
|
+
- is-intlayer-lighter-than-paraglide
|
|
18
|
+
author: aymericzip
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
# Intlayer, Paraglide'dan daha mı hafif?
|
|
22
|
+
|
|
23
|
+
Evet.
|
|
24
|
+
|
|
25
|
+
`Paraglide`, piyasadaki en hafif i18n çözümü olarak haklı bir üne sahiptir ve ilk bakışta [benchmark](https://intlayer.org/tr/doc/benchmark/tanstack) sonuçları da bunu doğrular niteliktedir: kütüphane boyutu sıfıra yakındır. Ancak kütüphane boyutunun sıfır olması, istemciye sıfır bayt gönderildiği anlamına gelmez. Bu yalnızca baytların, söz konusu metriğin ölçmediği bir yerde barındığı anlamına gelir.
|
|
26
|
+
|
|
27
|
+
<TOC/>
|
|
28
|
+
|
|
29
|
+
## Önemli Çıkarımlar
|
|
30
|
+
|
|
31
|
+
**Kütüphane boyutu ortadan kalkmadı, yalnızca gizlendi:**
|
|
32
|
+
|
|
33
|
+
Paraglide, runtime ve mesaj fonksiyonlarını doğrudan kod tabanınızın içine üretir. Bu kod tarayıcıya gönderilir ancak kütüphanenin kodu olarak değil, _sizin_ kodunuz olarak sayılır.
|
|
34
|
+
|
|
35
|
+
**Provider kullanmamak bedava bir kazanım değildir:**
|
|
36
|
+
|
|
37
|
+
Her `m.my_key()` çağrısı dili kendi başına çözümler ve değeri bir context içinden tek seferde okumak yerine, render edilen her düğüm için çerezi veya depolama alanını ayrı ayrı okur.
|
|
38
|
+
|
|
39
|
+
**Dinamik yükleme desteği yoktur:**
|
|
40
|
+
|
|
41
|
+
Paraglide, bir mesajın tüm dillerini istemci paketinize dahil eder. Intlayer ise `importMode: 'dynamic'` veya `'fetch'` ile yalnızca o an görüntülenen dili yükler.
|
|
42
|
+
|
|
43
|
+
**Tree shaking her zaman garanti değildir:**
|
|
44
|
+
|
|
45
|
+
Bazı testlerimizde Paraglide'ın vadettiği tree shaking mekanizması devreye girmedi. Kendi bundle boyutunuzu mutlaka kontrol edin.
|
|
46
|
+
|
|
47
|
+
## Paraglide'ın Yükü Nereye Gidiyor?
|
|
48
|
+
|
|
49
|
+
Kıyaslama raporlarında "kütüphane boyutu" metriği, henüz hiçbir içerik eklenmeden önce boş bir bileşende her bir i18n kütüphanesinin provider ve hook boyutlarını ölçer.
|
|
50
|
+
|
|
51
|
+
| Kütüphane (TanStack Start) | Kütüphane boyutu (gz) | Kütüphane boyutu (min) |
|
|
52
|
+
| ----------------------------- | --------------------- | ---------------------- |
|
|
53
|
+
| `@inlang/paraglide-js@2.15.1` | 1.8 KB | 4.5 KB |
|
|
54
|
+
| `react-intlayer@9.5.1` | 5.0 KB | 15.2 KB |
|
|
55
|
+
|
|
56
|
+
Tek başına değerlendirildiğinde Paraglide kazanmış görünür. Ancak Paraglide bir derleyicidir: `messages/*.json` dosyalarınızı okur ve deponuza bir `paraglide/` klasörü yazar. Bu klasör bir `runtime.js` (dil tespiti, çerez ve depolama stratejileri, URL yerelleştirmesi) ve mesaj başına bir JavaScript fonksiyonu içerir.
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
src/paraglide/
|
|
60
|
+
├── runtime.js # dil algılama, stratejiler, URL yardımcıları
|
|
61
|
+
├── server.js
|
|
62
|
+
├── messages.js # tüm mesajları yeniden dışa aktarır
|
|
63
|
+
└── messages/
|
|
64
|
+
├── _index.js
|
|
65
|
+
├── en.js
|
|
66
|
+
└── fr.js
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Bu kod `src/` klasörünüzde yer aldığından ve göreli bir yolla içe aktarıldığından, paketleyici bunu `node_modules` paketine değil, uygulamanıza ait bir kod olarak kabul eder. Kütüphane boyutu sütunu neredeyse hiçbir şey göstermezken, aynı mantık sayfa bundle'ınız içinde gönderilmeye devam eder.
|
|
70
|
+
|
|
71
|
+
Kod üretmek kendi başına kötü bir fikir değildir: üretilen runtime yalnızca yapılandırmanızın ihtiyaç duyduğu mantığı içerir (ön ek stratejisi, çerez vs yerel depolama vb.). Intlayer aynı sonuca farklı bir yoldan ulaşır; derleme zamanında ortam değişkenleri enjekte eder, böylece paketleyici yapılandırmanızın kullanmadığı kod dallarını otomatik olarak eler. Her iki yaklaşım da `i18next` veya `next-intl` kütüphanelerine kıyasla 3 ila 10 kat daha hafiftir.
|
|
72
|
+
|
|
73
|
+
Dolayısıyla adil bir karşılaştırma kütüphane boyutu üzerinden yapılamaz. Karşılaştırma **sayfa başına gerçekte gönderilen JavaScript miktarı** üzerinden yapılmalıdır.
|
|
74
|
+
|
|
75
|
+
## Ölçülen Sayfa Boyutları
|
|
76
|
+
|
|
77
|
+
TanStack Start uygulaması, 10 sayfa, `en` ve `fr` rotalarında ölçülmüştür, gzip ile sıkıştırılmıştır:
|
|
78
|
+
|
|
79
|
+
| Yapılandırma | Sayfa JS ort (gz) | Temelin üzerinde | Dil sızıntısı | Diğer sayfa sızıntısı |
|
|
80
|
+
| ----------------------------------- | ----------------- | ---------------- | ------------- | --------------------- |
|
|
81
|
+
| Temel (i18n yok) | 111.0 KB | - | 0.0% | 0.0% |
|
|
82
|
+
| `paraglide` (herhangi bir strateji) | 125.1 KB | +14.1 KB | 49.7% | 0.0% |
|
|
83
|
+
| `intlayer` (`importMode: static`) | 125.8 KB | +14.8 KB | 50.0% | 0.0% |
|
|
84
|
+
| `intlayer` (`importMode: dynamic`) | **118.6 KB** | **+7.6 KB** | **0.0%** | **0.0%** |
|
|
85
|
+
|
|
86
|
+
Next.js 16 App Router, aynı uygulama:
|
|
87
|
+
|
|
88
|
+
| Yapılandırma | Sayfa JS ort (gz) | Temelin üzerinde |
|
|
89
|
+
| ---------------- | ----------------- | ---------------- |
|
|
90
|
+
| Temel (i18n yok) | 141.0 KB | - |
|
|
91
|
+
| `paraglide-next` | 155.3 KB | +14.3 KB |
|
|
92
|
+
| `next-intlayer` | **141.3 KB** | **+0.3 KB** |
|
|
93
|
+
|
|
94
|
+
<I18nBenchmark framework="tanstack" vertical/>
|
|
95
|
+
|
|
96
|
+
> Tüm veriler [TanStack Start kıyaslama raporunda](https://intlayer.org/tr/doc/benchmark/tanstack) ve [Next.js kıyaslama raporunda](https://intlayer.org/tr/doc/benchmark/nextjs) incelenebilir. Her bir paket [kıyaslama deposunda](https://github.com/intlayer-org/benchmark-i18n) açıkça görülebilir.
|
|
97
|
+
|
|
98
|
+
İki önemli nokta öne çıkmaktadır:
|
|
99
|
+
|
|
100
|
+
- `static` modda Intlayer, Paraglide ile neredeyse aynı miktarda içerik gönderir (125.8 KB'a karşı 125.1 KB). Bu beklenen bir durumdur: her ikisi de bir sayfanın kullandığı mesajların tüm dillerini içerir.
|
|
101
|
+
- Paraglide, dinamik bir moda sahip olmadığı için hangi strateji seçilirse seçilsin 125.1 KB boyutunda kalır. Yukarıdaki tablodaki her satır statik duruma karşılık gelir.
|
|
102
|
+
|
|
103
|
+
## Provider Bulunmaması: İyi Görünen Ancak Maliyetli Bir Fikir
|
|
104
|
+
|
|
105
|
+
Paraglide bir provider gerektirmez. Bir mesajı içe aktarır ve doğrudan çağırırsınız:
|
|
106
|
+
|
|
107
|
+
```tsx fileName="Hero.tsx"
|
|
108
|
+
import { m } from "../paraglide/messages.js";
|
|
109
|
+
|
|
110
|
+
export const Hero = () => (
|
|
111
|
+
<section>
|
|
112
|
+
<h1>{m.hero_title()}</h1>
|
|
113
|
+
<p>{m.hero_description()}</p>
|
|
114
|
+
<button>{m.hero_cta()}</button>
|
|
115
|
+
</section>
|
|
116
|
+
);
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Context yok, wrapper bileşen yok, hook yok. İlk bakışta daha basit görünür. Ancak dil bilgisinin yine de bir yerden okunması gerekir. Üretilen her mesaj fonksiyonu yaklaşık olarak şu şekildedir (basitleştirilmiş):
|
|
120
|
+
|
|
121
|
+
```js fileName="paraglide/messages/_index.js"
|
|
122
|
+
export const hero_title = (inputs = {}, options = {}) => {
|
|
123
|
+
const locale = options.locale ?? getLocale(); // her çağrıda tekrar çözümlenir
|
|
124
|
+
|
|
125
|
+
if (locale === "en") return en.hero_title(inputs);
|
|
126
|
+
if (locale === "fr") return fr.hero_title(inputs);
|
|
127
|
+
// ...dil başına bir dal
|
|
128
|
+
};
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Ve `getLocale()` fonksiyonu, geçerli dili belirlemek için yapılandırılmış stratejileri (çerez, yerel depolama, URL, varsayılan dil) baştan sona tarar. Dolayısıyla render ettiğiniz her metin düğümü (`<>{m.my_key()}</>`), tarayıcıda `document.cookie` okumak da dahil olmak üzere kendi dil çözümleme sürecini çalıştırır. 200 çevrilmiş dize içeren bir sayfa, render başına 200 kez dil tespiti yapar ve her yeniden render işleminde bu tekrarlanır.
|
|
132
|
+
|
|
133
|
+
Provider tabanlı bir kütüphane ise dili **yalnızca bir kez** okur, bir context'e (veya signal'e, ya da store'a) kaydeder ve her düğüm bellekte hazır bulunan değeri doğrudan okur. Bir provider'ın maliyeti yalnızca birkaç yüz bayttır. Ondan kaçınmak her render sırasında işlemciye ek yük getirir ve bu durum kıyaslamalara doğrudan yansır: Paraglide'ın sayfa yükleme ve dil değiştirme süreleri TanStack Start üzerinde Intlayer'ın belirgin şekilde gerisinde kalmaktadır (sayfa yüklemede 22.1 ms'ye karşı 14.6 ms, uçtan uca reaktivitede 4.3 ms'ye karşı 3.2 ms).
|
|
134
|
+
|
|
135
|
+
## Geliştirici Deneyimi (DX)
|
|
136
|
+
|
|
137
|
+
Paraglide'ın asıl veri kaynağı JSON'dur, ancak JSON dosyalarını doğrudan içe aktarmazsınız. Derleyicinin ürettiği `.js` dosyasını içe aktarırsınız:
|
|
138
|
+
|
|
139
|
+
<Tabs defaultTab="intlayer" group="techno">
|
|
140
|
+
<Tab label="Paraglide" value="paraglide">
|
|
141
|
+
|
|
142
|
+
```json fileName="messages/en.json"
|
|
143
|
+
{
|
|
144
|
+
"hero_title": "Ship your app in every language"
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
```json fileName="messages/tr.json"
|
|
149
|
+
{
|
|
150
|
+
"hero_title": "Uygulamanızı tüm dillerde yayınlayın"
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
```tsx fileName="Hero.tsx"
|
|
155
|
+
// Yalnızca derleyici dosyayı JSON'dan yeniden ürettikten sonra erişilebilir
|
|
156
|
+
import { m } from "../paraglide/messages.js";
|
|
157
|
+
|
|
158
|
+
export const Hero = () => <h1>{m.hero_title()}</h1>;
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
</Tab>
|
|
162
|
+
<Tab label="Intlayer" value="intlayer">
|
|
163
|
+
|
|
164
|
+
```ts fileName="Hero.content.ts"
|
|
165
|
+
import { t, type Dictionary } from "intlayer";
|
|
166
|
+
|
|
167
|
+
export default {
|
|
168
|
+
key: "hero",
|
|
169
|
+
content: {
|
|
170
|
+
title: t({
|
|
171
|
+
tr: "Uygulamanızı tüm dillerde yayınlayın",
|
|
172
|
+
en: "Ship your app in every language",
|
|
173
|
+
}),
|
|
174
|
+
},
|
|
175
|
+
} satisfies Dictionary;
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
```tsx fileName="Hero.tsx"
|
|
179
|
+
import { useIntlayer } from "react-intlayer";
|
|
180
|
+
|
|
181
|
+
export const Hero = () => {
|
|
182
|
+
const { title } = useIntlayer("hero");
|
|
183
|
+
|
|
184
|
+
return <h1>{title}</h1>;
|
|
185
|
+
};
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
</Tab>
|
|
189
|
+
</Tabs>
|
|
190
|
+
|
|
191
|
+
Bu geliştirme döngüsü bazı zorluklar barındırır:
|
|
192
|
+
|
|
193
|
+
- Bir JSON dosyasındaki her değişiklik, import'un çözümlenmesi veya tiplerin güncellenmesi için önceden yeniden derleme gerektirir.
|
|
194
|
+
- Üretilen `paraglide/` klasörü ya git'e dahil edilmeli (bu da metin değiştiren her PR'da çakışmalara yol açar) ya da yok sayılmalıdır (bu da her tip denetimi, test ve CI adımı öncesinde zorunlu bir üretim adımı anlamına gelir).
|
|
195
|
+
- Her metin bir fonksiyon çağrısına dönüşür. Sabit değerler, düz bir dizenin yeterli olacağı yerler de dahil olmak üzere her yerde `m.key()` biçimini alır.
|
|
196
|
+
|
|
197
|
+
## Tree Shaking: Kendi Paketlerinizi İnceleyin
|
|
198
|
+
|
|
199
|
+
Paraglide'ın en büyük iddiası, her iletinin bağımsız bir dışa aktarma olması sebebiyle kullanılmayan mesajların tree shaking ile elenmesidir. Svelte + Vite ortamında bu vaat başarıyla çalışır.
|
|
200
|
+
|
|
201
|
+
Ancak diğer ortamlarda durum böyle olmadı. [Next.js](https://intlayer.org/tr/doc/benchmark/nextjs) testlerimizde Paraglide sayfaları temel uygulamadan 14 KB daha ağır çıkarken, `next-intlayer` yalnızca 0.3 KB eklemiştir. TanStack Start üzerindeki önceki çalışmalar da diğer sayfaların mesajlarının mevcut rota paketine sızdığını göstermiştir.
|
|
202
|
+
|
|
203
|
+
Tree shaking başarısı paketleyicinize (Turbopack, Rolldown, Rollup), mesajların içe aktarılma biçimine (`import { m }` vs `import * as m`) ve yan etki analizine sıkı sıkıya bağlıdır. Paraglide'ı boyutu nedeniyle tercih ediyorsanız, paket analiz aracınızı açıp uygulamanızda durumun gerçekten böyle olup olmadığını test edin.
|
|
204
|
+
|
|
205
|
+
## Dinamik Yükleme Eksikliği
|
|
206
|
+
|
|
207
|
+
Yapısal olarak en büyük sınır budur. Paraglide'ın dilleri teker teker yüklemek için bir yöntemi yoktur: her mesaj fonksiyonu tüm dillerin uygulamasını statik olarak içe aktarır, bu nedenle tüm diller istemci paketinize dahil olur.
|
|
208
|
+
|
|
209
|
+
2 dilli bir projede çeviri verilerinizin yarısı boşa harcanır ve bu durum yukarıda ölçülen ~%50 dil sızıntısıyla örtüşür. 10 dilde bu oran %90'a, 30 dilde ise %97'ye ulaşır.
|
|
210
|
+
|
|
211
|
+
Dinamik yüklemeye geçmek de bu sorunu çözmez: mesaj başına tek bir fonksiyon varken her fonksiyonu tembel (lazy) yüklemek binlerce ağ isteği anlamına gelir.
|
|
212
|
+
|
|
213
|
+
Intlayer, genel olarak veya sözlük bazında seçim yapmanıza olanak tanır:
|
|
214
|
+
|
|
215
|
+
```ts fileName="intlayer.config.ts"
|
|
216
|
+
import { Locales, type IntlayerConfig } from "intlayer";
|
|
217
|
+
|
|
218
|
+
const config: IntlayerConfig = {
|
|
219
|
+
internationalization: {
|
|
220
|
+
locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
|
|
221
|
+
defaultLocale: Locales.ENGLISH,
|
|
222
|
+
},
|
|
223
|
+
dictionary: {
|
|
224
|
+
importMode: "dynamic", // 'static' | 'dynamic' | 'fetch'
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
export default config;
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
| `importMode` | İstemciye gönderilen içerik | Paraglide ile kıyaslandığında |
|
|
232
|
+
| ------------ | ------------------------------------------------------ | -------------------------------- |
|
|
233
|
+
| `static` | Sayfanın kullandığı sözlüklerin tüm dilleri | Teorik olarak aynı içerik boyutu |
|
|
234
|
+
| `dynamic` | Yalnızca mevcut dil, sözlük başına dinamik yüklenir | N dilde **N kat daha hafif** |
|
|
235
|
+
| `fetch` | Yalnızca mevcut dil, Live Sync API üzerinden getirilir | N dilde **N kat daha hafif** |
|
|
236
|
+
|
|
237
|
+
[Derleme optimizasyonu](https://intlayer.org/tr/doc/concept/bundle-optimization) ve `importMode: 'static'` moduyla Intlayer, teoride Paraglide ile tamamen aynı içeriği yükler. `'dynamic'` veya `'fetch'` kullanıldığında ise yalnızca mevcut dilin ihtiyaç duyduğu veriyi yükler: N dile sahip bir uygulama için çeviri yükü Paraglide'a göre N kat daha küçüktür.
|
|
238
|
+
|
|
239
|
+
## Paraglide Hangi Durumlarda Hala Mantıklıdır?
|
|
240
|
+
|
|
241
|
+
<AccordionGroup>
|
|
242
|
+
<Accordion header="Az sayıda dile sahip Svelte + Vite projeleri">
|
|
243
|
+
|
|
244
|
+
Eğer altyapınız Svelte ve Vite üzerine kuruluysa ve yalnızca iki veya üç dili destekliyorsanız, tree shaking vadedildiği gibi çalışır ve ek dil maliyeti düşük kalır.
|
|
245
|
+
|
|
246
|
+
</Accordion>
|
|
247
|
+
<Accordion header="Mevcut inlang iş akışları">
|
|
248
|
+
|
|
249
|
+
Ekibiniz halihazırda inlang ekosistemini (Fink, Sherlock, mesaj biçimi eklentileri) kullanıyorsa, Paraglide bu yapıya yerel olarak entegre olur.
|
|
250
|
+
|
|
251
|
+
</Accordion>
|
|
252
|
+
</AccordionGroup>
|
|
253
|
+
|
|
254
|
+
## Kendi Uygulamanızda Deneyin
|
|
255
|
+
|
|
256
|
+
Canlı uygulamanızın transfer boyutunu ve dil sızıntılarını ücretsiz [i18n SEO Scanner](https://intlayer.org/i18n-seo-scanner) ile test edin:
|
|
257
|
+
|
|
258
|
+
<ClickToOpenIframe src="https://intlayer.org/i18n-seo-scanner" width="100%" height="600px" style="border:none;"/>
|
|
259
|
+
|
|
260
|
+
Intlayer kurulumu için:
|
|
261
|
+
|
|
262
|
+
```bash packageManager="npm"
|
|
263
|
+
npx intlayer init --interactive
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
```bash packageManager="pnpm"
|
|
267
|
+
pnpm dlx intlayer init --interactive
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
```bash packageManager="yarn"
|
|
271
|
+
yarn dlx intlayer init --interactive
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
```bash packageManager="bun"
|
|
275
|
+
bunx intlayer init --interactive
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## Ek Kaynaklar
|
|
279
|
+
|
|
280
|
+
- [TanStack Start i18n Kıyaslaması](https://intlayer.org/tr/doc/benchmark/tanstack)
|
|
281
|
+
- [Next.js i18n Kıyaslaması](https://intlayer.org/tr/doc/benchmark/nextjs)
|
|
282
|
+
- [Paket Optimizasyonu ve `importMode`](https://intlayer.org/tr/doc/concept/bundle-optimization)
|
|
283
|
+
- [React İçin Doğru i18n Kütüphanesi Nasıl Seçilir?](https://intlayer.org/tr/blog/how-to-pick-react-i18n-library)
|
|
284
|
+
- [Derleyici Tabanlı ve Bildirimsel Uluslararasılaştırma Kıyaslaması](https://intlayer.org/tr/blog/compiler-vs-declarative-i18n)
|
|
@@ -0,0 +1,284 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2026-09-23
|
|
3
|
+
updatedAt: 2026-09-23
|
|
4
|
+
title: Чи легший Intlayer за Paraglide?
|
|
5
|
+
description: Paraglide виглядає практично безкоштовним у бенчмарках i18n, оскільки його код генерується безпосередньо у ваш репозиторій. Розбираємося, куди насправді дівається ця вага, чому зчитування локалі для кожного вузла знижує продуктивність і як динамічне завантаження Intlayer передає одну локаль замість усіх.
|
|
6
|
+
keywords:
|
|
7
|
+
- Paraglide
|
|
8
|
+
- Intlayer
|
|
9
|
+
- Інтернаціоналізація
|
|
10
|
+
- i18n
|
|
11
|
+
- Bundle size
|
|
12
|
+
- Tree shaking
|
|
13
|
+
- Benchmark
|
|
14
|
+
- Blog
|
|
15
|
+
slugs:
|
|
16
|
+
- blog
|
|
17
|
+
- is-intlayer-lighter-than-paraglide
|
|
18
|
+
author: aymericzip
|
|
19
|
+
---
|
|
20
|
+
|
|
21
|
+
# Чи легший Intlayer за Paraglide?
|
|
22
|
+
|
|
23
|
+
Так.
|
|
24
|
+
|
|
25
|
+
`Paraglide` має чудову репутацію найлегшого рішення для i18n, і на перший погляд [бенчмарк](https://intlayer.org/uk/doc/benchmark/tanstack) це підтверджує: розмір його бібліотеки близький до нуля. Проте нульовий розмір бібліотеки зовсім не означає нуль переданих байтів. Це лише вказує на те, що байти знаходяться там, куди ця метрика не заглядає.
|
|
26
|
+
|
|
27
|
+
<TOC/>
|
|
28
|
+
|
|
29
|
+
## Ключові висновки
|
|
30
|
+
|
|
31
|
+
**Розмір бібліотеки прихований, а не усунутий:**
|
|
32
|
+
|
|
33
|
+
Paraglide генерує свій runtime та функції повідомлень безпосередньо у вашу кодову базу. Цей код відправляється в браузер, але враховується як _ваш_ код, а не код бібліотеки.
|
|
34
|
+
|
|
35
|
+
**Відсутність провайдера - це не безкоштовний виграш:**
|
|
36
|
+
|
|
37
|
+
Кожен виклик `m.my_key()` самостійно визначає локаль, зчитуючи cookie або сховище для кожного відрендереного вузла, замість того щоб прочитати її один раз із контексту.
|
|
38
|
+
|
|
39
|
+
**Немає динамічного завантаження:**
|
|
40
|
+
|
|
41
|
+
Paraglide імпортує всі локалі повідомлення в клієнтський бандл. Intlayer із параметром `importMode: 'dynamic'` або `'fetch'` завантажує лише ту локаль, яка зараз відображається.
|
|
42
|
+
|
|
43
|
+
**Tree shaking не гарантується:**
|
|
44
|
+
|
|
45
|
+
У деяких наших тестах заявлений Paraglide tree shaking не спрацював. Обов'язково перевірте власний бандл.
|
|
46
|
+
|
|
47
|
+
## Куди дівається вага Paraglide?
|
|
48
|
+
|
|
49
|
+
У звітах бенчмарків метрика «розмір бібліотеки» вимірює провайдер і хуки кожної бібліотеки i18n у порожньому компоненті, до додавання будь-якого контенту.
|
|
50
|
+
|
|
51
|
+
| Бібліотека (TanStack Start) | Розмір ліби (gz) | Розмір ліби (min) |
|
|
52
|
+
| ----------------------------- | ---------------- | ----------------- |
|
|
53
|
+
| `@inlang/paraglide-js@2.15.1` | 1.8 KB | 4.5 KB |
|
|
54
|
+
| `react-intlayer@9.5.1` | 5.0 KB | 15.2 KB |
|
|
55
|
+
|
|
56
|
+
Якщо розглядати ці цифри окремо, Paraglide виграє. Але Paraglide - це компілятор: він читає ваші файли `messages/*.json` і записує папку `paraglide/` у ваш репозиторій. Вона містить `runtime.js` (визначення локалі, стратегії cookie та сховища, локалізація URL) і по одній функції JavaScript на кожне повідомлення.
|
|
57
|
+
|
|
58
|
+
```bash
|
|
59
|
+
src/paraglide/
|
|
60
|
+
├── runtime.js # визначення локалі, стратегії, допоміжні інструменти URL
|
|
61
|
+
├── server.js
|
|
62
|
+
├── messages.js # реекспорт усіх повідомлень
|
|
63
|
+
└── messages/
|
|
64
|
+
├── _index.js
|
|
65
|
+
├── en.js
|
|
66
|
+
└── fr.js
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
Оскільки цей код розташований у вашій папці `src/` і імпортується за відносним шляхом, бандлер зараховує його до вашого додатку, а не до пакетів у `node_modules`. Колонка розміру бібліотеки не показує майже нічого, тоді як та сама логіка все одно передається в бандлі вашої сторінки.
|
|
70
|
+
|
|
71
|
+
Генерація коду сама по собі не є поганою ідеєю: згенерований runtime містить лише ту логіку, яка потрібна вашій конфігурації (стратегія префіксів, cookie проти local storage тощо). Intlayer досягає того ж результату інакше: впроваджуючи змінні середовища під час збірки, завдяки чому бандлер відкидає гілки, які ваша конфігурація не використовує. Обидва підходи виявляються в 3–10 разів легшими за `i18next` або `next-intl`.
|
|
72
|
+
|
|
73
|
+
Тому справедливе порівняння полягає не в розмірі бібліотеки. Це **обсяг JavaScript, який фактично передається на сторінку**.
|
|
74
|
+
|
|
75
|
+
## Виміряна вага сторінки
|
|
76
|
+
|
|
77
|
+
Додаток TanStack Start, 10 сторінок, виміри на маршрутах `en` та `fr`, стиснення gzip:
|
|
78
|
+
|
|
79
|
+
| Конфігурація | Сер. JS стор (gz) | Понад базу | Витік локалі | Витік інших сторінок |
|
|
80
|
+
| ---------------------------------- | ----------------- | ----------- | ------------ | -------------------- |
|
|
81
|
+
| База (без i18n) | 111.0 KB | - | 0.0% | 0.0% |
|
|
82
|
+
| `paraglide` (будь-яка стратегія) | 125.1 KB | +14.1 KB | 49.7% | 0.0% |
|
|
83
|
+
| `intlayer` (`importMode: static`) | 125.8 KB | +14.8 KB | 50.0% | 0.0% |
|
|
84
|
+
| `intlayer` (`importMode: dynamic`) | **118.6 KB** | **+7.6 KB** | **0.0%** | **0.0%** |
|
|
85
|
+
|
|
86
|
+
Next.js 16 App Router, той самий додаток:
|
|
87
|
+
|
|
88
|
+
| Конфігурація | Сер. JS стор (gz) | Понад базу |
|
|
89
|
+
| ---------------- | ----------------- | ----------- |
|
|
90
|
+
| База (без i18n) | 141.0 KB | - |
|
|
91
|
+
| `paraglide-next` | 155.3 KB | +14.3 KB |
|
|
92
|
+
| `next-intlayer` | **141.3 KB** | **+0.3 KB** |
|
|
93
|
+
|
|
94
|
+
<I18nBenchmark framework="tanstack" vertical/>
|
|
95
|
+
|
|
96
|
+
> Повні дані наведено у [звіті бенчмарку TanStack Start](https://intlayer.org/uk/doc/benchmark/tanstack) та [звіті бенчмарку Next.js](https://intlayer.org/uk/doc/benchmark/nextjs). Кожен бандл можна детально оглянути в [репозиторії бенчмарку](https://github.com/intlayer-org/benchmark-i18n).
|
|
97
|
+
|
|
98
|
+
Два висновки стають очевидними:
|
|
99
|
+
|
|
100
|
+
- У режимі `static` Intlayer передає практично той самий обсяг контенту, що й Paraglide (125.8 KB проти 125.1 KB). Це природно: обидва містять усі локалі повідомлень, які використовує сторінка.
|
|
101
|
+
- Paraglide залишається на рівні 125.1 KB за будь-якої стратегії, оскільки не має динамічного режиму. Кожен рядок у таблиці вище відповідає статичному варіанту.
|
|
102
|
+
|
|
103
|
+
## Відсутність Provider: ідея, яка здається гарною лише зовні
|
|
104
|
+
|
|
105
|
+
Paraglide не потребує провайдера. Ви просто імпортуєте повідомлення та викликаєте його:
|
|
106
|
+
|
|
107
|
+
```tsx fileName="Hero.tsx"
|
|
108
|
+
import { m } from "../paraglide/messages.js";
|
|
109
|
+
|
|
110
|
+
export const Hero = () => (
|
|
111
|
+
<section>
|
|
112
|
+
<h1>{m.hero_title()}</h1>
|
|
113
|
+
<p>{m.hero_description()}</p>
|
|
114
|
+
<button>{m.hero_cta()}</button>
|
|
115
|
+
</section>
|
|
116
|
+
);
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
Жодного контексту, жодних обгорток, жодних хуків. Здається простішим. Але інформацію про локаль усе одно потрібно звідкись отримувати. Кожна згенерована функція повідомлення виглядає приблизно так (спрощено):
|
|
120
|
+
|
|
121
|
+
```js fileName="paraglide/messages/_index.js"
|
|
122
|
+
export const hero_title = (inputs = {}, options = {}) => {
|
|
123
|
+
const locale = options.locale ?? getLocale(); // обчислюється під час кожного виклику
|
|
124
|
+
|
|
125
|
+
if (locale === "en") return en.hero_title(inputs);
|
|
126
|
+
if (locale === "fr") return fr.hero_title(inputs);
|
|
127
|
+
// ...по одній гілці на кожну локаль
|
|
128
|
+
};
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
А `getLocale()` проходить по всіх налаштованих стратегіях (cookie, local storage, URL, базова локаль), щоб знайти поточну мову. Отже, кожен відрендерений текстовий вузол (`<>{m.my_key()}</>`) виконує власне визначення локалі, включно зі зчитуванням `document.cookie` в браузері. Сторінка з 200 перекладеними рядками визначає локаль 200 разів за одне рендерення, і повторює це під час кожного повторного рендерення.
|
|
132
|
+
|
|
133
|
+
Бібліотека з провайдером зчитує локаль **один раз**, зберігає її в контексті (або сигналі, або сторі), і кожен вузол читає значення, яке вже присутнє в пам'яті. Провайдер коштує всього кілька сотень байтів. Відмова від нього навантажує процесор під час кожного рендерення, що чітко видно в бенчмарках: час завантаження сторінки та перемикання мови в Paraglide стабільно поступаються Intlayer на TanStack Start (22.1 мс проти 14.6 мс при завантаженні сторінки, 4.3 мс проти 3.2 мс у реактивності E2E).
|
|
134
|
+
|
|
135
|
+
## Досвід розробника (DX)
|
|
136
|
+
|
|
137
|
+
Джерелом правди для Paraglide є JSON, але розробник ніколи не імпортує файли JSON безпосередньо. Ви імпортуєте згенерований файл `.js`:
|
|
138
|
+
|
|
139
|
+
<Tabs defaultTab="intlayer" group="techno">
|
|
140
|
+
<Tab label="Paraglide" value="paraglide">
|
|
141
|
+
|
|
142
|
+
```json fileName="messages/en.json"
|
|
143
|
+
{
|
|
144
|
+
"hero_title": "Ship your app in every language"
|
|
145
|
+
}
|
|
146
|
+
```
|
|
147
|
+
|
|
148
|
+
```json fileName="messages/uk.json"
|
|
149
|
+
{
|
|
150
|
+
"hero_title": "Публікуйте свій застосунок усіма мовами"
|
|
151
|
+
}
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
```tsx fileName="Hero.tsx"
|
|
155
|
+
// Існує лише після перегенерації компілятором із файлу JSON
|
|
156
|
+
import { m } from "../paraglide/messages.js";
|
|
157
|
+
|
|
158
|
+
export const Hero = () => <h1>{m.hero_title()}</h1>;
|
|
159
|
+
```
|
|
160
|
+
|
|
161
|
+
</Tab>
|
|
162
|
+
<Tab label="Intlayer" value="intlayer">
|
|
163
|
+
|
|
164
|
+
```ts fileName="Hero.content.ts"
|
|
165
|
+
import { t, type Dictionary } from "intlayer";
|
|
166
|
+
|
|
167
|
+
export default {
|
|
168
|
+
key: "hero",
|
|
169
|
+
content: {
|
|
170
|
+
title: t({
|
|
171
|
+
uk: "Публікуйте свій застосунок усіма мовами",
|
|
172
|
+
en: "Ship your app in every language",
|
|
173
|
+
}),
|
|
174
|
+
},
|
|
175
|
+
} satisfies Dictionary;
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
```tsx fileName="Hero.tsx"
|
|
179
|
+
import { useIntlayer } from "react-intlayer";
|
|
180
|
+
|
|
181
|
+
export const Hero = () => {
|
|
182
|
+
const { title } = useIntlayer("hero");
|
|
183
|
+
|
|
184
|
+
return <h1>{title}</h1>;
|
|
185
|
+
};
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
</Tab>
|
|
189
|
+
</Tabs>
|
|
190
|
+
|
|
191
|
+
Такий робочий процес створює труднощі:
|
|
192
|
+
|
|
193
|
+
- Будь-яка зміна у файлі JSON вимагає перегенерації, перш ніж імпорт спрацює або оновляться типи.
|
|
194
|
+
- Згенеровану папку `paraglide/` доводиться або фіксувати в git (що призводить до конфліктів злиття у згенерованих файлах під час кожного PR зі зміною тексту), або ігнорувати (що вимагає кроку генерації перед кожною перевіркою типів, тестом і завданням CI).
|
|
195
|
+
- Кожен рядок стає викликом функції. Константи перетворюються на `m.key()` всюди, навіть там, де цілком вистачило б звичайного статичного значення.
|
|
196
|
+
|
|
197
|
+
## Tree Shaking: перевірте свій бандл
|
|
198
|
+
|
|
199
|
+
Головна обіцянка Paraglide полягає в тому, що невикористані повідомлення видаляються за допомогою tree shaking, оскільки кожне повідомлення є окремим експортом. У бенчмарку Svelte + Vite це працює саме так, як заявлено.
|
|
200
|
+
|
|
201
|
+
В інших середовищах цього не сталося. У наших тестах на [Next.js](https://intlayer.org/uk/doc/benchmark/nextjs) сторінки Paraglide важать на 14 KB більше за базовий додаток, тоді як `next-intlayer` додає лише 0.3 KB. Попередні виміри на TanStack Start також показали, що повідомлення з інших сторінок потрапляли в бандл поточного маршруту.
|
|
202
|
+
|
|
203
|
+
Tree shaking залежить від вашого бандлера (Turbopack, Rolldown, Rollup), способу імпорту повідомлень (`import { m }` проти `import * as m`) та аналізу побічних ефектів. Якщо ви обираєте Paraglide через компактність, відкрийте візуалізатор бандла та перевірте, чи працює це у вашому додатку.
|
|
204
|
+
|
|
205
|
+
## Відсутність динамічного завантаження
|
|
206
|
+
|
|
207
|
+
Це фундаментальне структурне обмеження. У Paraglide немає можливості завантажувати по одній локалі за раз: кожна функція повідомлення статично імпортує реалізацію кожної мови, тому абсолютно всі мови потрапляють у ваш клієнтський бандл.
|
|
208
|
+
|
|
209
|
+
При 2 мовах половина переданих даних перекладів витрачається марно, що відповідає витоку локалі близько ~50%, виміряному вище. При 10 мовах марно витрачається 90%. При 30 мовах - 97%.
|
|
210
|
+
|
|
211
|
+
Перехід на динамічне завантаження також не вирішив би проблеми: коли кожне повідомлення є окремою функцією, ліниве завантаження кожної з них створило б тисячі мережевих запитів.
|
|
212
|
+
|
|
213
|
+
Intlayer дозволяє обирати стратегію глобально або для кожного словника окремо:
|
|
214
|
+
|
|
215
|
+
```ts fileName="intlayer.config.ts"
|
|
216
|
+
import { Locales, type IntlayerConfig } from "intlayer";
|
|
217
|
+
|
|
218
|
+
const config: IntlayerConfig = {
|
|
219
|
+
internationalization: {
|
|
220
|
+
locales: [Locales.ENGLISH, Locales.FRENCH, Locales.SPANISH],
|
|
221
|
+
defaultLocale: Locales.ENGLISH,
|
|
222
|
+
},
|
|
223
|
+
dictionary: {
|
|
224
|
+
importMode: "dynamic", // 'static' | 'dynamic' | 'fetch'
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
export default config;
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
| `importMode` | Що відправляється клієнту | vs. Paraglide |
|
|
232
|
+
| ------------ | ------------------------------------------------------------- | --------------------------------- |
|
|
233
|
+
| `static` | Усі локалі словників, які використовує сторінка | Теоретично той самий обсяг |
|
|
234
|
+
| `dynamic` | Лише поточна локаль, ліниве завантаження для кожного словника | **У N разів менше** при N локалях |
|
|
235
|
+
| `fetch` | Лише поточна локаль, отримана через Live Sync API | **У N разів менше** при N локалях |
|
|
236
|
+
|
|
237
|
+
Завдяки [трансформації під час збірки](https://intlayer.org/uk/doc/concept/bundle-optimization) та режиму `importMode: 'static'`, Intlayer теоретично завантажує рівно той самий обсяг даних, що й Paraglide. А в режимах `'dynamic'` або `'fetch'` він завантажує лише те, що потрібно поточній мові: для додатку на N мовах обсяг переданих перекладів у N разів менший, ніж у Paraglide.
|
|
238
|
+
|
|
239
|
+
## Де Paraglide усе ще доречний
|
|
240
|
+
|
|
241
|
+
<AccordionGroup>
|
|
242
|
+
<Accordion header="Svelte + Vite з невеликою кількістю мов">
|
|
243
|
+
|
|
244
|
+
Якщо ваш стек побудований на Svelte з Vite і ви підтримуєте дві або три мови, tree shaking працює за планом, а накладні витрати на додаткові локалі залишаються незначними.
|
|
245
|
+
|
|
246
|
+
</Accordion>
|
|
247
|
+
<Accordion header="Наявний робочий процес із inlang">
|
|
248
|
+
|
|
249
|
+
Якщо ваша команда вже використовує екосистему inlang (Fink, Sherlock, плагіни форматів повідомлень), Paraglide нативно інтегрується в цей процес.
|
|
250
|
+
|
|
251
|
+
</Accordion>
|
|
252
|
+
</AccordionGroup>
|
|
253
|
+
|
|
254
|
+
## Спробуйте на власному додатку
|
|
255
|
+
|
|
256
|
+
Перевірте обсяг передачі даних та витоки локалей вашого робочого додатку за допомогою безкоштовного інструменту [i18n SEO Scanner](https://intlayer.org/i18n-seo-scanner):
|
|
257
|
+
|
|
258
|
+
<ClickToOpenIframe src="https://intlayer.org/i18n-seo-scanner" width="100%" height="600px" style="border:none;"/>
|
|
259
|
+
|
|
260
|
+
Встановлення Intlayer:
|
|
261
|
+
|
|
262
|
+
```bash packageManager="npm"
|
|
263
|
+
npx intlayer init --interactive
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
```bash packageManager="pnpm"
|
|
267
|
+
pnpm dlx intlayer init --interactive
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
```bash packageManager="yarn"
|
|
271
|
+
yarn dlx intlayer init --interactive
|
|
272
|
+
```
|
|
273
|
+
|
|
274
|
+
```bash packageManager="bun"
|
|
275
|
+
bunx intlayer init --interactive
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## Додаткові матеріали
|
|
279
|
+
|
|
280
|
+
- [Бенчмарк i18n TanStack Start](https://intlayer.org/uk/doc/benchmark/tanstack)
|
|
281
|
+
- [Бенчмарк i18n Next.js](https://intlayer.org/uk/doc/benchmark/nextjs)
|
|
282
|
+
- [Оптимізація бандла та `importMode`](https://intlayer.org/uk/doc/concept/bundle-optimization)
|
|
283
|
+
- [Як вибрати бібліотеку i18n для React](https://intlayer.org/uk/blog/how-to-pick-react-i18n-library)
|
|
284
|
+
- [Аргументи на користь компіляторного підходу до інтернаціоналізації](https://intlayer.org/uk/blog/compiler-vs-declarative-i18n)
|