@intlayer/docs 8.9.4 → 8.9.6-canary.0
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/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/plugins/sync-po.md +0 -21
- 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/plugins/sync-po.md +0 -22
- 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/plugins/sync-po.md +0 -21
- 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/plugins/sync-po.md +0 -21
- 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/plugins/sync-po.md +0 -21
- 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/plugins/sync-po.md +0 -21
- 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/plugins/sync-po.md +0 -21
- 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/plugins/sync-po.md +0 -21
- 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/plugins/sync-po.md +0 -21
- 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/plugins/sync-po.md +0 -21
- 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/plugins/sync-po.md +0 -21
- 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/plugins/sync-po.md +0 -21
- 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/plugins/sync-po.md +0 -21
- 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/plugins/sync-po.md +0 -21
- 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/plugins/sync-po.md +0 -21
- 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/plugins/sync-po.md +0 -21
- 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/plugins/sync-po.md +0 -21
- 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/plugins/sync-po.md +0 -21
- 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
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2026-04-20
|
|
3
|
+
updatedAt: 2026-04-21
|
|
4
|
+
title: Najlepsze rozwiązanie i18n dla Svelte w 2026 r. — raport z benchmarku
|
|
5
|
+
description: Porównaj biblioteki internacjonalizacji (i18n) dla Svelte, takie jak svelte-i18n, Paraglide i Intlayer. Szczegółowy raport wydajności dotyczący rozmiaru paczki, wycieków i reaktywności.
|
|
6
|
+
keywords:
|
|
7
|
+
- benchmark
|
|
8
|
+
- i18n
|
|
9
|
+
- intl
|
|
10
|
+
- svelte
|
|
11
|
+
- wydajność
|
|
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: "Inicjalizacja benchmarku"
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
# Biblioteki i18n dla Svelte — raport z benchmarku 2026
|
|
26
|
+
|
|
27
|
+
Ta strona zawiera raport z benchmarku rozwiązań i18n dla Svelte.
|
|
28
|
+
|
|
29
|
+
## Spis treści
|
|
30
|
+
|
|
31
|
+
<Toc/>
|
|
32
|
+
|
|
33
|
+
## Interaktywny benchmark
|
|
34
|
+
|
|
35
|
+
<I18nBenchmark framework="vite-svelte" 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-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
|
+
Pełne repozytorium benchmarku znajdziesz [tutaj](https://github.com/intlayer-org/benchmark-i18n/tree/main).
|
|
49
|
+
|
|
50
|
+
## Wstęp
|
|
51
|
+
|
|
52
|
+
Rozwiązania do internacjonalizacji należą do najcięższych zależności w aplikacji Svelte. Głównym ryzykiem jest wysyłanie niepotrzebnych treści: tłumaczeń dla innych stron i innych lokalizacji w paczce (bundle) pojedynczej trasy.
|
|
53
|
+
|
|
54
|
+
W miarę rozwoju aplikacji problem ten może szybko zwiększyć ilość JavaScriptu wysyłanego do klienta i spowolnić nawigację.
|
|
55
|
+
|
|
56
|
+
W praktyce, w przypadku najmniej zoptymalizowanych implementacji, strona zinternacjonalizowana może okazać się kilkukrotnie cięższa niż wersja bez i18n.
|
|
57
|
+
|
|
58
|
+
Innym skutkiem jest wpływ na doświadczenie programisty (DX): sposób deklarowania treści, typy, organizacja przestrzeni nazw (namespaces), dynamiczne ładowanie i reaktywność przy zmianie lokalizacji.
|
|
59
|
+
|
|
60
|
+
## TL;DR
|
|
61
|
+
|
|
62
|
+
- **Intlayer**: Najbardziej wydajny wybór (v8.7.12) z najmniejszym śladem (footprint).
|
|
63
|
+
- **Paraglide**: Mocny kandydat pod kątem tree-shakingu, ale oferuje bardziej złożone doświadczenie programisty i narzut reaktywności.
|
|
64
|
+
- **svelte-i18n**: Kompleksowy i standardowy dla Svelte, ale wiąże się ze znacznie większą wagą paczki (~7x Intlayer).
|
|
65
|
+
|
|
66
|
+
## Przetestuj swoją aplikację
|
|
67
|
+
|
|
68
|
+
Aby szybko wykryć problemy z wyciekami i18n, przygotowałem darmowy skaner dostępny [tutaj](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
|
+
## Problem
|
|
73
|
+
|
|
74
|
+
Dwa dźwignie są kluczowe dla ograniczenia kosztów aplikacji wielojęzycznej:
|
|
75
|
+
|
|
76
|
+
- Dzielenie treści według stron / przestrzeni nazw, aby nie ładować całych słowników, gdy nie są potrzebne.
|
|
77
|
+
- Dynamiczne ładowanie odpowiedniej lokalizacji tylko wtedy, gdy jest potrzebna.
|
|
78
|
+
|
|
79
|
+
Zrozumienie technicznych ograniczeń tych podejść:
|
|
80
|
+
|
|
81
|
+
**Dynamiczne ładowanie**
|
|
82
|
+
|
|
83
|
+
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.
|
|
84
|
+
|
|
85
|
+
Dzięki dynamicznemu ładowaniu akceptujesz kompromis: mniej początkowego JS, ale czasami dodatkowe zapytanie przy zmianie języka.
|
|
86
|
+
|
|
87
|
+
**Dzielenie treści (Splitting)**
|
|
88
|
+
|
|
89
|
+
Składnie zbudowane wokół `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 tree-shaking, chyba że biblioteka oferuje rzeczywistą strategię dzielenia na poszczególne strony.
|
|
90
|
+
|
|
91
|
+
## Metodologia badań
|
|
92
|
+
|
|
93
|
+
W tym benchmarku porównaliśmy następujące biblioteki:
|
|
94
|
+
|
|
95
|
+
- `Base App` (Brak biblioteki i18n)
|
|
96
|
+
- `svelte-intlayer` (v8.7.12)
|
|
97
|
+
- `svelte-i18n` (v4.0.1)
|
|
98
|
+
- `@inlang/paraglide-js` (v2.17.0)
|
|
99
|
+
|
|
100
|
+
Framework to `Svelte` z aplikacją wielojęzyczną składającą się z **10 stron** i **10 języków**.
|
|
101
|
+
|
|
102
|
+
Porównaliśmy **cztery strategie ładowania**:
|
|
103
|
+
|
|
104
|
+
| Strategia | Brak przestrzeni nazw (globalna) | Z przestrzeniami nazw (scoped) |
|
|
105
|
+
| :----------------------- | :------------------------------------------------ | :------------------------------------------------------------------------------- |
|
|
106
|
+
| **Ładowanie statyczne** | **Static**: Wszystko w pamięci przy starcie. | **Scoped static**: Podział na przestrzenie nazw; wszystko ładowane przy starcie. |
|
|
107
|
+
| **Ładowanie dynamiczne** | **Dynamic**: Ładowanie na żądanie na lokalizację. | **Scoped dynamic**: Szczegółowe ładowanie na przestrzeń nazw i lokalizację. |
|
|
108
|
+
|
|
109
|
+
## Podsumowanie strategii
|
|
110
|
+
|
|
111
|
+
- **Static**: Proste; brak opóźnień sieciowych po początkowym załadowaniu. Minus: duży rozmiar paczki.
|
|
112
|
+
- **Dynamic**: Zmniejsza początkową wagę (lazy-loading). Idealne, gdy masz wiele lokalizacji.
|
|
113
|
+
- **Scoped static**: Utrzymuje porządek w kodzie (logiczna separacja) bez skomplikowanych dodatkowych zapytań sieciowych.
|
|
114
|
+
- **Scoped dynamic**: Najlepsze podejście dla _code splittingu_ i wydajności. Minimalizuje zużycie pamięci, ładując tylko to, czego potrzebuje bieżący widok i aktywna lokalizacja.
|
|
115
|
+
|
|
116
|
+
## Wyniki szczegółowe
|
|
117
|
+
|
|
118
|
+
### 1 — Rozwiązania, których należy unikać
|
|
119
|
+
|
|
120
|
+
> W ekosystemie Svelte nie ma jednoznacznego rozwiązania, którego należy unikać.
|
|
121
|
+
|
|
122
|
+
### 2 — Rozwiązania akceptowalne
|
|
123
|
+
|
|
124
|
+
**(Paraglide)** (`@inlang/paraglide-js@2.17.0`):
|
|
125
|
+
|
|
126
|
+
`Paraglide` oferuje innowacyjne, przemyślane podejście. W kontekście aplikacji Vite + Svelte reklamowany przez nich tree-shaking działał zgodnie z oczekiwaniami, co jest świetne.
|
|
127
|
+
Ale w przypadku React + TanStack Start tree-shaking nie działał zgodnie z oczekiwaniami, podobnie w Next.js. To powiedziawszy, użycie Paraglide w projekcie Svelte i TanStack Start byłoby warte ponownego sprawdzenia.
|
|
128
|
+
Workflow i DX są również bardziej złożone niż w przypadku innych opcji.
|
|
129
|
+
Osobiście nie jestem fanem konieczności regeneracji plików JS przed każdym pushem, co stwarza ciągłe ryzyko konfliktów przy mergowaniu poprzez PR-y. Narzędzie wydaje się również bardziej skoncentrowane na Vite niż na Next.js.
|
|
130
|
+
Wreszcie, w porównaniu z innymi rozwiązaniami, Paraglide nie używa store'a (np. Svelte store) do pobierania aktualnej lokalizacji w celu renderowania treści. Dla każdego sparsowanego węzła będzie żądać lokalizacji z localStorage / cookie itp. Prowadzi to do wykonywania niepotrzebnej logiki, która wpływa na reaktywność komponentu.
|
|
131
|
+
|
|
132
|
+
> Uwaga na temat paraglide: rozwiązanie to wstrzykuje kod do Twojej bazy kodu w celu importu; w rezultacie metryka „lib size” w raporcie z benchmarku wynosi prawie 0. Generowanie kodu jest dobrą rzeczą, ponieważ użyta funkcja będzie zawierać tylko niezbędną logikę (prefiks wszędzie vs brak prefiksu, cookie vs storage itp.). Dla porównania, Intlayer wykonuje to filtrowanie poprzez wstrzykiwanie zmiennych środowiskowych podczas budowania, aby wymusić na bundlerze tree-shaking treści w zależności od logiki. Dzięki temu paraglide i intlayer okazują się być od 6 do 10 razy lżejszymi rozwiązaniami niż i18next czy next-intl.
|
|
133
|
+
|
|
134
|
+
**(svelte-i18n)** (`svelte-i18n@3.4.0`):
|
|
135
|
+
|
|
136
|
+
To rozwiązanie odpowiada na wszystkie potrzeby i18n w projekcie Svelte. Ale podobnie jak w przypadku i18next lub innych głównych rozwiązań i18n, jest ono nieco ciężkie (~15.9kb, co stanowi około 7x `svelte-intlayer`).
|
|
137
|
+
|
|
138
|
+
### 3 — Rekomendacje
|
|
139
|
+
|
|
140
|
+
**(Intlayer)** (`svelte-intlayer@8.7.12`):
|
|
141
|
+
|
|
142
|
+
Nie będę osobiście oceniać `svelte-intlayer` ze względu na obiektywizm, ponieważ jest to moje własne rozwiązanie.
|
|
143
|
+
|
|
144
|
+
### Notatka osobista
|
|
145
|
+
|
|
146
|
+
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 przetłumaczonych.
|
|
147
|
+
|
|
148
|
+
W aplikacjach Svelte wstrzykiwanie funkcji jako `Slot` jest moim zdaniem antywzorcem. Dodaje to również złożoność, której można uniknąć, oraz narzut na wykonywanie JavaScriptu (nawet jeśli jest on ledwo zauważalny).
|
|
@@ -57,6 +57,13 @@ W praktyce, w przypadku najmniej zoptymalizowanych implementacji, strona zintern
|
|
|
57
57
|
|
|
58
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
59
|
|
|
60
|
+
## TL;DR
|
|
61
|
+
|
|
62
|
+
- **Intlayer**: Zapewnia najlepszą wydajność i najmniejszy rozmiar pakietu (v8.7.12) dla TanStack Start.
|
|
63
|
+
- **react-i18next** & **use-intl**: Dojrzałe alternatywy z dużymi ekosystemami, ale znacznie cięższe i bardziej złożone w optymalizacji.
|
|
64
|
+
- **Paraglide**: Innowacyjny pomysł na tree-shaking, który nie działa w praktyce. Skomplikowane DX i narzut reaktywności w TanStack Start.
|
|
65
|
+
- **Unikaj**: **General Translation (GT)** i **Lingo.dev** ze względu na poważne problemy z wydajnością, limity AI i uzależnienie od dostawcy (vendor lock-in).
|
|
66
|
+
|
|
60
67
|
## Przetestuj swoją aplikację
|
|
61
68
|
|
|
62
69
|
Aby szybko wykryć problemy z wyciekami i18n, przygotowałem darmowy skaner dostępny [tutaj](https://intlayer.org/i18n-seo-scanner).
|
|
@@ -87,12 +94,12 @@ Składnie oparte na `const t = useTranslation()` + `t('a.b.c')` są bardzo wygod
|
|
|
87
94
|
W tym benchmarku porównaliśmy następujące biblioteki:
|
|
88
95
|
|
|
89
96
|
- `Base App` (Brak biblioteki 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 @@ Idea stojąca za `Wuchale` jest interesująca, ale nie jest to jeszcze opłacaln
|
|
|
150
157
|
|
|
151
158
|
`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
159
|
|
|
153
|
-
|
|
160
|
+
> Uwaga dotycząca paraglide: to rozwiązanie wstrzykuje kod do bazy kodu dla importów, w wyniku czego metryka 'lib size' w raporcie benchmarku wynosi prawie 0. Generowanie kodu jest dobre, ponieważ użyta funkcja będzie zawierać tylko niezbędną logikę (prefiks wszędzie vs brak prefiksu, cookie vs pamięć itp.). Dla porównania, Intlayer wykonuje to filtrowanie poprzez wstrzykiwanie zmiennych środowiskowych w procesie budowania, aby wymusić na bundlerze tree-shaking zawartości w zależności od logiki. Dzięki temu paraglide i intlayer są ostatecznie od 6 do 10 razy lżejszymi rozwiązaniami niż i18next czy next-intl.
|
|
161
|
+
|
|
162
|
+
**(Tolgee)** (`@tolgee/react@7.0.0`):
|
|
154
163
|
|
|
155
164
|
`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
165
|
|
|
@@ -0,0 +1,160 @@
|
|
|
1
|
+
---
|
|
2
|
+
createdAt: 2026-04-20
|
|
3
|
+
updatedAt: 2026-04-21
|
|
4
|
+
title: Najlepsze rozwiązanie i18n dla Vue w 2026 r. — raport z benchmarku
|
|
5
|
+
description: Porównaj biblioteki internacjonalizacji (i18n) dla Vue, takie jak vue-i18n, fluent-vue i Intlayer. Szczegółowy raport wydajności dotyczący rozmiaru paczki, wycieków i reaktywności.
|
|
6
|
+
keywords:
|
|
7
|
+
- benchmark
|
|
8
|
+
- i18n
|
|
9
|
+
- intl
|
|
10
|
+
- vue
|
|
11
|
+
- wydajność
|
|
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: "Inicjalizacja benchmarku"
|
|
23
|
+
---
|
|
24
|
+
|
|
25
|
+
# Biblioteki i18n dla Vue — raport z benchmarku 2026
|
|
26
|
+
|
|
27
|
+
Ta strona zawiera raport z benchmarku rozwiązań i18n dla Vue.
|
|
28
|
+
|
|
29
|
+
## Spis treści
|
|
30
|
+
|
|
31
|
+
<Toc/>
|
|
32
|
+
|
|
33
|
+
## Interaktywny benchmark
|
|
34
|
+
|
|
35
|
+
<I18nBenchmark framework="vite-vue" 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-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
|
+
Pełne repozytorium benchmarku znajdziesz [tutaj](https://github.com/intlayer-org/benchmark-i18n/tree/main).
|
|
49
|
+
|
|
50
|
+
## Wstęp
|
|
51
|
+
|
|
52
|
+
Rozwiązania do internacjonalizacji należą do najcięższych zależności w aplikacji Vue. Głównym ryzykiem jest wysyłanie niepotrzebnych treści: tłumaczeń dla innych stron i innych lokalizacji w paczce (bundle) pojedynczej trasy.
|
|
53
|
+
|
|
54
|
+
W miarę rozwoju aplikacji problem ten może szybko zwiększyć ilość JavaScriptu wysyłanego do klienta i spowolnić nawigację.
|
|
55
|
+
|
|
56
|
+
W praktyce, w przypadku najmniej zoptymalizowanych implementacji, strona zinternacjonalizowana może okazać się kilkukrotnie cięższa niż wersja bez i18n.
|
|
57
|
+
|
|
58
|
+
Innym skutkiem jest wpływ na doświadczenie programisty (DX): sposób deklarowania treści, typy, organizacja przestrzeni nazw (namespaces), dynamiczne ładowanie i reaktywność przy zmianie lokalizacji.
|
|
59
|
+
|
|
60
|
+
## TL;DR
|
|
61
|
+
|
|
62
|
+
- **Intlayer**: Najlżejsze rozwiązanie (v8.7.12) z natywnym scopingiem i dynamicznym ładowaniem.
|
|
63
|
+
- **vue-i18n**: Standard branżowy z bogatym ekosystemem, ale może być znacznie cięższy i trudniejszy do optymalizacji pod kątem code-splittingu w dużych aplikacjach.
|
|
64
|
+
- **fluent-vue**: Innowacyjna organizacja komunikatów, ale brakuje jej bezpieczeństwa typów (type-safety) i okazuje się być ekstremalnie ciężkim rozwiązaniem.
|
|
65
|
+
|
|
66
|
+
## Przetestuj swoją aplikację
|
|
67
|
+
|
|
68
|
+
Aby szybko wykryć problemy z wyciekami i18n, przygotowałem darmowy skaner dostępny [tutaj](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
|
+
## Problem
|
|
73
|
+
|
|
74
|
+
Dwa dźwignie są kluczowe dla ograniczenia kosztów aplikacji wielojęzycznej:
|
|
75
|
+
|
|
76
|
+
- Dzielenie treści według stron / przestrzeni nazw, aby nie ładować całych słowników, gdy nie są potrzebne.
|
|
77
|
+
- Dynamiczne ładowanie odpowiedniej lokalizacji tylko wtedy, gdy jest potrzebna.
|
|
78
|
+
|
|
79
|
+
Zrozumienie technicznych ograniczeń tych podejść:
|
|
80
|
+
|
|
81
|
+
**Dynamiczne ładowanie**
|
|
82
|
+
|
|
83
|
+
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.
|
|
84
|
+
|
|
85
|
+
Dzięki dynamicznemu ładowaniu akceptujesz kompromis: mniej początkowego JS, ale czasami dodatkowe zapytanie przy zmianie języka.
|
|
86
|
+
|
|
87
|
+
**Dzielenie treści (Splitting)**
|
|
88
|
+
|
|
89
|
+
Składnie zbudowane wokół `const { t } = useI18n()` + `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 tree-shaking, chyba że biblioteka oferuje rzeczywistą strategię dzielenia na poszczególne strony.
|
|
90
|
+
|
|
91
|
+
## Metodologia badań
|
|
92
|
+
|
|
93
|
+
W tym benchmarku porównaliśmy następujące biblioteki:
|
|
94
|
+
|
|
95
|
+
- `Base App` (Brak biblioteki i18n)
|
|
96
|
+
- `vue-intlayer` (v8.7.12)
|
|
97
|
+
- `vue-i18n` (v11.4.0)
|
|
98
|
+
- `fluent-vue` (v3.8.2)
|
|
99
|
+
|
|
100
|
+
Framework to `Vue` z aplikacją wielojęzyczną składającą się z **10 stron** i **10 języków**.
|
|
101
|
+
|
|
102
|
+
Porównaliśmy **cztery strategie ładowania**:
|
|
103
|
+
|
|
104
|
+
| Strategia | Brak przestrzeni nazw (globalna) | Z przestrzeniami nazw (scoped) |
|
|
105
|
+
| :----------------------- | :------------------------------------------------ | :------------------------------------------------------------------------------- |
|
|
106
|
+
| **Ładowanie statyczne** | **Static**: Wszystko w pamięci przy starcie. | **Scoped static**: Podział na przestrzenie nazw; wszystko ładowane przy starcie. |
|
|
107
|
+
| **Ładowanie dynamiczne** | **Dynamic**: Ładowanie na żądanie na lokalizację. | **Scoped dynamic**: Szczegółowe ładowanie na przestrzeń nazw i lokalizację. |
|
|
108
|
+
|
|
109
|
+
## Podsumowanie strategii
|
|
110
|
+
|
|
111
|
+
- **Static**: Proste; brak opóźnień sieciowych po początkowym załadowaniu. Minus: duży rozmiar paczki.
|
|
112
|
+
- **Dynamic**: Zmniejsza początkową wagę (lazy-loading). Idealne, gdy masz wiele lokalizacji.
|
|
113
|
+
- **Scoped static**: Utrzymuje porządek w kodzie (logiczna separacja) bez skomplikowanych dodatkowych zapytań sieciowych.
|
|
114
|
+
- **Scoped dynamic**: Najlepsze podejście dla _code splittingu_ i wydajności. Minimalizuje zużycie pamięci, ładując tylko to, czego potrzebuje bieżący widok i aktywna lokalizacja.
|
|
115
|
+
|
|
116
|
+
### Co mierzyłem:
|
|
117
|
+
|
|
118
|
+
Uruchomiłem tę samą wielojęzyczną aplikację w prawdziwej przeglądarce dla każdego stosu technologicznego, a następnie zanotowałem, co faktycznie przesłała sieć i ile czasu zajęły poszczególne operacje. Rozmiary są podawane **po normalnej kompresji internetowej**, ponieważ jest to bliższe temu, co ludzie faktycznie pobierają, niż surowa liczba linii kodu źródłowego.
|
|
119
|
+
|
|
120
|
+
- **Rozmiar biblioteki internacjonalizacji**: Po spakowaniu (bundling), tree-shakingu i minifikacji, rozmiar biblioteki i18n to rozmiar kodu providerów + composables w pustym komponencie. Nie obejmuje ładowania plików tłumaczeń. Odpowiada na pytanie, jak „droga” jest biblioteka, zanim Twoja treść wejdzie do gry.
|
|
121
|
+
|
|
122
|
+
- **JavaScript na stronę**: Dla każdej trasy benchmarku, ile skryptów przeglądarka pobiera dla tej wizyty, uśrednione dla stron w zestawie (i dla lokalizacji). Ciężkie strony to wolne strony.
|
|
123
|
+
|
|
124
|
+
- **Wycieki z innych lokalizacji (Leakage)**: To treść tej samej strony, ale w innym języku, która zostałaby błędnie załadowana na kontrolowanej stronie. Ta treść jest niepotrzebna i należy jej unikać (np. treść strony `/fr/about` w paczce strony `/en/about`).
|
|
125
|
+
|
|
126
|
+
- **Wycieki z innych tras**: Ten sam pomysł dla **innych ekranów** w aplikacji: czy ich teksty są dołączane, gdy otworzyłeś tylko jedną stronę (np. treść strony `/en/about` w paczce strony `/en/contact`). Wysoki wynik sugeruje słabe dzielenie lub zbyt szerokie paczki.
|
|
127
|
+
|
|
128
|
+
- **Średni rozmiar paczki komponentu**: Typowe elementy interfejsu użytkownika są mierzone **pojedynczo**, zamiast ukrywać się w gigantycznej liczbie dla całej aplikacji. Pokazuje to, czy internacjonalizacja po cichu nadyma codzienne komponenty. Na przykład, jeśli Twój komponent renderuje się ponownie, załaduje wszystkie te dane z pamięci. Dołączanie gigantycznego JSON-a do dowolnego komponentu jest jak podłączanie dużego magazynu nieużywanych danych, co spowolni wydajność Twoich komponentów.
|
|
129
|
+
|
|
130
|
+
- **Reaktywność przełączania języka**: Przełączam język za pomocą własnego sterowania aplikacji i mierzę czas, aż strona wyraźnie się przełączy — co zauważyłby odwiedzający.
|
|
131
|
+
|
|
132
|
+
- **Praca renderowania po zmianie języka**: Bardziej szczegółowe badanie: ile wysiłku interfejs włożył w ponowne odrysowanie dla nowego języka po rozpoczęciu zmiany. Przydatne, gdy „odczuwalny” czas i koszt frameworka się rozbiegają.
|
|
133
|
+
|
|
134
|
+
- **Czas początkowego ł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”.
|
|
135
|
+
|
|
136
|
+
- **Czas hydratacji (Hydration)**: Czas, jaki klient spędza na przekształcaniu HTML z serwera w interaktywny interfejs. Myślnik w tabelach oznacza, że ta implementacja nie dostarczyła wiarygodnej liczby dotyczącej hydratacji w tym benchmarku.
|
|
137
|
+
|
|
138
|
+
## Wyniki szczegółowe
|
|
139
|
+
|
|
140
|
+
### 1 — Rozwiązania, których należy unikać
|
|
141
|
+
|
|
142
|
+
> W ekosystemie Vue nie ma jednoznacznego rozwiązania, którego należy unikać.
|
|
143
|
+
|
|
144
|
+
### 2 — Rozwiązania akceptowalne
|
|
145
|
+
|
|
146
|
+
**(vue-i18n)** (`vue-i18n@11.4.0`):
|
|
147
|
+
|
|
148
|
+
- **vue-i18n** jest bezsprzecznie najczęściej używaną biblioteką i18n dla Vue, ma wiele funkcji i ogromny ekosystem. Jednak pod maską rozwiązanie to jest dość ciężkie. Nawet jeśli vue-i18n integruje lazy loading dla komunikatów, brakuje mu funkcji scopingu. W przypadku klasycznej aplikacji Vue SPA nie ma problemu, ale dla aplikacji nuxt wykorzystującej @nuxt/i18n prowadzi to do włączania komunikatów ze wszystkich stron do jednej. W przypadku dużej aplikacji nuxt zawierającej ponad 10 stron może to stać się naprawdę problematyczne.
|
|
149
|
+
|
|
150
|
+
Paczka jest bardzo ciężka (~24.3kb, co stanowi około 9x `vue-intlayer`).
|
|
151
|
+
|
|
152
|
+
**(fluent-vue)** (`fluent-vue@0.5.0`):
|
|
153
|
+
|
|
154
|
+
- **fluent-vue** oferuje próbę innowacji poprzez format .ftl. Organizacja komunikatów jest świetna, łatwiej zacząć. Ale w praktyce brak bezpieczeństwa typów zwiększa ryzyko błędu, a debugowanie może szybko stać się czasochłonne. Co więcej, to rozwiązanie ładuje komunikaty za pomocą wtyczki vite, która wymusza ładowanie całej treści we wszystkich językach na każdej stronie. Dodatkowo jest to ekstremalnie ciężkie rozwiązanie (~92.7kb, co stanowi około 34x `vue-intlayer`).
|
|
155
|
+
|
|
156
|
+
### 3 — Rekomendacje
|
|
157
|
+
|
|
158
|
+
**(Intlayer)** (`vue-intlayer@8.7.12`):
|
|
159
|
+
|
|
160
|
+
Nie będę osobiście oceniać `vue-intlayer` ze względu na obiektywizm, ponieważ jest to moje własne rozwiązanie.
|
package/docs/pl/configuration.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2024-08-13
|
|
3
|
-
updatedAt: 2026-
|
|
3
|
+
updatedAt: 2026-05-12
|
|
4
4
|
title: Konfiguracja
|
|
5
5
|
description: Dowiedz się, jak skonfigurować Intlayer dla swojej aplikacji. Zrozum różne ustawienia i opcje dostępne do dostosowania Intlayer do Twoich potrzeb.
|
|
6
6
|
keywords:
|
|
@@ -14,6 +14,9 @@ slugs:
|
|
|
14
14
|
- concept
|
|
15
15
|
- configuration
|
|
16
16
|
history:
|
|
17
|
+
- version: 8.9.4
|
|
18
|
+
date: 2026-05-12
|
|
19
|
+
changes: "Dodano obsługę dostawcy LM Studio"
|
|
17
20
|
- version: 8.7.0
|
|
18
21
|
date: 2026-04-08
|
|
19
22
|
changes: "Dodano opcje `prune` i `minify` do konfiguracji budowania"
|
|
@@ -350,7 +353,7 @@ const config: IntlayerConfig = {
|
|
|
350
353
|
ai: {
|
|
351
354
|
/**
|
|
352
355
|
* Wybrany dostawca AI.
|
|
353
|
-
* Opcje: 'openai', 'anthropic', 'mistral', 'deepseek', 'gemini', 'ollama', 'openrouter', 'alibaba', 'fireworks', 'groq', 'huggingface', 'bedrock', 'googlevertex', 'togetherai'
|
|
356
|
+
* Opcje: 'openai', 'anthropic', 'mistral', 'deepseek', 'gemini', 'ollama', 'openrouter', 'alibaba', 'fireworks', 'groq', 'huggingface', 'bedrock', 'googlevertex', 'togetherai', 'lmstudio'
|
|
354
357
|
* Domyślnie: 'openai'
|
|
355
358
|
*/
|
|
356
359
|
provider: "openai",
|
|
@@ -916,16 +919,17 @@ Intlayer obsługuje szeroką gamę dostawców AI, aby zapewnić maksymalną elas
|
|
|
916
919
|
- **Groq**
|
|
917
920
|
- **Amazon Bedrock**
|
|
918
921
|
- **Together.ai**
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
|
922
|
-
|
|
|
923
|
-
| `
|
|
924
|
-
| `
|
|
925
|
-
| `
|
|
926
|
-
| `
|
|
927
|
-
| `
|
|
928
|
-
| `
|
|
922
|
+
- **LM Studio**
|
|
923
|
+
|
|
924
|
+
| Pole | Opis | Typ | Domyślnie | Przykład | Uwagi |
|
|
925
|
+
| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------- | ------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
926
|
+
| `provider` | Dostawca, który będzie używany do funkcji AI w Intlayer. | `'openai'` | <br/> `'anthropic'` | <br/> `'mistral'` | <br/> `'deepseek'` | <br/> `'gemini'` | <br/> `'ollama'` | <br/> `'openrouter'` | <br/> `'alibaba'` | <br/> `'fireworks'` | <br/> `'groq'` | <br/> `'huggingface'` | <br/> `'bedrock'` | <br/> `'googleaistudio'` | <br/> `'googlevertex'` | <br/> `'togetherai'` | <br/> `'lmstudio'` | `undefined` | `'anthropic'` | Różni dostawcy wymagają różnych kluczy API i mają różne cenniki. |
|
|
927
|
+
| `model` | Model AI do użycia w funkcjach AI. | `string` | Brak | `'gpt-4o-2024-11-20'` | Konkretne modele zależą od dostawcy. |
|
|
928
|
+
| `temperature` | Kontroluje losowość odpowiedzi AI. | `number` | Brak | `0.1` | Wyższa temperatura = bardziej kreatywne, ale mniej niezawodne odpowiedzi. |
|
|
929
|
+
| `apiKey` | Twój klucz API dla wybranego dostawcy. | `string` | Brak | `process.env.OPENAI_API_KEY` | Musi pozostać tajny; używaj zmiennych środowiskowych. |
|
|
930
|
+
| `applicationContext` | Dodatkowy kontekst o Twojej aplikacji, aby pomóc AI generować dokładniejsze tłumaczenia (domena, grupa docelowa, ton, terminologia). | `string` | Brak | `'mój własny kontekst aplikacji'` | Można użyć do dodania zasad (np.: `"Nie powinieneś tłumaczyć swoich URL"` ). |
|
|
931
|
+
| `baseURL` | Bazowy URL dla API AI. | `string` | Brak | `'https://api.openai.com/v1'` <br/> `'http://localhost:5000'` | Może wskazywać na lokalne lub własne punkty końcowe API AI. |
|
|
932
|
+
| `dataSerialization` | Format serializacji danych dla funkcji AI. | `'json'` | <br/> `'toon'` | `undefined` | `'toon'` | • `'json'`: domyślnie, niezawodne; zużywa więcej tokenów.<br/>• `'toon'`: mniej tokenów, mniej stabilne.<br/>• Przekazuje modelowi kontekst jako dodatkowy parametr (reasoning effort itp.). |
|
|
929
933
|
|
|
930
934
|
---
|
|
931
935
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
---
|
|
2
2
|
createdAt: 2025-02-07
|
|
3
|
-
updatedAt: 2026-
|
|
3
|
+
updatedAt: 2026-05-12
|
|
4
4
|
title: Plik z Treścią
|
|
5
5
|
description: Dowiedz się, jak dostosować rozszerzenia dla plików deklaracji treści. Postępuj zgodnie z tą dokumentacją, aby efektywnie wdrażać warunki w swoim projekcie.
|
|
6
6
|
keywords:
|
|
@@ -12,6 +12,9 @@ slugs:
|
|
|
12
12
|
- concept
|
|
13
13
|
- content
|
|
14
14
|
history:
|
|
15
|
+
- version: 8.9.0
|
|
16
|
+
date: 2026-05-12
|
|
17
|
+
changes: "Add `plural` content node type"
|
|
15
18
|
- version: 8.0.0
|
|
16
19
|
date: 2026-01-28
|
|
17
20
|
changes: "Dodano typ węzła zawartości `html`"
|
|
@@ -66,6 +69,7 @@ import { type ReactNode } from "react";
|
|
|
66
69
|
import {
|
|
67
70
|
t,
|
|
68
71
|
enu,
|
|
72
|
+
plural,
|
|
69
73
|
cond,
|
|
70
74
|
nest,
|
|
71
75
|
md,
|
|
@@ -85,6 +89,7 @@ interface Content {
|
|
|
85
89
|
};
|
|
86
90
|
multilingualContent: string;
|
|
87
91
|
quantityContent: string;
|
|
92
|
+
pluralContent: string;
|
|
88
93
|
conditionalContent: string;
|
|
89
94
|
markdownContent: never;
|
|
90
95
|
htmlContent: never;
|
|
@@ -120,6 +125,10 @@ export default {
|
|
|
120
125
|
">5": "Kilka samochodów",
|
|
121
126
|
">19": "Wiele samochodów",
|
|
122
127
|
}),
|
|
128
|
+
pluralContent: plural({
|
|
129
|
+
one: "One car",
|
|
130
|
+
other: "{{count}} cars",
|
|
131
|
+
}),
|
|
123
132
|
conditionalContent: cond({
|
|
124
133
|
true: "Walidacja jest włączona",
|
|
125
134
|
false: "Walidacja jest wyłączona",
|
|
@@ -174,6 +183,13 @@ export default {
|
|
|
174
183
|
">5": "Kilka samochodów",
|
|
175
184
|
">19": "Wiele samochodów",
|
|
176
185
|
},
|
|
186
|
+
"pluralContent": {
|
|
187
|
+
"nodeType": "plural",
|
|
188
|
+
"plural": {
|
|
189
|
+
"one": "One car",
|
|
190
|
+
"other": "{{count}} cars",
|
|
191
|
+
},
|
|
192
|
+
},
|
|
177
193
|
},
|
|
178
194
|
"conditionalContent": {
|
|
179
195
|
"nodeType": "condition",
|
|
@@ -221,6 +237,7 @@ Węzły treści są podstawowymi elementami zawartości słownika. Mogą to być
|
|
|
221
237
|
- **Wartości prymitywne**: łańcuchy znaków, liczby, wartości logiczne, null, undefined
|
|
222
238
|
- **Węzły typowane**: Specjalne typy zawartości, takie jak tłumaczenia, warunki, markdown itp.
|
|
223
239
|
- **Funkcje**: Dynamiczna zawartość, która może być oceniana w czasie wykonywania [zobacz Pobieranie funkcji](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pl/dictionary/function_fetching.md)
|
|
240
|
+
- **Plural Content**: See Plural Content [See Plural Content](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pl/dictionary/plural.md)
|
|
224
241
|
- **Zagnieżdżona zawartość**: Odwołania do innych słowników
|
|
225
242
|
|
|
226
243
|
#### Typy zawartości
|
|
@@ -551,6 +568,8 @@ multilingualContent: t({
|
|
|
551
568
|
});
|
|
552
569
|
```
|
|
553
570
|
|
|
571
|
+
> See [Zawartość tłumaczenia (`t`) Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pl/dictionary/translation.md) for more information.
|
|
572
|
+
|
|
554
573
|
### Zawartość warunkowa (`cond`)
|
|
555
574
|
|
|
556
575
|
Treść, która zmienia się w zależności od warunków logicznych (boolean):
|
|
@@ -564,6 +583,8 @@ conditionalContent: cond({
|
|
|
564
583
|
});
|
|
565
584
|
```
|
|
566
585
|
|
|
586
|
+
> See [Zawartość warunkowa (`cond`) Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pl/dictionary/condition.md) for more information.
|
|
587
|
+
|
|
567
588
|
### Treść enumeracyjna (`enu`)
|
|
568
589
|
|
|
569
590
|
Treść, która zmienia się w zależności od wartości enumeracyjnych:
|
|
@@ -578,6 +599,23 @@ statusContent: enu({
|
|
|
578
599
|
});
|
|
579
600
|
```
|
|
580
601
|
|
|
602
|
+
> See [Treść enumeracyjna (`enu`) Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pl/dictionary/enumeration.md) for more information.
|
|
603
|
+
|
|
604
|
+
### Plural Content (`plural`)
|
|
605
|
+
|
|
606
|
+
Content that varies based on plural rules:
|
|
607
|
+
|
|
608
|
+
```typescript
|
|
609
|
+
import { plural } from "intlayer";
|
|
610
|
+
|
|
611
|
+
pluralContent: plural({
|
|
612
|
+
one: "One car",
|
|
613
|
+
other: "{{count}} cars",
|
|
614
|
+
});
|
|
615
|
+
```
|
|
616
|
+
|
|
617
|
+
> See [Plural Content Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pl/dictionary/plural.md) for more information.
|
|
618
|
+
|
|
581
619
|
### Treść wstawiana (`insert`)
|
|
582
620
|
|
|
583
621
|
Treść, którą można wstawić do innej treści:
|
|
@@ -588,6 +626,8 @@ import { insert } from "intlayer";
|
|
|
588
626
|
insertionContent: insert("Ten tekst można wstawić w dowolne miejsce");
|
|
589
627
|
```
|
|
590
628
|
|
|
629
|
+
> See [Treść wstawiana (`insert`) Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pl/dictionary/insertion.md) for more information.
|
|
630
|
+
|
|
591
631
|
### Treść zagnieżdżona (`nest`)
|
|
592
632
|
|
|
593
633
|
Odniesienia do innych słowników:
|
|
@@ -598,6 +638,8 @@ import { nest } from "intlayer";
|
|
|
598
638
|
nestedContent: nest("about-page");
|
|
599
639
|
```
|
|
600
640
|
|
|
641
|
+
> See [Treść zagnieżdżona (`nest`) Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pl/dictionary/nesting.md) for more information.
|
|
642
|
+
|
|
601
643
|
### Zawartość Markdown (`md`)
|
|
602
644
|
|
|
603
645
|
Treść sformatowana w Markdown:
|
|
@@ -610,6 +652,8 @@ markdownContent: md(
|
|
|
610
652
|
);
|
|
611
653
|
```
|
|
612
654
|
|
|
655
|
+
> See [Zawartość Markdown (`md`) Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pl/dictionary/markdown.md) for more information.
|
|
656
|
+
|
|
613
657
|
### Zawartość HTML (`html`)
|
|
614
658
|
|
|
615
659
|
Zawartość HTML, która może używać standardowych tagów lub niestandardowych komponentów:
|
|
@@ -627,6 +671,8 @@ localizedHtmlContent: t({
|
|
|
627
671
|
});
|
|
628
672
|
```
|
|
629
673
|
|
|
674
|
+
> See [Zawartość HTML (`html`) Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pl/dictionary/html.md) for more information.
|
|
675
|
+
|
|
630
676
|
### Zawartość według płci (`gender`)
|
|
631
677
|
|
|
632
678
|
Treść zmieniająca się w zależności od płci:
|
|
@@ -641,6 +687,8 @@ genderContent: gender({
|
|
|
641
687
|
});
|
|
642
688
|
```
|
|
643
689
|
|
|
690
|
+
> See [Zawartość według płci (`gender`) Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pl/dictionary/gender.md) for more information.
|
|
691
|
+
|
|
644
692
|
### Zawartość pliku (`file`)
|
|
645
693
|
|
|
646
694
|
Odniesienia do plików zewnętrznych:
|
|
@@ -651,6 +699,8 @@ import { file } from "intlayer";
|
|
|
651
699
|
fileContent: file("./path/to/content.txt");
|
|
652
700
|
```
|
|
653
701
|
|
|
702
|
+
> See [Zawartość pliku (`file`) Doc](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pl/dictionary/file.md) for more information.
|
|
703
|
+
|
|
654
704
|
## Tworzenie plików z zawartością
|
|
655
705
|
|
|
656
706
|
### Podstawowa struktura pliku z zawartością
|
|
@@ -160,30 +160,9 @@ syncPO({
|
|
|
160
160
|
source: ({ key, locale }) => string, // wymagane
|
|
161
161
|
location?: string, // opcjonalna etykieta, domyślnie: "sync-po::path/to/source"
|
|
162
162
|
priority?: number, // opcjonalny priorytet dla rozwiązywania konfliktów, domyślnie: 0
|
|
163
|
-
format?: 'icu' | 'i18next' | 'vue-i18n', // opcjonalne, potrzebne tylko gdy wartości msgstr używają specyficznej składni interpolacji
|
|
164
163
|
});
|
|
165
164
|
```
|
|
166
165
|
|
|
167
|
-
#### `format` ('icu' | 'i18next' | 'vue-i18n')
|
|
168
|
-
|
|
169
|
-
Pliki PO to zawsze pliki Gettext Portable Object — to jest stałe. Ta opcja opisuje jedynie **składnię interpolacji** używaną wewnątrz wartości `msgstr`, dzięki czemu Intlayer może przekonwertować je na własny format w czasie parsowania (przez `formatDictionary`) i z powrotem podczas zapisywania wyników.
|
|
170
|
-
|
|
171
|
-
- `undefined` _(domyślnie)_: wartości `msgstr` są traktowane jako zwykłe ciągi znaków — brak transformacji. Używaj tego dla większości plików PO.
|
|
172
|
-
- `'icu'`: wartości `msgstr` używają składni komunikatów ICU (np. `{count, plural, one {# item} other {# items}}`).
|
|
173
|
-
- `'i18next'`: wartości `msgstr` używają składni interpolacji i18next (np. `{{variable}}`).
|
|
174
|
-
- `'vue-i18n'`: wartości `msgstr` używają składni Vue I18n.
|
|
175
|
-
|
|
176
|
-
> Transformacja jest nakładana przez `formatDictionary` z `@intlayer/chokidar` przy ładowaniu i odwracana za pomocą `formatDictionaryOutput` przy zapisie. W przypadku złożonych reguł, takich jak liczby mnogie ICU, wierność konwersji w obie strony nie jest gwarantowana.
|
|
177
|
-
|
|
178
|
-
**Przykład — pliki PO zawierają interpolację w stylu i18next:**
|
|
179
|
-
|
|
180
|
-
```ts
|
|
181
|
-
syncPO({
|
|
182
|
-
source: ({ key, locale }) => `./locales/${locale}/${key}.po`,
|
|
183
|
-
format: "i18next",
|
|
184
|
-
}),
|
|
185
|
-
```
|
|
186
|
-
|
|
187
166
|
### Wiele źródeł PO i priorytet
|
|
188
167
|
|
|
189
168
|
Możesz dodać wiele pluginów `syncPO`, aby synchronizować różne źródła PO. Jest to przydatne, gdy masz wiele źródeł tłumaczeń lub różne struktury PO w swoim projekcie.
|
|
@@ -30,6 +30,3 @@ Abaixo estão os relatórios detalhados e a documentação técnica de cada fram
|
|
|
30
30
|
- [**Vue Benchmark Report**](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/benchmark/vue.md)
|
|
31
31
|
- [**Solid Benchmark Report**](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/benchmark/solid.md)
|
|
32
32
|
- [**Svelte Benchmark Report**](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/benchmark/svelte.md)
|
|
33
|
-
- [**Vue Benchmark Report**](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/benchmark/vue.md)
|
|
34
|
-
- [**Solid Benchmark Report**](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/benchmark/solid.md)
|
|
35
|
-
- [**Svelte Benchmark Report**](https://github.com/aymericzip/intlayer/blob/main/docs/docs/en/benchmark/svelte.md)
|