@intlayer/docs 7.3.3 → 7.3.4

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.
@@ -2,7 +2,7 @@
2
2
  createdAt: 2025-11-24
3
3
  updatedAt: 2025-11-24
4
4
  title: Kompilator kontra deklaratywne i18n
5
- description: Eksploracja kompromisów architektonicznych między "magiczna" internacjonalizacją opartą na kompilatorze a explicytnym, deklaratywnym zarządzaniem treścią.
5
+ description: Eksploracja kompromisów architektonicznych między "magiczna" internacjonalizacją opartą na kompilatorze a eksplicytnym, deklaratywnym zarządzaniem treścią.
6
6
  keywords:
7
7
  - Intlayer
8
8
  - Internacjonalizacja
@@ -20,37 +20,69 @@ slugs:
20
20
 
21
21
  # Argumenty za i przeciw internacjonalizacji opartej na kompilatorze
22
22
 
23
- Jeśli tworzysz aplikacje webowe od ponad dekady, wiesz, że internacjonalizacja (i18n) zawsze była punktem zapalnym. Często jest to zadanie, którego nikt nie chce wykonywać — wyciąganie stringów, zarządzanie plikami JSON i martwienie się o zasady pluralizacji.
23
+ Jeśli budujesz aplikacje webowe od ponad dekady, wiesz, że internacjonalizacja (i18n) zawsze była punktem zapalnym. Często jest to zadanie, którego nikt nie chce wykonywać — wyciąganie stringów, zarządzanie plikami JSON i martwienie się o zasady pluralizacji.
24
24
 
25
- Ostatnio pojawiła się nowa fala narzędzi i18n opartych na "kompilatorze", obiecujących, że ta uciążliwość zniknie. Przekaz jest kuszący: **Po prostu pisz tekst w swoich komponentach, a narzędzie budujące zajmie się resztą.** Bez kluczy, bez importów, po prostu magia.
25
+ Niedawno pojawiła się nowa fala **narzędzi i18n opartych na kompilatorze**, obiecujących, że ta uciążliwość zniknie. Oferta jest kusząca: **Po prostu pisz tekst w swoich komponentach, a narzędzie budujące zajmie się resztą.** Bez kluczy, bez importów, po prostu magia.
26
26
 
27
27
  Ale jak to bywa ze wszystkimi abstrakcjami w inżynierii oprogramowania, magia ma swoją cenę.
28
28
 
29
- W tym wpisie na blogu przyjrzymy się przejściu od bibliotek deklaratywnych do podejść opartych na kompilatorze, ukrytym długom architektonicznym, które one wprowadzają, oraz dlaczego "nudny" sposób może nadal być najlepszym rozwiązaniem dla profesjonalnych aplikacji.
29
+ W tym wpisie na blogu przeanalizujemy przejście od bibliotek deklaratywnych do podejść opartych na kompilatorze, ukryte długi architektoniczne, które wprowadzają, oraz dlaczego nudny" sposób może nadal być najlepszym rozwiązaniem dla profesjonalnych aplikacji.
30
30
 
31
- ## Krótka historia tłumaczeń
31
+ ## Spis treści
32
+
33
+ <TOC/>
34
+
35
+ ## Krótka historia internacjonalizacji
32
36
 
33
37
  Aby zrozumieć, gdzie jesteśmy, musimy spojrzeć wstecz, skąd zaczęliśmy.
34
38
 
35
- Około 2011–2012 krajobraz JavaScript wyglądał zupełnie inaczej. Bundlery takie jak znamy je dziś (Webpack, Vite) nie istniały lub były we wczesnym stadium rozwoju. Sklejaliśmy skrypty bezpośrednio w przeglądarce. W tym okresie powstały biblioteki takie jak **i18next**.
39
+ Około 2011–2012 krajobraz JavaScript wyglądał zupełnie inaczej. Bundlery, jakie znamy dzisiaj (Webpack, Vite), nie istniały lub były na bardzo wczesnym etapie rozwoju. Sklejaliśmy skrypty bezpośrednio w przeglądarce. W tym okresie powstały biblioteki takie jak **i18next**.
36
40
 
37
- Rozwiązały one problem w jedyny możliwy wtedy sposób: **Słowniki w czasie wykonywania (Runtime Dictionaries)**. Ładowało się ogromny obiekt JSON do pamięci, a funkcja wyszukiwała klucze na bieżąco. Było to niezawodne, jawne i działało wszędzie.
41
+ Rozwiązały one problem w jedyny możliwy wtedy sposób: **Słowniki w czasie wykonywania**. Ładowało się ogromny obiekt JSON do pamięci, a funkcja wyszukiwała klucze na bieżąco. Było to niezawodne, jawne i działało wszędzie.
38
42
 
39
43
  Przenieśmy się do dziś. Mamy potężne kompilatory (SWC, bundlery oparte na Rust), które potrafią analizować Abstrakcyjne Drzewa Składniowe (AST) w ciągu milisekund. Ta moc dała początek nowemu pomysłowi: _Dlaczego ręcznie zarządzamy kluczami? Dlaczego kompilator nie może po prostu zobaczyć tekstu "Hello World" i zamienić go za nas?_
40
44
 
41
45
  Tak narodziło się i18n oparte na kompilatorze.
42
46
 
43
- ## Urok Kompilatora (Podejście „Magiczne”)
47
+ > **Przykład i18n opartego na kompilatorze:**
48
+ >
49
+ > - Paraglide (Moduły poddane tree-shakingowi, które kompilują każdą wiadomość do małej funkcji ESM, dzięki czemu bundlery mogą automatycznie usuwać nieużywane lokalizacje i klucze. Importujesz wiadomości jako funkcje zamiast wyszukiwać je po kluczach tekstowych.)
50
+ > - LinguiJS (Kompilator makr do funkcji, który przepisuje makra wiadomości, takie jak `<Trans>`, na zwykłe wywołania funkcji JS podczas budowania. Otrzymujesz składnię ICU/MessageFormat z bardzo małym narzutem w czasie wykonywania.)
51
+ > - Lingo.dev (Skupia się na automatyzacji procesu lokalizacji poprzez wstrzykiwanie przetłumaczonej zawartości bezpośrednio podczas budowania aplikacji React. Może automatycznie generować tłumaczenia za pomocą AI i integrować się bezpośrednio z CI/CD.)
52
+ > - Wuchale (Preprocesor skoncentrowany na Svelte, który wyodrębnia tekst inline w plikach .svelte i kompiluje go do funkcji tłumaczeniowych bez dodatkowych wrapperów. Unika kluczy tekstowych i całkowicie oddziela logikę ekstrakcji treści od głównego środowiska uruchomieniowego aplikacji.)
53
+ > - Intlayer (Kompilator / CLI do ekstrakcji, który analizuje twoje komponenty, generuje typowane słowniki i opcjonalnie może przepisać kod, aby używać jawnej zawartości Intlayer. Celem jest wykorzystanie kompilatora dla szybkości, zachowując deklaratywne, niezależne od frameworka jądro.)
54
+
55
+ > **Przykład deklaratywnego i18n:**
56
+ >
57
+ > - i18next / react-i18next / next-i18next (Dojrzały standard branżowy wykorzystujący słowniki JSON w czasie wykonywania oraz rozbudowany ekosystem wtyczek)
58
+ > - react-intl (Część biblioteki FormatJS, skupiająca się na standardowej składni komunikatów ICU oraz ścisłym formatowaniu danych)
59
+ > - next-intl (Specjalnie zoptymalizowany dla Next.js z integracją dla App Router i React Server Components)
60
+ > - vue-i18n / @nuxt/i18n (Standardowe rozwiązanie ekosystemu Vue oferujące bloki tłumaczeń na poziomie komponentów oraz ścisłą integrację reaktywności)
61
+ > - svelte-i18n (Lekka nakładka na Svelte stores dla reaktywnych tłumaczeń w czasie wykonywania)
62
+ > - angular-translate (Przestarzała biblioteka dynamicznych tłumaczeń oparta na wyszukiwaniu kluczy w czasie wykonywania zamiast scalania podczas budowania)
63
+ > - angular-i18n (Natywne podejście Angulara, działające ahead-of-time, scalające pliki XLIFF bezpośrednio z szablonami podczas budowania)
64
+ > - Tolgee (Łączy deklaratywny kod z SDK w kontekście, umożliwiając edycję "kliknij, aby przetłumaczyć" bezpośrednio w interfejsie użytkownika)
65
+ > - Intlayer (Podejście per-komponent, wykorzystujące pliki deklaracji treści umożliwiające natywne tree-shaking oraz walidację TypeScript)
66
+
67
+ ## Kompilator Intlayer
68
+
69
+ Chociaż **Intlayer** jest rozwiązaniem, które zasadniczo zachęca do **deklaratywnego podejścia** do Twoich treści, zawiera kompilator, który pomaga przyspieszyć rozwój lub ułatwić szybkie prototypowanie.
70
+
71
+ Kompilator Intlayer przeszukuje AST (Abstract Syntax Tree) Twoich komponentów React, Vue lub Svelte, a także innych plików JavaScript/TypeScript. Jego rolą jest wykrywanie zakodowanych na stałe łańcuchów znaków i wyodrębnianie ich do dedykowanych deklaracji `.content`.
72
+
73
+ > Aby uzyskać więcej szczegółów, zapoznaj się z dokumentacją: [Intlayer Compiler Docs](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pl/compiler.md)
74
+
75
+ ## Urok Kompilatora (Podejście "Magiczne")
44
76
 
