Zadaj pytanie i otrzymaj streszczenie dokumentu, odwołując się do tej strony i wybranego dostawcy AI
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
i18next VS @intlayer/i18next: To samo API, inny bundle

@intlayer/i18next, @intlayer/react-i18next i @intlayer/next-i18next to adaptery kompatybilności. Udostępniają API i18next, którego Twój kod już używa (useTranslation, t(), <Trans>, i18n.changeLanguage(), getFixedT, serverSideTranslations...) i obsługują je ze słowników skompilowanych przez Intlayer. Komponenty się nie zmieniają. Zmienia się runtime pod nimi.
Ten artykuł mierzy tę zamianę na tej samej aplikacji Next.js, zbudowanej raz z next-i18next, a raz z @intlayer/next-i18next. Liczby pochodzą z Benchmark Bloom. Aby porównać i18next i Intlayer jako biblioteki, przeczytaj i18next vs Intlayer. Ten artykuł dotyczy tego, co zmienia adapter, gdy zachowujesz swój kod bez zmian.
tl;dr: W tej samej aplikacji Next.js zastąpienienext-i18nextprzez@intlayer/next-i18nextzmniejszyło ilość kodu JavaScript na stronę z 218.5 KB do 150.7 KB gzip (konfiguracja naiwna) i pokonało w pełni zoptymalizowaną konfiguracjęnext-i18next(163.4 KB) o 12.7 KB. Średni komponent zmniejszył się z 78.5 KB do 9.7 KB, wyciek ciągów znaków z obcych stron z ~90% do 0%, hydratacja z 15.6 ms do 11.3 ms, a runtime z 19.7 KB do 9.4 KB. Żaden komponent nie był modyfikowany; zmieniono jeden plik dostawcy (provider). Wtyczkii18next(backendy, detektory języka) są akceptowane, ale nic nie robią: w środowisku wykonawczym nie ma już nic do załadowania ani wykrycia.
Czym jest @intlayer/i18next
i18next to środowisko wykonawcze (runtime). i18n.init({ resources }) lub wtyczka backendu ładuje locales/{lng}/{ns}.json do globalnej instancji; useTranslation("about") subskrybuje do niej komponent; t("title") wyszukuje klucz podczas renderowania. Przestrzenie nazw (namespaces), leniwe ładowanie (lazy loading), listy przestrzeni nazw na stronę i bezpieczeństwo typów pozostają w Twojej gestii do skonfigurowania i utrzymania.
Adaptery zachowują API i zastępują instancję:
- Aliasy importów.
createNextI18nPlugin()z@intlayer/next-i18next/plugin(lubwithI18next) opakowujewithIntlayeri dodaje aliasy Webpack / Turbopack, dzięki czemunext-i18next,react-i18nextii18nextwskazują na ich odpowiedniki@intlayer/*. W VitereactI18nextVitePlugin()z@intlayer/react-i18next/pluginrobi to samo. Żaden import nie jest zmieniany. - JSON jako źródło prawdy. Wtyczka
syncJSONodczytuje istniejące plikilocales/{lng}/{ns}.jsonzformat: "i18next"(dzięki czemu{{name}}, zagnieżdżanie$t(), sufiksy_one/_otheroraz konteksty są poprawnie parsowane) i zapisuje tłumaczenia z powrotem, gdy CLI lub CMS je zaktualizuje. - Wiązanie w miejscu wywołania (call-site binding). Krok optymalizacji Intlayer przepisuje
useTranslation("about")na wywołanie, które otrzymuje słownikaboutbezpośrednio, w aktywnym języku. Komponent przestaje odwoływać się do globalnego magazynu.
Skopiuj kod do schowka
Skopiuj kod do schowka
To przepisanie wpływa bezpośrednio na kolumny rozmiaru komponentów i wycieków stron poniżej.
Co adaptery zachowują, ignorują i czego nie zastępują
Otwórz tabelę w oknie modalnym, aby wyraźnie zobaczyć całą zawartość
API i18next | Z @intlayer/* |
|---|---|
useTranslation("ns"), useTranslation("ns", { keyPrefix }) | ✅ Zachowane. Powiązane ze słownikiem ns w czasie budowania; klucze typowane na podstawie zawartości |
t("key", { name }), {{interpolation}}, zagnieżdżanie $t(key) | ✅ Zachowane |
Liczba mnoga key_one / key_other, kontekst key_male, returnObjects | ✅ Zachowane. Liczby mnogie ewaluowane za pomocą Intl.PluralRules |
<Trans> z components, numerowane tagi <1>...</1>, values | ✅ Zachowane |
withTranslation, Translation, I18nContext | ✅ Zachowane |
i18n.changeLanguage(), i18n.language, i18n.dir(), on("languageChanged") | ✅ Zachowane. changeLanguage steruje językiem Intlayer |
getFixedT(lng, ns, keyPrefix), i18n.exists(), hasLoadedNamespace() | ✅ Zachowane |
i18n.use(Backend).use(LanguageDetector).init({...}) | ⚠️ use() wywołuje init wtyczki i zwraca wynik; backendy i detektory nie mają nic do załadowania ani wykrycia |
init({ resources }), addResourceBundle() | ⚠️ resources jest ignorowane z ostrzeżeniem dev; usuń importy JSON, aby uzyskać korzyści w bundle |
I18nextProvider i18n={i18n} | ⚠️ Renderuje IntlayerProvider; właściwość i18n jest ignorowana. W App Router przekaż locale (patrz poniżej) |
serverSideTranslations(locale, ["common"]) (next-i18next) | ⚠️ Zwraca oczekiwany kształt i niczego nie ładuje. Bezpieczne do pozostawienia lub usunięcia |
appWithTranslation(App) (next-i18next) | ✅ Zachowane |
next-i18next.config.js | ⚠️ Nieodczytywane. Języki pochodzą z intlayer.config.ts |
Zwykłe useTranslation() bez przestrzeni nazw | ✅ Działa względem słownika translation dla całego pliku (splitKeys: false) |
Benchmark
Co mierzono
Zestaw Benchmark Bloom buduje tę samą aplikację w każdej konfiguracji: 10 stron (home, about, blog, careers, contact, FAQ, pricing, products, settings, team), 10 języków (en, fr, es, de, it, pt, zh, ja, ko, ru), identyczne komponenty i identyczna zawartość. Strony są mierzone w en i fr.
next-i18next zbudowano w czterech strategiach ładowania, od importu JSON każdego języka do resources (static) po jedną przestrzeń nazw na trasę, ładowaną leniwie przez backend (scoped-dynamic). Adapter zbudowano na tych samych komponentach co konfigurację naiwną, ze zmienionymi plikami next.config.ts, intlayer.config.ts oraz plikiem providera. Nie ma wariantu "scoped": kompilator sam ogranicza zasięg zawartości na komponent.
Dla każdego buildu zestaw rejestruje:
- Lib size: rozmiar gzip pustego komponentu, który importuje tylko bibliotekę i18n.
- Page JS: pobrany JavaScript gzip na stronę, uśredniony dla wszystkich stron i języków.
- Locale leak %: udział przetłumaczonych ciągów w pobranym JS należących do języka, którego użytkownik nie przegląda.
- Page leak %: udział przetłumaczonych ciągów w pobranym JS należących do strony, na której użytkownik nie przebywa.
- Component avg: średni rozmiar gzip każdego komponentu skompilowanego w izolacji.
- E2E reactivity: rzeczywisty czas między wyborem nowego języka a aktualizacją
html[lang]w DOM (Playwright, 5 iteracji). - Hydration: czas trwania fazy hydratacji React.
Poniższe liczby pochodzą z uruchomienia z dnia 2026-09-12 znext-i18next16.3.0 (react-i18next17.0.13,i18next26.4.2) oraz@intlayer/next-i18next9.5.1. Aplikacja testowa jest celowo niewielka (kilkadziesiąt ciągów na język), więc wartości procentowe wycieków opisują wzorzec: rosną one wraz z zawartością, podczas gdy koszt runtime pozostaje stały.
Wyniki w Next.js
Wybierz metryki i biblioteki, które Cię interesują:
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
Otwórz tabelę w oknie modalnym, aby wyraźnie zobaczyć całą zawartość
| Konfiguracja | Strategia | Lib size (gz) | Page JS avg (gz) | Locale leak | Page leak | Component avg (gz) | E2E reactivity | Hydration |
|---|---|---|---|---|---|---|---|---|
| base (brak i18n) | - | 0.0 KB | 141.0 KB | 0.0% | 0.0% | 0.9 KB | 13.4 ms | 11.8 ms |
next-i18next | static | 19.7 KB | 218.5 KB | 0.0% | 89.8% | 78.5 KB | 16.4 ms | 15.6 ms |
next-i18next | dynamic | 19.7 KB | 169.5 KB | 50.0% | 89.8% | 26.1 KB | 15.4 ms | 27.7 ms |
next-i18next | scoped-static | 19.7 KB | 220.1 KB | 0.0% | 89.8% | 78.9 KB | 16.4 ms | 14.7 ms |
next-i18next | scoped-dynamic | 19.7 KB | 163.4 KB | 0.0% | 0.0% | 27.1 KB | 15.9 ms | 15.1 ms |
@intlayer/next-i18next | static | 9.4 KB | 150.7 KB | 0.0% | 0.0% | 9.7 KB | 10.7 ms | 11.3 ms |
@intlayer/next-i18next | dynamic | 9.4 KB | 150.7 KB | 0.0% | 0.0% | 9.7 KB | 11.9 ms | 10.6 ms |
next-intlayer (natywny) | static | 5.5 KB | 141.3 KB | 0.0% | 0.0% | 8.5 KB | 15.5 ms | 16.9 ms |
next-intlayer (natywny) | dynamic | 5.5 KB | 141.3 KB | 0.0% | 0.0% | 6.9 KB | 15.3 ms | 15.9 ms |
Jak to interpretować
- 68 KB mniej na stronę względem konfiguracji naiwnej.
resources: { en, fr, ... }wysyła każdy język i każdą przestrzeń nazw na każdej stronie: 218.5 KB. Build adaptera dla tych samych komponentów osiąga 150.7 KB. Pokonuje również najlepszą konfiguracjęnext-i18next(163.4 KB, jedna przestrzeń nazw na trasę, ładowana leniwie) o 12.7 KB, ponieważ sam runtimei18nextważy 19.7 KB w porównaniu do 9.4 KB. - Wyciek spada do 0% bez dotykania jakiegokolwiek komponentu. Każda konfiguracja
next-i18nextz wyjątkiem w pełni wyizolowanej (scoped) wysyła ~90% ciągów z obcych stron. Wierszdynamicwygląda gorzej niż w teorii: wcale nie eliminuje wycieku stron i dodaje 50% wycieku języków, ponieważ backend dla danego języka nadal pobiera całą przestrzeń nazwtranslation. Adapter osiąga 0% / 0% z poziomu naiwnego kodu. - Komponenty: 8-krotnie mniejsze. Komponent
useTranslation()skompilowany w izolacji waży średnio 78.5 KB przy wbudowanychresourcesoraz 26-27 KB z backendem, ponieważtjest powiązane z globalnym magazynem. Z adapterem osiąga średnio 9.7 KB. - Hydratacja i przełączanie są szybsze. Hydratacja przyspiesza z 15.6 ms do 11.3 ms (oraz z 27.7 ms w konfiguracji
dynamic, gdzie pobieranie z backendu znajduje się na ścieżce krytycznej). Przełączanie języka przyspiesza z 15-16 ms do 11-12 ms. - Adapter to nie natywny runtime.
next-intlayerosiąga 141.3 KB, czyli +0.3 KB względem bazowej aplikacji. Adapter wnosi powierzchnię APIi18next(dialekt interpolacji, rozwiązywanie sufiksów liczby mnogiej i kontekstu, parsowanie tagów<Trans>) na wierzchu rdzenia Intlayer: 9.4 KB i +9.4 KB na stronę ponad natywną implementację. To pomost, a nie ostateczny cel.
Pełna tabela, każda biblioteka i każda strategia, w raporcie benchmarku Next.js.
Wyniki w TanStack Start (react-i18next)
Dla Vite i TanStack Start benchmark porównuje czysty react-i18next z intlayer:
Otwórz tabelę w oknie modalnym, aby wyraźnie zobaczyć całą zawartość
| Biblioteka | Strategia | Lib size (gz) | Page JS avg (gz) | Locale leak | Page leak | Component avg (gz) | E2E reactivity | Hydration |
|---|---|---|---|---|---|---|---|---|
| base (brak i18n) | - | 0.0 KB | 111.0 KB | 0.0% | 0.0% | 0.7 KB | 8.1 ms | 21.6 ms |
react-i18next | dynamic | 18.4 KB | 136.4 KB | 23.1% | 89.8% | 24.8 KB | 123.1 ms | 32.9 ms |
intlayer | dynamic | 5.0 KB | 118.6 KB | 0.0% | 0.0% | 6.3 KB | 3.6 ms | 14.1 ms |
Pełna tabela w raporcie benchmarku TanStack Start.
Adapterreact-i18nextw Vite / TanStack Start nie brał udziału w tym uruchomieniu. Wartość bazowareact-i18nextw TanStack Start znajduje się w i18next vs Intlayer: 127-184 KB na stronę i 123-185 ms przełączania języka przy leniwym backendzie.
Dlaczego liczby się zmieniają

W katalogu components/ nic się nie zmieniło, więc zyski wynikają z tego, z czym powiązane jest useTranslation.
W przypadku i18next powiązaniem jest instancja globalna. Cokolwiek zostało do niej załadowane (wszystkie języki w static, cała przestrzeń nazw aktywnego języka w dynamic), jest dostępne z każdego komponentu wywołującego useTranslation(). Bundler nie może dokonać podziału poniżej tego, co zawiera instancja, a runtime nie może wiedzieć, o które klucze zapyta komponent.
Skopiuj kod do schowka
Wszystko, co zawiera instancja, jest przesyłane na każdą stronę, a marnotrawstwo rośnie na dwóch osiach, stron i języków:

W przypadku @intlayer/next-i18next powiązaniem jest słownik. syncJSON przekształca każdy plik przestrzeni nazw w słownik; krok optymalizacji przekazuje komponentowi słownik, do którego się odwołuje, jako import, który bundler może śledzić i dzielić według stron i języków.
Skopiuj kod do schowka
i18n/i18n.ts i jego import resources stają się martwym kodem. To właśnie te 68 KB.
Migracja w trzech krokach
Instalacja
bashKopiuj kodSkopiuj kod do schowka
Polecenie wykrywa
i18next/react-i18next/next-i18next, instalujeintlayer, pakiet frameworka (next-intlayerlubreact-intlayer), pasujący adapter@intlayer/*oraz@intlayer/sync-json-plugin, a także wstępnie konfigurujeintlayer.config.ts. Zachowaj zainstalowane oryginalne pakiety: są to peer dependencies i dostarczają typy.Wskaż Intlayer pliki językowe
intlayer.config.tsKopiuj kodSkopiuj kod do schowka
Jeśli masz pojedynczy plik
translation.jsonna język (domyślna przestrzeń nazw w i18next), ustawsplitKeys: false, aby cały plik pozostał jednym słownikiem i zwykłeuseTranslation()nadal działało.Dodaj wtyczkę
next.config.tsKopiuj kodSkopiuj kod do schowka
W App Router komponenty klienckie pobierają swój język z segmentu
[locale]. KomponentI18nextProvideradaptera nie przyjmuje parametru locale, więc zastąp go raz w pliku providera:components/AppProviders.tsxKopiuj kodSkopiuj kod do schowka
Każdy komponent poniżej nadal wywołuje
useTranslation().vite.config.tsKopiuj kodSkopiuj kod do schowka
reactI18nextVitePlugin()opakowujevite-intlayeri tworzy aliasy dlareact-i18nextii18next. W projekcie bez Reacti18nextVitePlugin()z@intlayer/i18next/plugintworzy alias dla samegoi18next.
Co można potem usunąć
Otwórz tabelę w oknie modalnym, aby wyraźnie zobaczyć całą zawartość
| Plik / wzorzec | Dlaczego |
|---|---|
resources: { en, fr, ... } i importy JSON | Ignorowane przez adapter. To tutaj znajdowało się 68 KB |
i18next-http-backend, i18next-resources-to-backend | Brak danych do pobierania w środowisku wykonawczym |
i18next-browser-languagedetector | Wykrywanie języka to konfiguracja routingu Intlayer (prefiks URL, cookie, nagłówek) |
serverSideTranslations() w getStaticProps | Zwraca pustą strukturę; nieszkodliwe, ale martwe |
next-i18next.config.js | Nieodczytywane. Języki znajdują się w intlayer.config.ts |
Listy ns: [...] per strona | Kompilator dobiera przestrzenie nazw na komponent |
Co zyskujesz poza zaoszczędzonymi bajtami
- Typowane klucze.
useTranslation("about")jest typowane względem skompilowanego słownikaabout;t("does.not.exist")powoduje błąd TypeScript zamiast zwróconego ciągu klucza. npx intlayer testkończy się błędem w CI w przypadku brakującego klucza w dowolnym języku.npx intlayer filltłumaczy brakujące klucze za pomocą Twojego klucza dostawcy (OpenAI, Anthropic, Mistral, Gemini...) i zapisuje je z powrotem dolocales/{lng}/{ns}.json.- Wizualny Edytor i CMS operują na tym samym JSON, dzięki czemu tłumacze edytują treści przez interfejs użytkownika, a pliki są aktualizowane.
- Stopniowe przejście na
.content.ts. Dowolny komponent może przełączyć się zuseTranslation("about")nauseIntlayer("about")z plikiem zawartości zlokalizowanym obok komponentu. Słowniki JSON i.content.tswspółistnieją.
Ograniczenia, które warto znać przed rozpoczęciem
i18n.use(HttpBackend) wywołuje jedynie init wtyczki i nic więcej. Jeśli Twoja aplikacja polegała na pobieraniu tłumaczeń z CMS w czasie wykonywania, ten przepływ znika; użyj zamiast tego Intlayer CMS lub poleceń intlayer pull / push. Wykrywanie języka staje się konfiguracją routingu Intlayer (prefiks URL, cookie, nagłówek).
W przeciwieństwie do innych adapterów, @intlayer/i18next nie używa wbudowanych resources jako rozwiązania awaryjnego. Każdy klucz musi istnieć w zsynchronizowanych słownikach, co weryfikuje intlayer test.
Jeden plik, pokazany powyżej. Pages Router z appWithTranslation nie wymaga żadnych zmian.
localePath, fallbackLng, reloadOnPrerender i pokrewne nie mają odpowiedników; języki i wartości domyślne pochodzą z intlayer.config.ts.
9.4 KB runtime i +9.4 KB na stronę w stosunku do next-intlayer. Gdy każdy komponent przejdzie na useIntlayer, usuń go.
Porównanie funkcji
Poza bajtami, co daje każda z opcji:
Otwórz tabelę w oknie modalnym, aby wyraźnie zobaczyć całą zawartość
| Funkcja | i18next / react-i18next / next-i18next | Adaptery @intlayer/* | Natywny Intlayer |
|---|---|---|---|
Twoje wywołania t(), useTranslation, <Trans> | ✅ | ✅ Bez zmian | ❌ Przeniesione do useIntlayer |
| Rozmiar runtime (gzip, Next.js) | 19.7 KB | 9.4 KB | 5.5 KB |
| Wyciek z innych stron bez ręcznych namespace'ów | ~90% | 0% | 0% |
| Typowane klucze | ⚠️ Ręczna deklaracja | ✅ Ze skompilowanych słowników | ✅ Generowane automatycznie |
| Backendy i pluginy w runtime | ✅ Pełny ekosystem pluginów | ❌ Nieaktywne | ❌ Nie dotyczy, użyj CMS |
| Treść obok komponentów | ❌ Scentralizowany JSON | ⚠️ JSON, .content.ts może współistnieć | ✅ .content.ts obok każdego komponentu |
| Brakujące tłumaczenia w CI | ⚠️ Brak wbudowanej obsługi | ✅ npx intlayer test | ✅ npx intlayer test |
| Tłumaczenie AI | ❌ Nie | ✅ npx intlayer fill | ✅ npx intlayer fill |
| Edytor wizualny / CMS | ❌ Przez zewnętrzne platformy | ✅ Na tym samym JSON | ✅ Tak |
| Ekosystem / społeczność | ✅ Bardzo duży | ⚠️ Mniejszy, szybko rośnie | ⚠️ Mniejszy, szybko rośnie |
Rozmiary runtime pochodzą z opisanego wyżej uruchomienia na Next.js.
Kiedy używać którego rozwiązania?
Twoja aplikacja zależy od backendów w czasie wykonywania (tłumaczenia serwowane przez CMS w momencie żądania), od ekosystemu wtyczek lub od środowiska innego niż React, którego adaptery nie obsługują.
Używasz react-i18next / next-i18next i chcesz zaoszczędzić 68 KB, mieć 8-krotnie mniejsze komponenty, 0% wycieków, typowane klucze i testy CI bez przepisywania kodu. To punkt wejścia dla istniejącej bazy kodu i18next.
Dla nowych projektów lub po zakończeniu pracy przez adapter. Ma najlżejszy runtime (5.5 KB, +0.3 KB na stronę) i odblokowuje synchroniczne Server Components oraz pliki .content.ts dla każdego komponentu. Zacznij od Intlayer z Next.js lub z Vite i React.
Często zadawane pytania
Z resources: { en, fr, ... }. Domyślna konfiguracja next-i18next importuje JSON każdego języka do init(), przez co każda strona przenosi każdy namespace w każdym języku: 218.5 KB na stronę. Adapter nigdy nie dołącza tego bloku w całości; przekazuje każdemu komponentowi tylko żądany słownik w aktywnym języku.
Tak, z components, numerowanymi tagami <1>...</1> oraz values. Podobnie z {{interpolation}}, zagnieżdżaniem $t(key), formami mnogimi key_one / key_other (ocenianymi za pomocą Intl.PluralRules), sufiksami kontekstowymi i returnObjects.
Ustaw splitKeys: false we wtyczce syncJSON. Cały plik pozostanie jednym słownikiem, a standardowe wywołanie useTranslation() będzie nadal na niego wskazywać.
Nie, to pomost. Adapter zachowuje API i18next i kosztuje 9.4 KB runtime; natywny next-intlayer kosztuje 5.5 KB i dodaje synchroniczne Server Components oraz pliki .content.ts umieszczone obok komponentów. Możesz migrować komponent po komponencie, ponieważ słowniki JSON i .content.ts współistnieją.
Tak. locales/{lng}/{ns}.json pozostaje źródłem prawdy: syncJSON odczytuje go w dialekcie i18next i zapisuje tłumaczenia z powrotem, gdy CLI lub CMS je zaktualizuje.
Powiązane porównania
Ta sama seria adapterów:
Biblioteki w bezpośrednim porównaniu:
Dokumentacja referencyjna:
Compat adapters:
Migration guides:
Aby zrozumieć, skąd wzięły się te biblioteki, przeczytaj historię i18n w JavaScript.
Podsumowanie
i18next to najcięższy runtime w tym benchmarku, a adaptery usuwają większość z niego bez konieczności rezygnacji z jego API. Na tej samej aplikacji Next.js oznacza to 68 KB mniej na stronę niż w konfiguracji naiwnej, 12.7 KB mniej niż w najlepiej zoptymalizowanej ręcznie, 8x mniejsze komponenty, 0% wycieków oraz 4 ms szybszą hydratację, w zamian za plik konfiguracyjny, jedną linijkę wtyczki i zmianę w jednym providerze. Backendy i detektory stają się operacjami no-op, resources jest ignorowane zamiast scalane, a natywny runtime next-intlayer pozostaje o kolejne 9 KB lżejszy.
Wszystkie surowe dane, aplikacje testowe i skrypty znajdują się w repozytorium Benchmark Bloom. Uruchom je samodzielnie.
Więcej szczegółów znajdziesz w dokumentacji Dlaczego Intlayer?.
Komentarze
Nie ma jeszcze komentarzy. Bądź pierwszą osobą, która podzieli się swoimi przemyśleniami.
