Autor:
    Data utworzenia:2026-04-20Ostatnia aktualizacja:2026-09-27

    Biblioteki i18n dla Solid - raport z benchmarku 2026

    Ta strona zawiera raport z benchmarku rozwiązań i18n dla Solid.

    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 Solid. 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: Zalecany wybór dla profesjonalnych aplikacji Solid wymagających zaawansowanych funkcji i optymalizacji (v9.5.10).
    • @solid-primitives/i18n: Doskonała lekka alternatywa dla prostych projektów, choć brakuje jej zaawansowanych funkcji, takich jak lazy loading.
    • solid-i18next: Standardowa, ale ciężka opcja (~3.5x Intlayer) z tymi samymi wadami co React i18next.
    • Tolgee: Bogata w funkcje platforma tłumaczeniowa, ale dość ciężka (~12.7kb, około 3.0× Intlayer), pozbawiona dedykowanych prymitywów Solid (opiera się na @tolgee/web) i wykazująca znaczny wyciek między stronami w konfiguracjach statycznych (90% wycieku stron).
    • Paraglide: Innowacyjne podejście, ale złożone DX i problemy z tree-shakingiem w niektórych konfiguracjach.

    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ół 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:

    Framework to Solid z aplikacją wielojęzyczną składającą się z 10 stron i 10 języków.

    Porównaliśmy cztery strategie ładowania:

    StrategiaBrak przestrzeni nazw (globalna)Z przestrzeniami nazw (scoped)
    Ładowanie statyczneStatic: Wszystko w pamięci przy starcie.Scoped static: Podział na przestrzenie nazw; wszystko ładowane przy starcie.
    Ładowanie dynamiczneDynamic: Ł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, a następnie zapisałem, co faktycznie pojawiło się na sieci i jak długo to trwało. Rozmiary są podawane po normalnej kompresji internetowej, ponieważ jest to bliższe temu, co ludzie pobierają, niż surowe liczby źródła.

    • Rozmiar biblioteki internacjonalizacji: Po bundlingu, tree-shakingu i minifikacji, rozmiar biblioteki i18n to rozmiar providerów + kodu hooks/primitives w pustym komponencie. Nie obejmuje ładowania plików tłumaczeń. Odpowiada na pytanie, jak kosztowna jest biblioteka zanim twoja zawartość wejdzie do gry.

    • JavaScript na stronę: Dla każdej trasy benchmarku, ile skryptu przeglądarka pobiera dla tej wizyty, uśrednione na stronach w zestawie (i na lokalizacjach, gdzie raport je łączy). Ciężkie strony to wolne strony.

    • Wyciek z innych lokalizacji: To zawartość tej samej strony, ale w innym języku, która byłaby załadowana przez pomyłkę na audytowanej stronie. Ta zawartość jest zbędna i powinna być unikana. (np. zawartość strony /fr/about w bundlu strony /en/about)

    • Wyciek z innych tras: Ten sam pomysł dla innych ekranów w aplikacji: czy ich kopia jedzie razem, gdy otworzysz tylko jedną stronę. (np. zawartość strony /en/about w bundlu strony /en/contact). Wysoki wynik sugeruje słabe dzielenie lub zbyt szerokie bundle'i.

    • Średni rozmiar bundle'u komponentu: Typowe elementy UI są mierzone jeden po drugim zamiast ukrywania się wewnątrz jednej gigantycznej liczby aplikacji. Pokazuje, czy internacjonalizacja po cichu rozszerza zwykłe komponenty. Na przykład, jeśli twój komponent zostanie ponownie renderowany, załaduje wszystkie te dane z pamięci. Przywiązanie gigantycznego JSON'a do dowolnego komponentu jest jak podłączenie dużego magazynu nieużywanych danych, który spowolni wydajność twoich komponentów.

    • Responsywność przełącznika języka: Przełączam język przy użyciu kontrolki aplikacji i mierzę, jak długo trwa, zanim strona wyraźnie się zmieni, co odwiedzający zauważy, a nie laboratoryjny mikrokrok.

    • Praca renderowania po zmianie języka: Węższe uzupełnienie: ile wysiłku interfejsowi zajęło przepainting dla nowego języka po tym, jak przełączenie jest w locie. Przydatne, gdy „odczuty" czas i koszt framework'u się rozchodzą.

    • Czas początkowego załadowania strony: Od nawigacji do przeglądarki traktującej stronę jako całkowicie załadowaną dla scenariuszy, które testowałem. Dobry do porównywania zimnych startów.

    • Czas hydratacji: Gdy aplikacja to ujawnia, jak długo klient spędza na zamienianiu HTML serwera na coś, na co możesz faktycznie kliknąć. Kreska w tabelach oznacza, że implementacja nie dostarczyła wiarygodnej liczby 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.

    Star History Chart

    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.

    • solidjs-community/solid-primitives
    • mbarzda/solid-i18next
    • opral/paraglide-js
    • 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

    • @solid-primitives/i18n
    • @mbarzda/solid-i18next
    • @inlang/paraglide-js
    • @tolgee/web
    • solid-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 Solid nie ma jednoznacznego rozwiązania, którego należy unikać.

    2 - Rozwiązania akceptowalne

    (solid-i18next) (i18next@26.0.8):

    solid-i18next jest prawdopodobnie najpopularniejszą opcją, ponieważ był jednym z pierwszych rozwiązań zaspokajających potrzeby i18n aplikacji JavaScript. Posiada również szeroki zestaw wtyczek społecznościowych dla konkretnych problemów.

    Paczka jest ciężka (~14.9kb, co stanowi około 3.5x solid-intlayer).

    Mimo to dzieli te same główne wady co stosy technologiczne zbudowane na t('a.b.c'): optymalizacje są możliwe, ale bardzo czasochłonne, a duże projekty niosą ze sobą ryzyko złych praktyk (przestrzenie nazw + dynamiczne ładowanie + typy).

    (@solid-primitives/i18n) (@solid-primitives/i18n@2.2.1):

    Solid primitive jest niezwykle lekki i wydajny. Polecam to rozwiązanie dla lekkich projektów, ale może w nim szybko zabraknąć funkcji dla profesjonalnych rozwiązań, w tym zarządzania plikami cookie, przekierowań proxy, formaterów itp. Brakuje mu również lazy loadingu i scopingu przestrzeni nazw w celu optymalizacji rozmiaru strony.

    (Tolgee) (@tolgee/web@7.2.0):

    Tolgee oferuje kompleksową platformę zarządzania tłumaczeniami z funkcjami edycji in-context.

    W Solid obecnie nie ma oficjalnego natywnego adaptera (takiego jak @tolgee/solid), co zmusza programistów do integracji za pomocą @tolgee/web z własnymi sygnałami.

    Pakiet jest stosunkowo ciężki (~12.7kb, czyli około 3.0× solid-intlayer).

    Bez mechanizmu granularnego podziału na strony w Solid wszystkie tłumaczenia są ładowane do pamięci od razu przy starcie w konfiguracjach statycznych. Skutkuje to dużym wyciekiem paczki (44.5% wycieku języka, 90.0% wycieku stron) oraz średnim rozmiarem paczki strony ~91.8kb (w porównaniu do ~35.4kb dla Intlayer).

    Reaktywność podczas zmiany języka jest bardzo szybka (0.6ms), idealnie współgrając z drobnoziarnistą reaktywnością Solid, chociaż narzut hydratacji jest nieco wyższy (~5.6ms w porównaniu do ~2.9ms dla Intlayer).

    (Paraglide) (@inlang/paraglide-js@2.25.1):

    Paraglide oferuje innowacyjne, przemyślane podejście. Mimo to w tym benchmarku reklamowany przez nich tree-shaking nie zadziałał w mojej implementacji. Workflow i DX są również bardziej złożone niż w przypadku innych opcji. Osobiście nie lubię konieczności regeneracji plików JS przed każdym pushem, co stwarza ciągłe ryzyko konfliktów przy mergowaniu poprzez PR-y. Wreszcie, w porównaniu z innymi rozwiązaniami, Paraglide nie używa store'a (np. Solid signal) 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.

    3 - Rekomendacje

    (Intlayer) (solid-intlayer@9.5.10):

    Nie będę osobiście oceniać solid-intlayer ze względu na obiektywizm, ponieważ jest to moje własne rozwiązanie.

    Notatka osobista

    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.

    W aplikacjach Solid wstrzykiwanie funkcji jako JSX.Element 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).