45
- Istnieje powód, dla którego to nowe podejście zyskuje na popularności. Dla dewelopera doświadczenie jest niesamowite.
77
+ Jest powód, dla którego to nowe podejście zyskuje na popularności. Dla dewelopera doświadczenie jest niesamowite.
46
78
 
47
- ### 1. Szybkość i Flow
79
+ ### 1. Szybkość i "Flow"
48
80
 
49
- Kiedy jesteś w strefie, zatrzymanie się, by wymyślić nazwę zmiennej (`home_hero_title_v2`), przerywa twój flow. Przy podejściu kompilatorowym wpisujesz `<p>Welcome back</p>` i idziesz dalej. Tarcie jest zerowe.
81
+ Kiedy jesteś w strefie, zatrzymanie się, aby wymyślić semantyczną nazwę zmiennej (`home_hero_title_v2`), przerywa twój flow. Przy podejściu kompilatora wpisujesz `<p>Welcome back</p>` i idziesz dalej. Tarcie jest zerowe.
50
82
 
51
- ### 2. Misja Ratunkowa dla Dziedzictwa
83
+ ### 2. Misja Ratunkowa dla Dziedzictwa (Legacy)
52
84
 
53
- Wyobraź sobie, że dziedziczysz ogromną bazę kodu z 5000 komponentów i zerowymi tłumaczeniami. Dopasowanie tego do ręcznego systemu opartego na kluczach to koszmar trwający miesiące. Narzędzie oparte na kompilatorze działa jako strategia ratunkowa, natychmiast wyciągając tysiące stringów bez konieczności ręcznego dotykania choćby jednego pliku.
85
+ Wyobraź sobie, że dziedziczysz ogromną bazę kodu z 5000 komponentami i zerowymi tłumaczeniami. Dostosowanie tego do ręcznego systemu opartego na kluczach to koszmar trwający miesiącami. Narzędzie oparte na kompilatorze działa jako strategia ratunkowa, natychmiast wyciągając tysiące ciągów znaków bez konieczności ręcznego dotykania pojedynczego pliku.
54
86
 
55
87
  ### 3. Era AI
56
88
 
@@ -59,79 +91,130 @@ To nowoczesna korzyść, której nie powinniśmy pomijać. Asystenci kodowania A
59
91
  - **Deklaratywne:** Musisz przepisać wynik AI, aby zastąpić tekst kluczami.
60
92
  - **Kompilator:** Kopiujesz i wklejasz kod AI i po prostu działa.
61
93
 
62
- ## Sprawdzenie Rzeczywistości: Dlaczego „Magia” jest Niebezpieczna
94
+ ## Sprawdzenie rzeczywistości: Dlaczego „magia” jest niebezpieczna
95
+
96
+ Chociaż „magia” jest kusząca, abstrakcja przecieka. Poleganie na narzędziu do budowania, które ma rozumieć intencje człowieka, wprowadza architektoniczną kruchość.
97
+
98
+ ### Kruchość heurystyczna (gra w zgadywanie)
99
+
100
+ Kompilator musi zgadywać, co jest treścią, a co kodem. Prowadzi to do sytuacji brzegowych, w których kończysz na „walce” z narzędziem.
101
+
102
+ Rozważ te scenariusze:
103
+
104
+ - Czy `<span className="active"></span>` jest wyodrębniane? (To jest string, ale prawdopodobnie klasa).
105
+ - Czy `<span status="pending"></span>` jest wyodrębniane? (To jest wartość propsa).
106
+ - Czy `<span>{"Hello World"}</span>` jest wyodrębniane? (To jest wyrażenie JS).
107
+ - Czy `<span>Hello {name}. How are you?</span>` jest wyodrębniane? (Interpolacja jest skomplikowana).
108
+ - Czy `<span aria-label="Image of cat"></span>` jest wyodrębniane? (Atrybuty dostępności wymagają tłumaczenia).
109
+ - Czy `<span data-testid="my-element"></span>` jest wyodrębniany? (ID testów NIE powinny być tłumaczone).
110
+ - Czy `<MyComponent errorMessage="An error occurred" />` jest wyodrębniany?
111
+ - Czy `<p>This is a paragraph{" "}\n containing multiple lines</p>` jest wyodrębniany?
112
+ - Czy wynik funkcji `<p>{getStatusMessage()}</p>` jest wyodrębniany?
113
+ - Czy `<div>{isLoading ? "The page is loading" : <MyComponent/>} </div>` jest wyodrębniany?
114
+ - Czy ID produktu takie jak `<span>AX-99</span>` jest wyodrębniany?
115
+
116
+ Nieuchronnie kończysz na dodawaniu specyficznych komentarzy (np. `// ignore-translation` lub specyficznych atrybutów jak `data-compiler-ignore="true"`) aby zapobiec łamaniu logiki Twojej aplikacji.
117
+
118
+ ### Jak Intlayer radzi sobie z tą złożonością?
63
119
 
64
- Chociaż „magia” jest kusząca, abstrakcja przecieka. Poleganie na narzędziu budującym, które ma rozumieć intencje człowieka, wprowadza architektoniczną kruchość.
120
+ Intlayer używa podejścia mieszanego do wykrywania, czy pole powinno zostać wyodrębnione do tłumaczenia, starając się zminimalizować fałszywe trafienia:
65
121
 
66
- ### 1. Kruchość Heurystyczna (Gra w Zgadywanie)
122
+ 1. **Analiza AST:** Sprawdza typ elementu (np. rozróżnia `reactNode`, `label` lub właściwość `title`).
123
+ 2. **Rozpoznawanie wzorców:** Wykrywa, czy ciąg znaków jest napisany wielką literą lub zawiera spacje, co sugeruje, że jest to prawdopodobnie tekst czytelny dla człowieka, a nie identyfikator kodu.
67
124
 
68
- Kompilator musi zgadnąć, co jest treścią, a co kodem.
125
+ ### Twardy limit danych dynamicznych
69
126
 
