Zadaj pytanie i otrzymaj streszczenie dokumentu, odwołując się do tej strony i wybranego dostawcy AI
Historia wersji
- "Aktualizacja wyników benchmarku"v9.5.1026.09.2026
- "Aktualizacja wyników benchmarku i dodanie Tolgee"v9.5.723.09.2026
- "Aktualizacja wyników benchmarku"v9.5.111.09.2026
- "Dodaj porównanie gwiazdek GitHub"v8.9.818.05.2026
- "Inicjalizacja benchmarku"v8.7.126.01.2026
Treść tej strony została przetłumaczona przy użyciu sztucznej inteligencji.
Zobacz ostatnią wersję oryginalnej treści w języku angielskimJeśli masz pomysł na ulepszenie tej dokumentacji, zachęcamy do przesłania pull requesta na GitHubie.
Link do dokumentacji na GitHubieKopiuj dokument Markdown do schowka
Biblioteki i18n dla Vue - raport z benchmarku 2026
Ta strona zawiera raport z benchmarku rozwiązań i18n dla Vue.
Spis treści
Interaktywny benchmark
Metryka
Dynamiczne ładowanie JSON
Wczytuje tłumaczenia leniwie w czasie wykonywania
Ograniczony JSON (przestrzenie nazw)
Przestrzenie nazw tłumaczeń na stronę
Czym jest ta metryka?
Całkowity skompresowany przez gzip rozmiar pakietu biblioteki umiędzynarodowienia. Obejmuje tylko dostawcę i logikę pobierania treści po tree-shakingu i minifikacji.
Dlaczego to jest ważne?
Mniejszy rozmiar biblioteki zmniejsza obciążenie u klienta.
Zobacz jako
Referencja wyników:
Wstęp
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.
W miarę rozwoju aplikacji problem ten może szybko zwiększyć ilość JavaScriptu wysyłanego do klienta i spowolnić nawigację.
W praktyce, w przypadku najmniej zoptymalizowanych implementacji, strona zinternacjonalizowana może okazać się kilkukrotnie cięższa niż wersja bez i18n.
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.
Aby zrozumieć, skąd wzięły się te biblioteki, przeczytaj historię i18n w JavaScript.
TL;DR
- Intlayer: Najlżejsze rozwiązanie (v9.5.10) z natywnym scopingiem i dynamicznym ładowaniem.
- Tolgee: Efektywne ładowanie dynamiczne z zerowym wyciekiem w trybie dynamicznym, ale cięższe (~3.0× Intlayer) i brak wbudowanego bezpieczeństwa typów w czasie kompilacji.
- 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.
- fluent-vue: Innowacyjna organizacja komunikatów, ale brakuje jej bezpieczeństwa typów (type-safety) i okazuje się być ekstremalnie ciężkim rozwiązaniem.
Przetestuj swoją aplikację
Aby szybko wykryć problemy z wyciekami i18n, możesz wypróbować darmowy skaner SEO i18n.
Problem
Dwa dźwignie są kluczowe dla ograniczenia kosztów aplikacji wielojęzycznej:
- Dzielenie treści według stron / przestrzeni nazw, aby nie ładować całych słowników, gdy nie są potrzebne.
- Dynamiczne ładowanie odpowiedniej lokalizacji tylko wtedy, gdy jest potrzebna.
Zrozumienie technicznych ograniczeń tych podejść:
Dynamiczne ładowanie
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.
Dzięki dynamicznemu ładowaniu akceptujesz kompromis: mniej początkowego JS, ale czasami dodatkowe zapytanie przy zmianie języka.
Dzielenie treści (Splitting)
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.
Metodologia badań
W tym benchmarku porównaliśmy następujące biblioteki:
Base App(Brak biblioteki i18n)vue-intlayer(v9.5.10)@intlayer/vue-i18n(v9.5.10)vue-i18n(v11.4.0)fluent-vue(v3.8.2)@tolgee/vue(v7.2.0)
Framework to Vue z aplikacją wielojęzyczną składającą się z 10 stron i 10 języków.
Porównaliśmy cztery strategie ładowania:
Otwórz tabelę w oknie modalnym, aby wyraźnie zobaczyć całą zawartość
| Strategia | Brak przestrzeni nazw (globalna) | Z przestrzeniami nazw (scoped) |
|---|---|---|
| Ładowanie statyczne | Static: Wszystko w pamięci przy starcie. | Scoped static: Podział na przestrzenie nazw; wszystko ładowane przy starcie. |
| Ładowanie dynamiczne | Dynamic: Ładowanie na żądanie na lokalizację. | Scoped dynamic: Szczegółowe ładowanie na przestrzeń nazw i lokalizację. |
Podsumowanie strategii
- Static: Proste; brak opóźnień sieciowych po początkowym załadowaniu. Minus: duży rozmiar paczki.
- Dynamic: Zmniejsza początkową wagę (lazy-loading). Idealne, gdy masz wiele lokalizacji.
- Scoped static: Utrzymuje porządek w kodzie (logiczna separacja) bez skomplikowanych dodatkowych zapytań sieciowych.
- 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.
Co mierzyłem:
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.
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.
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.
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/aboutw paczce strony/en/about).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/aboutw paczce strony/en/contact). Wysoki wynik sugeruje słabe dzielenie lub zbyt szerokie paczki.Ś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.
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.
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ą.
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”.
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.
Gwiazdki na GitHubie
Gwiazdki na GitHubie są silnym wskaźnikiem popularności projektu, zaufania społeczności i długoterminowego znaczenia. Choć nie są bezpośrednią miarą jakości technicznej, odzwierciedlają, ilu programistów uważa projekt za przydatny, śledzi jego postępy i prawdopodobnie go przyjmie. Przy szacowaniu wartości projektu gwiazdki pomagają porównać zainteresowanie alternatywami i dostarczają wglądu w rozwój ekosystemu.
Aktywność commitów
Gwiazdki pokazują popularność. Commity pokazują, ile pracy włożono w projekt. W chwili pisania Intlayer ma około 7 500 commitów, więcej niż większość porównywanych tu bibliotek i mniej więcej 5 razy więcej niż next-intl czy next-i18next.
- intlify/vue-i18n
- fluent-vue/fluent-vue
- tolgee/tolgee-js
- aymericzip/intlayer
Commity na domyślnej gałęzi, źródło: GitHub API.
Intlayer to monorepo, więc ta liczba obejmuje każdy pakiet dla frameworków, CLI i dokumentację. Traktuj commity jako sygnał aktywności, a nie jakości.
Pobrania z npm
- vue-i18n
- fluent-vue
- @tolgee/vue
- vue-intlayer
Źródło: API pobrań rejestru npm.
Liczba pobrań nagradza najstarsze rozwiązania, a nie najlepsze. Biblioteka wydana lata temu wciąż jest instalowana przez każdy projekt, który ją wtedy wybrał, przez każde uruchomienie CI i przez każdy pakiet, który od niej zależy. Ta liczba mierzy bezwładność bardziej niż świadomy wybór.
Asystenci AI wzmacniają ten efekt. next-intl, i18next i vue-i18n są wszędzie w kodzie, na którym ich trenowano, więc proponują je domyślnie, bez porównywania alternatyw. Każda sugestia dodaje pobrań, które napędzają kolejną sugestię. Porównuj na podstawie benchmarku, a nie liczby pobrań.
Wyniki szczegółowe
1 - Rozwiązania, których należy unikać
W ekosystemie Vue nie ma jednoznacznego rozwiązania, którego należy unikać.
2 - Rozwiązania akceptowalne
(Tolgee) (@tolgee/vue@7.2.0):
Tolgee rozwiązuje wiele z wymienionych wcześniej problemów, oferując dynamiczne ładowanie, które skutecznie eliminuje wycieki locale i stron (zmniejszając rozmiar JS strony do około 58.8kb). Nie zapewnia jednak wbudowanego bezpieczeństwa typów w czasie kompilacji dla kluczy, co utrudnia wykrywanie brakujących kluczy. Ponadto sama biblioteka jest stosunkowo ciężka (~13.8kb, czyli około 3.0× vue-intlayer).
(vue-i18n) (vue-i18n@11.4.0):
- 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.
Paczka jest bardzo ciężka (~24.1 kb, co stanowi około 6.5× vue-intlayer).
(fluent-vue) (fluent-vue@3.8.2):
- 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 20×
vue-intlayer).
3 - Rekomendacje
(Intlayer) (vue-intlayer@9.5.10):
Nie będę osobiście oceniać vue-intlayer ze względu na obiektywizm, ponieważ jest to moje własne rozwiązanie.