70
- - Czy `className="active"` jest tłumaczone? To jest string.
71
- - Czy `status="pending"` jest tłumaczone?
72
- - Czy `<MyComponent errorMessage="An error occurred" />` jest tłumaczone?
73
- - Czy identyfikator produktu taki jak `"AX-99"` jest tłumaczony?
127
+ Ekstrakcja przez kompilator opiera się na **analizie statycznej**. Musi zobaczyć dosłowny ciąg znaków w Twoim kodzie, aby wygenerować stabilny identyfikator.
128
+ Jeśli Twoje API zwraca ciąg znaków z kodem błędu, taki jak `server_error`, nie możesz go przetłumaczyć za pomocą kompilatora, ponieważ kompilator nie zna tego ciągu w czasie kompilacji. Jesteś zmuszony do zbudowania drugorzędnego systemu działającego wyłącznie w czasie wykonywania, przeznaczonego tylko dla danych dynamicznych.
74
129
 
75
- Nieuchronnie kończysz na „walce” z kompilatorem, dodając specyficzne komentarze (np. `// ignore-translation`), aby zapobiec złamaniu logiki twojej aplikacji.
130
+ ### Brak dzielenia na fragmenty
76
131
 
77
- ### 2. Twardy Limit Danych Dynamicznych
132
+ Niektóre kompilatory nie dzielą tłumaczeń na fragmenty na poziomie stron. Jeśli Twój kompilator generuje duży plik JSON na język (np. `./lang/en.json`, `./lang/fr.json` itd.), prawdopodobnie załadujesz zawartość ze wszystkich stron podczas odwiedzania jednej strony. Dodatkowo każdy komponent korzystający z Twoich treści zostanie prawdopodobnie zainicjowany z dużo większą ilością danych niż to konieczne, co może powodować problemy z wydajnością.
78
133
 
79
- Ekstrakcja przez kompilator opiera się na **analizie statycznej**. Musi zobaczyć dosłowny ciąg znaków w twoim kodzie, aby wygenerować stabilny identyfikator.
80
- Jeśli twoje API zwraca kod błędu w postaci ciągu znaków, np. `server_error`, nie możesz go przetłumaczyć za pomocą kompilatora, ponieważ kompilator nie wie o istnieniu tego ciągu w czasie budowania. Jesteś zmuszony do stworzenia drugiego systemu działającego tylko w czasie wykonywania, przeznaczonego wyłącznie dla danych dynamicznych.
134
+ Bądź również ostrożny przy dynamicznym ładowaniu tłumaczeń. Jeśli tego nie zrobisz, załadujesz zawartość dla wszystkich języków oprócz bieżącego.
81
135
 
82
- ### 3. „Eksplozja Fragmentów” i Kaskady Sieciowe
136
+ > Aby zobrazować problem, rozważ stronę z 10 podstronami i 10 językami (wszystkie w 100% unikalne). Załadujesz zawartość dla dodatkowych 99 podstron (10 × 10 - 1).
83
137
 
84
- Aby umożliwić tree-shaking, narzędzia kompilatora często dzielą tłumaczenia na poszczególne komponenty.
138
+ ### „Eksplozja chunków” i wodospady sieciowe
85
139
 
86
- - **Konsekwencja:** Pojedyncze wyświetlenie strony z 50 małymi komponentami może wywołać **50 oddzielnych żądań HTTP** dla drobnych fragmentów tłumaczeń. Nawet przy HTTP/2 tworzy to efekt wodospadu sieciowego, który sprawia, że Twoja aplikacja działa wolniej w porównaniu do załadowania pojedynczego, zoptymalizowanego pakietu językowego.
140
+ Aby rozwiązać problem chunkowania, niektóre rozwiązania oferują chunkowanie per komponent, a nawet per klucz. Jednak problem jest tylko częściowo rozwiązany. Głównym argumentem tych rozwiązań jest często stwierdzenie Twoja zawartość jest tree-shaken”.
87
141
 
88
- ### 4. Obciążenie wydajności w czasie wykonywania
142
+ Rzeczywiście, jeśli ładujesz zawartość statycznie, twoje rozwiązanie usunie nieużywaną zawartość (tree-shake), ale i tak skończysz z zawartością ze wszystkich języków załadowaną wraz z aplikacją.
89
143
 
90
- Aby tłumaczenia były reaktywne (tak, aby aktualizowały się natychmiast po zmianie języka), kompilator często wstrzykuje hooki zarządzania stanem do _każdego_ komponentu.
144
+ Więc dlaczego nie ładować go dynamicznie? Tak, w takim przypadku załadujesz więcej treści niż jest to konieczne, ale nie jest to pozbawione kompromisów.
91
145
 
92
- - **Koszt:** Jeśli renderujesz listę 5 000 elementów, inicjujesz 5 000 hooków `useState` i `useEffect` wyłącznie dla tekstu. Zużywa to pamięć i cykle CPU, które biblioteki deklaratywne (zazwyczaj używające pojedynczego dostawcy Context) oszczędzają.
146
+ Dynamiczne ładowanie treści izoluje każdą część treści w osobnym kawałku (chunku), który będzie ładowany tylko wtedy, gdy komponent zostanie wyrenderowany. Oznacza to, że wykonasz jedno żądanie HTTP na każdy blok tekstu. 1000 bloków tekstu na Twojej stronie? → 1000 żądań HTTP do Twoich serwerów. Aby ograniczyć szkody i zoptymalizować czas pierwszego renderowania aplikacji, będziesz musiał wstawić wiele granic Suspense lub Skeleton Loaderów.
147
+
148
+ > Uwaga: Nawet z Next.js i SSR, Twoje komponenty będą nadal hydradowane po załadowaniu, więc żądania HTTP nadal będą wykonywane.
149
+
150
+ Rozwiązanie? Przyjęcie rozwiązania, które pozwala deklarować zakresowe deklaracje treści, tak jak robią to `i18next`, `next-intl` lub `intlayer`.
151
+
152
+ > Uwaga: `i18next` i `next-intl` wymagają ręcznego zarządzania importami przestrzeni nazw / wiadomości dla każdej strony, aby zoptymalizować rozmiar pakietu. Powinieneś użyć analizatora pakietów, takiego jak `rollup-plugin-visualizer` (vite), `@next/bundle-analyzer` (next.js) lub `webpack-bundle-analyzer` (React CRA / Angular / itp.), aby wykryć, czy nie zaśmiecasz swojego pakietu nieużywanymi tłumaczeniami.
153
+
154
+ ### Obciążenie wydajności w czasie działania
155
+
156
+ Aby uczynić tłumaczenia reaktywnymi (tak, aby aktualizowały się natychmiast po zmianie języka), kompilator często wstrzykuje hooki zarządzania stanem do każdego komponentu.
157
+
158
+ - **Koszt:** Jeśli renderujesz listę 5 000 elementów, inicjujesz 5 000 hooków `useState` i `useEffect` wyłącznie dla tekstu. React musi zidentyfikować i ponownie wyrenderować wszystkich 5 000 konsumentów jednocześnie. Powoduje to ogromne zablokowanie "Głównego Wątku", zamrażając interfejs użytkownika podczas przełączania. Zużywa to pamięć i cykle CPU, które oszczędzają biblioteki deklaratywne (które zazwyczaj używają pojedynczego dostawcy Context).
159
+
160
+ > Uwaga: problematyka jest podobna w innych frameworkach niż React.
93
161
 
94
162
  ## Pułapka: Vendor Lock-in
95
163
 
96
- To prawdopodobnie najniebezpieczniejszy aspekt i18n opartego na kompilatorze.
164
+ Uważaj, aby wybrać rozwiązanie i18n, które pozwala na ekstrakcję lub migrację kluczy tłumaczeń.
97
165
 
98
- W bibliotece deklaratywnej Twój kod źródłowy zawiera wyraźny zamiar. Posiadasz klucze. Jeśli zmienisz bibliotekę, wystarczy, że zmienisz import.
166
+ W przypadku biblioteki deklaratywnej, Twój kod źródłowy wyraźnie zawiera zamiar tłumaczenia: to są Twoje klucze i masz nad nimi kontrolę. Jeśli chcesz zmienić bibliotekę, zazwyczaj wystarczy zaktualizować import.
99
167
 
100
- W podejściu opartym na kompilatorze, **Twój kod źródłowy to tylko tekst w języku angielskim.** „Logika tłumaczenia istnieje tylko w konfiguracji wtyczki build.
101
- Jeśli ta biblioteka przestanie być utrzymywana lub jeśli ją przerosniesz, utkniesz. Nie możesz łatwo „wyjść” z niej, ponieważ nie masz żadnych kluczy tłumaczeń w swoim kodzie źródłowym. Musiałbyś ręcznie przepisać całą aplikację, aby przejść na inne rozwiązanie.
168
+ W podejściu kompilatora, Twój kod źródłowy może być po prostu zwykłym tekstem angielskim, bez śladu logiki tłumaczenia: wszystko jest ukryte w konfiguracji narzędzia budującego. Jeśli ten plugin przestanie być utrzymywany lub chcesz zmienić rozwiązanie, możesz utknąć. Nie ma łatwego sposobu na „wyjście”: w Twoim kodzie nie ma użytecznych kluczy i może być konieczne ponowne wygenerowanie wszystkich tłumaczeń dla nowej biblioteki.
102
169
 
103
- ## Druga strona medalu: Ryzyka podejścia deklaratywnego
170
+ Niektóre rozwiązania oferują również usługi generowania tłumaczeń. Brak kredytów? Brak tłumaczeń.
104
171
 
105
- Aby być sprawiedliwym, tradycyjny sposób deklaratywny też nie jest idealny. Ma swoje własne „pułapki”.
172
+ Kompilatory często haszują tekst (np. `"Hello World"` -> `x7f2a`). Twoje pliki tłumaczeń wyglądają wtedy tak: `{ "x7f2a": "Hola Mundo" }`. Pułapka: jeśli zmienisz bibliotekę, nowa biblioteka widzi `"Hello World"` i szuka tego klucza. Nie znajdzie go, ponieważ Twój plik tłumaczeń jest pełen haszy (`x7f2a`).
106
173
 
107
- 1. **Piekło przestrzeni nazw:** Często musisz ręcznie zarządzać, które pliki JSON załadować (`common.json`, `dashboard.json`, `footer.json`). Jeśli zapomnisz o jednym, użytkownik zobaczy surowe klucze.
174
+ ### Uzależnienie od Platformy
175
+
176
+ Wybierając podejście oparte na kompilatorze, zamykasz się w podstawowej platformie. Na przykład, niektóre kompilatory nie są dostępne dla wszystkich bundlerów (takich jak Vite, Turbopack lub Metro). To może utrudnić przyszłe migracje i możesz potrzebować przyjąć wiele rozwiązań, aby pokryć wszystkie swoje aplikacje.
177
+
178
+ ## Druga Strona: Ryzyka Podejścia Deklaratywnego
179
+
180
+ Aby być sprawiedliwym, tradycyjny sposób deklaratywny też nie jest idealny. Ma swoje własne "pułapki".
181
+
182
+ 1. **Piekło przestrzeni nazw:** Często musisz ręcznie zarządzać, które pliki JSON ładować (`common.json`, `dashboard.json`, `footer.json`). Jeśli zapomnisz o którymś, użytkownik zobaczy surowe klucze.
108
183
  2. **Nadmierne pobieranie:** Bez ostrożnej konfiguracji bardzo łatwo jest przypadkowo załadować _wszystkie_ klucze tłumaczeń dla _wszystkich_ stron podczas początkowego ładowania, co powoduje nadmierne powiększenie rozmiaru paczki.
109
- 3. **Sync Drift:** Często zdarza się, że klucze pozostają w pliku JSON długo po usunięciu komponentu, który ich używał. Twoje pliki tłumaczeń rosną w nieskończoność, wypełnione zombie kluczami”.
184
+ 3. **Dryf synchronizacji:** Często zdarza się, że klucze pozostają w pliku JSON długo po usunięciu komponentu, który ich używał. Twoje pliki tłumaczeń rosną w nieskończoność, wypełnione "zombie kluczami".
110
185
 
111
- ## Środkowa Droga Intlayer
186
+ ## Środkowa droga Intlayer
112
187
 
113
- To właśnie tutaj narzędzia takie jak **Intlayer** próbują wprowadzać innowacje. Intlayer rozumie, że chociaż kompilatory są potężne, to ukryta magia jest niebezpieczna.
188
+ To właśnie tutaj narzędzia takie jak **Intlayer** próbują wprowadzać innowacje. Intlayer rozumie, że choć kompilatory są potężne, to ukryta magia jest niebezpieczna.
114
189
 
115
- Intlayer oferuje unikalne polecenie **`transform`**. Zamiast po prostu wykonywać magię w ukrytym kroku budowania, może faktycznie **przepisać kod twojego komponentu**. Skanuje twój tekst i zastępuje go jawnie zadeklarowaną zawartością w twojej bazie kodu.
190
+ Intlayer oferuje podejście mieszane, pozwalające korzystać z zalet obu metod: deklaratywnego zarządzania treścią, które jest również kompatybilne z jego kompilatorem, co oszczędza czas programowania.
191
+
192
+ A nawet jeśli nie używasz kompilatora Intlayer, Intlayer oferuje polecenie `transform` (dostępne również za pomocą rozszerzenia VSCode). Zamiast wykonywać magię w ukrytym kroku budowania, faktycznie może **przepisać kod twojego komponentu**. Skanuje twój tekst i zastępuje go jawnie zadeklarowanymi treściami w twojej bazie kodu.
116
193
 
117
194
  Daje to najlepsze z obu światów:
118
195
 
119
196
  1. **Szczegółowość:** Trzymasz tłumaczenia blisko swoich komponentów (poprawiając modularność i tree-shaking).
120
- 2. **Bezpieczeństwo:** Tłumaczenie staje się jawnie zapisanym kodem, a nie ukrytą magią podczas kompilacji.
121
- 3. **Brak uzależnienia:** Ponieważ kod jest przekształcany do standardowej, deklaratywnej struktury w Twoim repozytorium, nie ukrywasz logiki w wtyczce webpack.
197
+ 2. **Bezpieczeństwo:** Tłumaczenie staje się jawnie zapisanym kodem, a nie ukrytą magią podczas budowania.
198
+ 3. **Brak uzależnienia:** Ponieważ kod jest przekształcany w deklaratywną strukturę w twoim repozytorium, możesz łatwo nacisnąć tabulator lub użyć copilot w IDE, aby generować deklaracje treści, nie ukrywając logiki w wtyczce webpack.
122
199
 
123
- ## Podsumowanie
200
+ ## Wnioski
124
201
 
125
202
  Więc, którą opcję powinieneś wybrać?
126
203
 
127
- **Jeśli jesteś Junior Developerem, Samodzielnym Założycielem lub tworzysz MVP:**
128
- Podejście oparte na kompilatorze jest dobrym wyborem. Pozwala Ci działać niesamowicie szybko. Nie musisz martwić się strukturą plików ani kluczami. Po prostu budujesz. Dług techniczny to problem dla „Przyszłego Ciebie”.
204
+ **Jeśli tworzysz MVP lub chcesz działać szybko:**
205
+ Podejście oparte na kompilatorze jest dobrym wyborem. Pozwala na niezwykle szybkie działanie. Nie musisz się martwić o strukturę plików czy klucze. Po prostu budujesz. Dług techniczny to problem dla „Przyszłego Ciebie”.
206
+
207
+ **Jeśli jesteś Junior Developerem lub nie zależy Ci na optymalizacji:**
208
+ Jeśli chcesz jak najmniej ręcznego zarządzania, podejście oparte na kompilatorze jest prawdopodobnie najlepsze. Nie będziesz musiał samodzielnie obsługiwać kluczy czy plików tłumaczeń — po prostu piszesz tekst, a kompilator automatyzuje resztę. To zmniejsza nakład pracy przy konfiguracji i typowe błędy i18n związane z ręcznymi krokami.
209
+
210
+ **Jeśli internacjonalizujesz istniejący projekt, który już zawiera tysiące komponentów do refaktoryzacji:**
211
+ Podejście oparte na kompilatorze może być tutaj pragmatycznym wyborem. Początkowa faza ekstrakcji może zaoszczędzić tygodnie lub miesiące ręcznej pracy. Jednak rozważ użycie narzędzia takiego jak polecenie `transform` Intlayer, które może wyodrębnić ciągi znaków i przekształcić je w jawne deklaracje treści deklaratywnej. Daje to szybkość automatyzacji przy jednoczesnym zachowaniu bezpieczeństwa i przenośności podejścia deklaratywnego. Otrzymujesz to, co najlepsze z obu światów: szybką początkową migrację bez długoterminowego długu architektonicznego.
129
212
 
130
- **Jeśli tworzysz profesjonalną aplikację klasy enterprise:**
213
+ **Jeśli tworzysz profesjonalną aplikację klasy Enterprise:**
131
214
  Magia zazwyczaj jest złym pomysłem. Potrzebujesz kontroli.
132
215
 
133
216
  - Musisz obsługiwać dynamiczne dane z backendów.
134
- - Musisz zapewnić wydajność na urządzeniach o niskich parametrach (unikając eksplozji hooków).
135
- - Musisz upewnić się, że nie jesteś na stałe związany z konkretnym narzędziem do budowania.
217
+ - Musisz zapewnić wydajność na urządzeniach o niskiej wydajności (unikając eksplozji hooków).
218
+ - Musisz zapewnić, że nie zostaniesz na stałe związany z konkretnym narzędziem do budowania.
136
219
 
137
- W przypadku profesjonalnych aplikacji, **Deklaratywne Zarządzanie Treścią** (takie jak Intlayer lub uznane biblioteki) pozostaje złotym standardem. Oddziela Twoje obszary odpowiedzialności, utrzymuje czystą architekturę i zapewnia, że zdolność Twojej aplikacji do obsługi wielu języków nie zależy od „czarnej skrzynki” kompilatora, która zgaduje Twoje intencje.
220
+ Dla profesjonalnych aplikacji **Deklaratywne Zarządzanie Treścią** (takie jak Intlayer lub sprawdzone biblioteki) pozostaje złotym standardem. Oddziela to Twoje obszary odpowiedzialności, utrzymuje architekturę w czystości i zapewnia, że zdolność Twojej aplikacji do obsługi wielu języków nie zależy od „czarnej skrzynki” kompilatora, który zgaduje Twoje intencje.
@@ -2,7 +2,7 @@
2
2
  createdAt: 2025-11-24
3
3
  updatedAt: 2025-11-24
4
4
  title: Compilador vs. i18n Declarativo
5
- description: Explorando as trocas arquitetônicas entre a internacionalização "mágica" baseada em compilador e o gerenciamento explícito de conteúdo declarativo.
5
+ description: Explorando as compensações arquitetônicas entre a internacionalização "mágica" baseada em compilador e o gerenciamento explícito e declarativo de conteúdo.
6
6
  keywords:
7
7
  - Intlayer
8
8
  - Internacionalização
@@ -20,15 +20,19 @@ slugs:
20
20
 
21
21
  # O Caso a Favor e Contra a i18n Baseada em Compilador
22
22
 
23
- Se você tem construído aplicações web por mais de uma década, sabe que a Internacionalização (i18n) sempre foi um ponto de atrito. Frequentemente é a tarefa que ninguém quer fazer — extrair strings, gerenciar arquivos JSON e se preocupar com regras de pluralização.
23
+ Se você tem construído aplicações web por mais de uma década, sabe que a Internacionalização (i18n) sempre foi um ponto de atrito. Frequentemente, é a tarefa que ninguém quer fazer — extrair strings, gerenciar arquivos JSON e se preocupar com regras de pluralização.
24
24
 
25
- Recentemente, uma nova onda de ferramentas de i18n "baseadas em compilador" surgiu, prometendo fazer essa dor desaparecer. A proposta é sedutora: **Basta escrever o texto nos seus componentes e deixar a ferramenta de build cuidar do resto.** Sem chaves, sem imports, apenas magia.
25
+ Recentemente, uma nova onda de ferramentas de i18n **"baseadas em compilador"** surgiu, prometendo fazer essa dor desaparecer. A proposta é sedutora: **Basta escrever o texto nos seus componentes e deixar a ferramenta de build cuidar do resto.** Sem chaves, sem imports, apenas mágica.
26
26
 
27
- Mas, como em todas as abstrações na engenharia de software, magia tem um preço.
27
+ Mas, como em todas as abstrações na engenharia de software, mágica tem um preço.
28
28
 
29
- Neste post do blog, exploraremos a mudança das bibliotecas declarativas para abordagens baseadas em compilador, as dívidas arquitetônicas ocultas que elas introduzem e por que o jeito "chato" pode ainda ser o melhor para aplicações profissionais.
29
+ Neste post do blog, exploraremos a transição de bibliotecas declarativas para abordagens baseadas em compilador, as dívidas arquiteturais ocultas que elas introduzem e por que o jeito "chato" ainda pode ser o melhor para aplicações profissionais.
30
30
 
31
- ## Uma Breve História da Tradução
31
+ ## Índice
32
+
33
+ <TOC/>
34
+
35
+ ## Uma Breve História da Internacionalização
32
36
 
33
37
  Para entender onde estamos, precisamos olhar para onde começamos.
34
38
 
@@ -36,21 +40,49 @@ Por volta de 2011–2012, o cenário do JavaScript era muito diferente. Bundlers
36
40
 
37
41
  Elas resolveram o problema da única forma possível na época: **Dicionários em tempo de execução**. Você carregava um enorme objeto JSON na memória, e uma função buscava as chaves dinamicamente. Era confiável, explícito e funcionava em qualquer lugar.
38
42
 
39
- Avançando para hoje. Temos compiladores poderosos (SWC, bundlers baseados em Rust) que conseguem analisar Árvores de Sintaxe Abstrata (AST) em milissegundos. Esse poder deu origem a uma nova ideia: _Por que gerenciar chaves manualmente? Por que o compilador não pode simplesmente ver o texto "Hello World" e substituí-lo para nós?_
43
+ Avançando para hoje. Temos compiladores poderosos (SWC, bundlers baseados em Rust) que conseguem analisar Árvores de Sintaxe Abstrata (AST) em milissegundos. Esse poder deu origem a uma nova ideia: _Por que estamos gerenciando chaves manualmente? Por que o compilador não pode simplesmente ver o texto "Hello World" e substituí-lo para nós?_
40
44
 
41
45
  Assim, nasceu o i18n baseado em compilador.
42
46
 
47
+ > **Exemplo de i18n baseado em compilador:**
48
+ >
49
+ > - Paraglide (Módulos tree-shaken que compilam cada mensagem em uma pequena função ESM para que os bundlers possam eliminar automaticamente locais e chaves não utilizados. Você importa mensagens como funções em vez de fazer buscas por chaves de string.)
50
+ > - LinguiJS (Compilador de macro para função que reescreve macros de mensagem como `<Trans>` em chamadas de função JS simples durante o build. Você obtém a sintaxe ICU/MessageFormat com uma pegada de runtime muito pequena.)
51
+ > - Lingo.dev (Foca em automatizar o pipeline de localização injetando conteúdo traduzido diretamente durante a construção da sua aplicação React. Pode gerar traduções automaticamente usando IA e integrar-se diretamente ao CI/CD.)
52
+ > - Wuchale (Pré-processador focado em Svelte que extrai texto inline em arquivos .svelte e compila em funções de tradução sem wrappers. Evita chaves de string e separa completamente a lógica de extração de conteúdo do runtime principal da aplicação.)
53
+ > - Intlayer (Compilador / CLI de extração que analisa seus componentes, gera dicionários tipados e pode opcionalmente reescrever o código para usar conteúdo explícito do Intlayer. O objetivo é usar o compilador para velocidade mantendo um núcleo declarativo e agnóstico ao framework.)
54
+
55
+ > **Exemplo de i18n declarativo:**
56
+ >
57
+ > - i18next / react-i18next / next-i18next (O padrão maduro da indústria que usa dicionários JSON em runtime e um extenso ecossistema de plugins)
58
+ > - react-intl (Parte da biblioteca FormatJS, focada na sintaxe padrão de mensagens ICU e formatação rigorosa de dados)
59
+ > - next-intl (Otimizado especificamente para Next.js com integração para o App Router e React Server Components)
60
+ > - vue-i18n / @nuxt/i18n (A solução padrão do ecossistema Vue que oferece blocos de tradução a nível de componente e integração estreita com reatividade)
61
+ > - svelte-i18n (Um wrapper leve em torno dos stores do Svelte para traduções reativas em tempo de execução)
62
+ > - angular-translate (A biblioteca legada de tradução dinâmica que depende de buscas por chaves em tempo de execução ao invés de mesclagem em tempo de build)
63
+ > - angular-i18n (A abordagem nativa do Angular, ahead-of-time, que mescla arquivos XLIFF diretamente nos templates durante a build)
64
+ > - Tolgee (Combina código declarativo com um SDK em contexto para edição "click-to-translate" diretamente na interface)
65
+ > - Intlayer (Abordagem por componente, usando arquivos de declarações de conteúdo que permitem tree-shaking nativo e validação TypeScript)
66
+
67
+ ## O Compilador Intlayer
68
+
69
+ Embora o **Intlayer** seja uma solução que fundamentalmente incentiva uma **abordagem declarativa** para o seu conteúdo, ele inclui um compilador para ajudar a acelerar o desenvolvimento ou facilitar prototipagem rápida.
70
+
71
+ O compilador Intlayer percorre a AST (Abstract Syntax Tree) dos seus componentes React, Vue ou Svelte, assim como outros arquivos JavaScript/TypeScript. Seu papel é detectar strings hardcoded e extraí-las para declarações dedicadas `.content`.
72
+
73
+ > Para mais detalhes, consulte a documentação: [Documentação do Compilador Intlayer](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pt/compiler.md)
74
+
43
75
  ## O Encanto do Compilador (A Abordagem "Mágica")
44
76
 
45
77
  Há uma razão pela qual essa nova abordagem está em alta. Para um desenvolvedor, a experiência é incrível.
46
78
 
47
79
  ### 1. Velocidade e "Flow"
48
80
 
49
- Quando você está concentrado, parar para pensar em um nome de variável (`home_hero_title_v2`) quebra seu fluxo. Com a abordagem do compilador, você digita `<p>Welcome back</p>` e continua. O atrito é zero.
81
+ Quando você está concentrado, parar para pensar em um nome de variável semântico (`home_hero_title_v2`) quebra seu fluxo. Com a abordagem do compilador, você digita `<p>Welcome back</p>` e continua. O atrito é zero.
50
82
 
51
83
  ### 2. A Missão de Resgate do Legado
52
84
 
53
- Imagine herdar uma base de código enorme com 5.000 componentes e zero traduções. Adaptar isso para um sistema manual baseado em chaves é um pesadelo que dura meses. Uma ferramenta baseada em compilador atua como uma estratégia de resgate, extraindo instantaneamente milhares de strings sem que você precise tocar manualmente em um único arquivo.
85
+ Imagine herdar uma base de código enorme com 5.000 componentes e nenhuma tradução. Adaptar isso com um sistema manual baseado em chaves é um pesadelo que dura meses. Uma ferramenta baseada em compilador atua como uma estratégia de resgate, extraindo instantaneamente milhares de strings sem que você precise tocar em um único arquivo manualmente.
54
86
 
55
87
  ### 3. A Era da IA
56
88
 
@@ -59,79 +91,130 @@ Este é um benefício moderno que não devemos ignorar. Assistentes de codifica
59
91
  - **Declarativo:** Você precisa reescrever a saída da IA para substituir o texto por chaves.
60
92
  - **Compilador:** Você copia e cola o código da IA, e ele simplesmente funciona.
61
93
 
62
- ## A Verificação da Realidade: Por que a "Magia" é Perigosa
94
+ ## A Realidade: Por que a "Magia" é Perigosa
95
+
96
+ Embora a "mágica" seja atraente, a abstração apresenta vazamentos. Confiar em uma ferramenta de build para entender a intenção humana introduz fragilidade arquitetural.
97
+
98
+ ### Fragilidade Heurística (O Jogo de Adivinhação)
99
+
100
+ O compilador precisa adivinhar o que é conteúdo e o que é código. Isso leva a casos extremos onde você acaba "lutando" contra a ferramenta.
101
+
102
+ Considere estes cenários:
103
+
104
+ - `<span className="active"></span>` é extraído? (É uma string, mas provavelmente uma classe).
105
+ - `<span status="pending"></span>` é extraído? (É um valor de prop).
106
+ - `<span>{"Hello World"}</span>` é extraído? (É uma expressão JS).
107
+ - `<span>Hello {name}. How are you?</span>` é extraído? (Interpolação é complexa).
108
+ - `<span aria-label="Image of cat"></span>` é extraído? (Atributos de acessibilidade precisam de tradução).
109
+ - O `<span data-testid="my-element"></span>` é extraído? (IDs de teste NÃO devem ser traduzidos).
110
+ - O `<MyComponent errorMessage="An error occurred" />` é extraído?
111
+ - O `<p>This is a paragraph{" "}\n containing multiple lines</p>` é extraído?
112
+ - O resultado da função `<p>{getStatusMessage()}</p>` é extraído?
113
+ - O `<div>{isLoading ? "The page is loading" : <MyComponent/>} </div>` é extraído?
114
+ - Um ID de produto como `<span>AX-99</span>` é extraído?
115
+
116
+ Inevitavelmente, você acaba adicionando comentários específicos (como `// ignore-translation`, ou props específicas como `data-compiler-ignore="true"`) para evitar que isso quebre a lógica da sua aplicação.
117
+
118
+ ### Como o Intlayer lida com essa complexidade?
63
119
 
64
- Embora a "magia" seja atraente, a abstração apresenta vazamentos. Confiar em uma ferramenta de build para entender a intenção humana introduz fragilidade arquitetural.
120
+ Intlayer utiliza uma abordagem mista para detectar se um campo deve ser extraído para tradução, tentando minimizar falsos positivos:
65
121
 
66
- ### 1. Fragilidade Heurística (O Jogo de Adivinhação)
122
+ 1. **Análise AST:** Verifica o tipo do elemento (por exemplo, distinguindo entre um `reactNode`, um `label` ou uma prop `title`).
123
+ 2. **Reconhecimento de Padrões:** Detecta se a string está capitalizada ou inclui espaços, sugerindo que provavelmente é um texto legível por humanos e não um identificador de código.
67
124
 
68
- O compilador precisa adivinhar o que é conteúdo e o que é código.
125
+ ### O Limite Rígido para Dados Dinâmicos
69
126
 
70
- - `className="active"` é traduzido? É uma string.
71
- - `status="pending"` é traduzido?
72
- - O `<MyComponent errorMessage="An error occurred" />` é traduzido?
73
- - Um ID de produto como `"AX-99"` é traduzido?
127
+ A extração pelo compilador depende de **análise estática**. Ele deve ver a string literal no seu código para gerar um ID estável.
128
+ Se a sua API retornar uma string de código de erro como `server_error`, você não poderá traduzi-la com um compilador porque o compilador não sabe que essa string existe em tempo de build. Você será forçado a construir um sistema secundário "apenas em tempo de execução" apenas para dados dinâmicos.
74
129
 
75
- Inevitavelmente, você acaba "lutando" contra o compilador, adicionando comentários específicos (como `// ignore-translation`) para evitar que ele quebre a lógica da sua aplicação.
130
+ ### Falta de chunking
76
131
 
77
- ### 2. O Limite Rígido dos Dados Dinâmicos
132
+ Certos compiladores não fragmentam as traduções por página. Se o seu compilador gerar um arquivo JSON grande por idioma (por exemplo, `./lang/en.json`, `./lang/fr.json`, etc.), você provavelmente acabará carregando conteúdo de todas as suas páginas para uma única página visitada. Além disso, cada componente que usa seu conteúdo provavelmente será hidratado com muito mais conteúdo do que o necessário, o que pode causar problemas de desempenho.
78
133
 
79
- A extração pelo compilador depende de **análise estática**. Ele precisa ver a string literal no seu código para gerar um ID estável.
80
- Se sua API retorna uma string de código de erro como `server_error`, você não pode traduzi-la com um compilador porque ele não sabe que essa string existe em tempo de build. Você é forçado a construir um sistema secundário "apenas em tempo de execução" só para dados dinâmicos.
134
+ Também tenha cuidado ao carregar suas traduções dinamicamente. Se isso não for feito, você carregará conteúdo para todos os idiomas além do atual.
81
135
 
82
- ### 3. "Explosão de Chunks" e Cascatas de Rede
136
+ > Para ilustrar o problema, considere um site com 10 páginas e 10 idiomas (todos 100% únicos). Você carregaria conteúdo para 99 páginas adicionais (10 × 10 - 1).
83
137
 
84
- Para permitir tree-shaking, as ferramentas de compilação frequentemente dividem as traduções por componente.
138
+ ### "Explosão de Chunks" e Cascatas de Rede
85
139
 
86
- - **A Consequência:** Uma única visualização de página com 50 pequenos componentes pode disparar **50 requisições HTTP separadas** para pequenos fragmentos de tradução. Mesmo com HTTP/2, isso cria um efeito cascata na rede que faz sua aplicação parecer lenta em comparação ao carregamento de um único pacote de idioma otimizado.
140
+ Para resolver o problema do chunking, algumas soluções oferecem chunking por componente, ou até mesmo por chave. No entanto, o problema é apenas parcialmente resolvido. O argumento de venda dessas soluções é frequentemente dizer "Seu conteúdo é tree-shaken."
87
141
 
88
- ### 4. Sobrecarga de Performance em Tempo de Execução
142
+ De fato, se você carregar conteúdo estaticamente, sua solução fará tree-shake no conteúdo não utilizado, mas você ainda acabará com conteúdo de todos os idiomas carregado junto com sua aplicação.
89
143
 
90
- Para tornar as traduções reativas (para que atualizem instantaneamente quando você troca de idioma), o compilador frequentemente injeta hooks de gerenciamento de estado em _cada_ componente.
144
+ Então, por que não carregar dinamicamente? Sim, nesse caso você carregará mais conteúdo do que o necessário, mas isso não é sem compensações.
91
145
 
92
- - **O Custo:** Se você renderizar uma lista de 5.000 itens, estará inicializando 5.000 hooks `useState` e `useEffect` apenas para texto. Isso consome memória e ciclos de CPU que bibliotecas declarativas (que normalmente usam um único provedor Context) economizam.
146
+ Carregar conteúdo dinamicamente isola cada pedaço de conteúdo em seu próprio chunk, que só será carregado quando o componente for renderizado. Isso significa que você fará uma requisição HTTP por bloco de texto. 1.000 blocos de texto na sua página? → 1.000 requisições HTTP para seus servidores. E para limitar o impacto e otimizar o tempo de renderização inicial da sua aplicação, você precisará inserir múltiplos limites de Suspense ou Skeleton Loaders.
147
+
148
+ > Nota: Mesmo com Next.js e SSR, seus componentes ainda serão hidratados após o carregamento, então as requisições HTTP ainda serão feitas.
149
+
150
+ A solução? Adotar uma solução que permita declarar declarações de conteúdo com escopo, como fazem `i18next`, `next-intl` ou `intlayer`.
151
+
152
+ > Nota: `i18next` e `next-intl` exigem que você gerencie manualmente a importação dos namespaces / mensagens para cada página, a fim de otimizar o tamanho do seu bundle. Você deve usar um analisador de bundle como `rollup-plugin-visualizer` (vite), `@next/bundle-analyzer` (next.js) ou `webpack-bundle-analyzer` (React CRA / Angular / etc) para detectar se você está poluindo seu bundle com traduções não utilizadas.
153
+
154
+ ### Sobrecarga de Performance em Tempo de Execução
155
+
156
+ Para tornar as traduções reativas (para que atualizem instantaneamente quando você troca de idioma), o compilador frequentemente injeta hooks de gerenciamento de estado em cada componente.
157
+
158
+ - **O Custo:** Se você renderizar uma lista de 5.000 itens, estará inicializando 5.000 hooks `useState` e `useEffect` apenas para o texto. O React precisa identificar e re-renderizar todos os 5.000 consumidores simultaneamente. Isso causa um bloqueio massivo na "Main Thread", congelando a interface durante a troca. Isso consome memória e ciclos de CPU que bibliotecas declarativas (que normalmente usam um único provedor de Context) economizam.
159
+
160
+ > Note que o problema é semelhante para outros frameworks além do React.
93
161
 
94
162
  ## A Armadilha: Vendor Lock-in
95
163
 
96
- Este é, sem dúvida, o aspecto mais perigoso da i18n baseada em compilador.
164
+ Tenha cuidado ao escolher uma solução i18n que permita a extração ou migração das chaves de tradução.
97
165
 
98
- Em uma biblioteca declarativa, seu código-fonte contém a intenção explícita. Você possui as chaves. Se trocar de biblioteca, basta alterar a importação.
166
+ No caso de uma biblioteca declarativa, seu código-fonte contém explicitamente sua intenção de tradução: estas são suas chaves, e você as controla. Se quiser mudar de biblioteca, geralmente precisa atualizar a importação.
99
167
 
100
- Em uma abordagem baseada em compilador, **seu código-fonte é apenas texto em inglês.** A "lógica de tradução" existe apenas dentro da configuração do plugin de build.
101
- Se essa biblioteca deixar de ser mantida, ou se você ultrapassar suas limitações, ficará preso. Você não pode "ejetar" facilmente porque não há nenhuma chave de tradução no seu código-fonte. Você teria que reescrever manualmente toda a sua aplicação para migrar para outra solução.
168
+ Com uma abordagem de compilador, seu código-fonte pode ser apenas texto em inglês simples, sem nenhum vestígio da lógica de tradução: tudo está oculto na configuração da ferramenta de build. Se esse plugin deixar de ser mantido ou você quiser mudar de solução, pode ficar preso. Não há uma maneira fácil de "ejetar": não existem chaves utilizáveis no seu código, e você pode precisar re-gerar todas as suas traduções para uma nova biblioteca.
169
+
170
+ Algumas soluções também oferecem serviços de geração de tradução. Sem mais créditos? Sem mais traduções.
171
+
172
+ Os compiladores frequentemente fazem hash do texto (por exemplo, `"Hello World"` -> `x7f2a`). Seus arquivos de tradução ficam parecidos com `{ "x7f2a": "Hola Mundo" }`. A armadilha: se você trocar de biblioteca, a nova biblioteca vê `"Hello World"` e procura por essa chave. Ela não vai encontrar porque seu arquivo de tradução está cheio de hashes (`x7f2a`).
173
+
174
+ ### Bloqueio de Plataforma
175
+
176
+ Ao escolher uma abordagem baseada em compilador, você se prende à plataforma subjacente. Por exemplo, certos compiladores não estão disponíveis para todos os bundlers (como Vite, Turbopack ou Metro). Isso pode tornar as migrações futuras difíceis, e você pode precisar adotar múltiplas soluções para cobrir todas as suas aplicações.
102
177
 
103
178
  ## O Outro Lado: Riscos da Abordagem Declarativa
104
179
 
105
180
  Para ser justo, a forma tradicional declarativa também não é perfeita. Ela tem seu próprio conjunto de "armadilhas".
106
181
 
107
- 1. **Inferno dos Namespaces:** Frequentemente, você precisa gerenciar manualmente quais arquivos JSON carregar (`common.json`, `dashboard.json`, `footer.json`). Se esquecer algum, o usuário verá as chaves brutas.
108
- 2. **Carregamento Excessivo:** Sem uma configuração cuidadosa, é muito fácil carregar acidentalmente _todas_ as suas chaves de tradução para _todas_ as páginas no carregamento inicial, inchando o tamanho do seu bundle.
109
- 3. **Descompasso de Sincronização:** É comum que chaves permaneçam no arquivo JSON muito tempo depois do componente que as utiliza ter sido deletado. Seus arquivos de tradução crescem indefinidamente, cheios de "chaves zumbi".
182
+ 1. **Inferno dos Namespaces:** Você frequentemente precisa gerenciar manualmente quais arquivos JSON carregar (`common.json`, `dashboard.json`, `footer.json`). Se você esquecer algum, o usuário verá as chaves brutas.
183
+ 2. **Carregamento excessivo:** Sem uma configuração cuidadosa, é muito fácil carregar acidentalmente _todas_ as suas chaves de tradução para _todas_ as páginas no carregamento inicial, inchando o tamanho do seu bundle.
184
+ 3. **Desalinhamento de sincronização:** É comum que chaves permaneçam no arquivo JSON muito tempo depois do componente que as utiliza ter sido deletado. Seus arquivos de tradução crescem indefinidamente, cheios de "chaves zumbis".
110
185
 
111
- ## O Meio-Termo do Intlayer
186
+ ## O Meio-termo do Intlayer
112
187
 
113
- É aqui que ferramentas como o **Intlayer** estão tentando inovar. O Intlayer entende que, embora compiladores sejam poderosos, magia implícita é perigosa.
188
+ É aqui que ferramentas como o **Intlayer** estão tentando inovar. O Intlayer entende que, embora os compiladores sejam poderosos, a mágica implícita é perigosa.
114
189
 
115
- O Intlayer oferece um comando único chamado **`transform`**. Em vez de apenas fazer mágica na etapa oculta de build, ele pode realmente **reescrever o código do seu componente**. Ele escaneia seu texto e o substitui por declarações explícitas de conteúdo na sua base de código.
190
+ O Intlayer oferece uma abordagem mista, permitindo que você se beneficie das vantagens de ambas as abordagens: gerenciamento declarativo de conteúdo, também compatível com seu compilador para economizar tempo de desenvolvimento.
191
+
192
+ E mesmo que você não use o compilador Intlayer, o Intlayer oferece um comando `transform` (também acessível usando a extensão VSCode). Em vez de apenas fazer mágica na etapa oculta de build, ele pode realmente **reescrever o código do seu componente**. Ele escaneia seu texto e o substitui por declarações explícitas de conteúdo na sua base de código.
116
193
 
117
194
  Isso lhe dá o melhor dos dois mundos:
118
195
 
119
- 1. **Granularidade:** Você mantém suas traduções próximas aos seus componentes (melhorando modularidade e tree-shaking).
120
- 2. **Segurança:** A tradução torna-se código explícito, não uma mágica oculta em tempo de build.
121
- 3. **Sem Aprisionamento:** Como o código é transformado em uma estrutura declarativa padrão dentro do seu repositório, você não está escondendo lógica em um plugin do webpack.
196
+ 1. **Granularidade:** Você mantém suas traduções próximas aos seus componentes (melhorando a modularidade e o tree-shaking).
197
+ 2. **Segurança:** A tradução se torna código explícito, não mágica oculta em tempo de build.
198
+ 3. **Sem Lock-in:** Como o código é transformado em uma estrutura declarativa dentro do seu repositório, você pode facilmente pressionar tab, ou usar o copilot do seu IDE, para gerar suas declarações de conteúdo, sem esconder lógica em um plugin do webpack.
122
199
 
123
200
  ## Conclusão
124
201
 
125
202
  Então, qual você deve escolher?
126
203
 
127
- **Se você é um Desenvolvedor Júnior, um Fundador Solo ou está construindo um MVP:**
128
- A abordagem baseada em compilador é uma escolha válida. Ela permite que você avance incrivelmente rápido. Você não precisa se preocupar com estruturas de arquivos ou chaves. Você simplesmente constrói. A dívida técnica é um problema para o "Você do Futuro".
204
+ **Se você está construindo um MVP, ou quer avançar rapidamente:**
205
+ A abordagem baseada em compilador é uma escolha válida. Ela permite que você avance incrivelmente rápido. Você não precisa se preocupar com estruturas de arquivos ou chaves. Você apenas constrói. A dívida técnica é um problema para o "Você do Futuro".
206
+
207
+ **Se você é um Desenvolvedor Júnior, ou não se importa com otimização:**
208
+ Se você quer o mínimo de gerenciamento manual, uma abordagem baseada em compilador provavelmente é a melhor. Você não precisará lidar com chaves ou arquivos de tradução - apenas escreva o texto, e o compilador automatiza o resto. Isso reduz o esforço de configuração e os erros comuns de i18n ligados a etapas manuais.
209
+
210
+ **Se você está internacionalizando um projeto existente que já inclui milhares de componentes para refatorar:**
211
+ Uma abordagem baseada em compilador pode ser uma escolha pragmática aqui. A fase inicial de extração pode economizar semanas ou meses de trabalho manual. No entanto, considere usar uma ferramenta como o comando `transform` do Intlayer, que pode extrair strings e convertê-las em declarações explícitas de conteúdo declarativo. Isso oferece a velocidade da automação enquanto mantém a segurança e a portabilidade de uma abordagem declarativa. Você obtém o melhor dos dois mundos: migração inicial rápida sem dívida arquitetural a longo prazo.
129
212
 
130
213
  **Se você está construindo uma Aplicação Profissional, de Nível Empresarial:**
131
- Mágica geralmente é uma má ideia. Você precisa de controle.
214
+ Magia geralmente é uma má ideia. Você precisa de controle.
132
215
 
133
- - Você precisa lidar com dados dinâmicos provenientes de backends.
216
+ - Você precisa lidar com dados dinâmicos de backends.
134
217
  - Você precisa garantir desempenho em dispositivos de baixo custo (evitando explosões de hooks).
135
218
  - Você precisa garantir que não fique preso a uma ferramenta de build específica para sempre.
136
219
 
137
- Para aplicativos profissionais, **Gerenciamento Declarativo de Conteúdo** (como Intlayer ou bibliotecas consolidadas) continua sendo o padrão ouro. Ele separa suas preocupações, mantém sua arquitetura limpa e garante que a capacidade do seu aplicativo de falar múltiplos idiomas não dependa de um compilador "caixa preta" tentando adivinhar suas intenções.
220
+ Para aplicativos profissionais, o **Gerenciamento Declarativo de Conteúdo** (como Intlayer ou bibliotecas consolidadas) continua sendo o padrão ouro. Ele separa suas preocupações, mantém sua arquitetura limpa e garante que a capacidade do seu aplicativo de falar múltiplos idiomas não dependa de um compilador "caixa-preta" tentando adivinhar suas intenções.