@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.
@@ -20,89 +20,164 @@ slugs:
20
20
 
21
21
  # Argumen Mendukung dan Menentang i18n Berbasis Compiler
22
22
 
23
- Jika Anda telah membangun aplikasi web selama lebih dari satu dekade, Anda tahu bahwa Internasionalisasi (i18n) selalu menjadi titik gesekan. Ini sering menjadi tugas yang tidak ada yang ingin lakukan—mengekstrak string, mengelola file JSON, dan memikirkan aturan pluralisasi.
23
+ Jika Anda telah membangun aplikasi web selama lebih dari satu dekade, Anda tahu bahwa Internasionalisasi (i18n) selalu menjadi titik gesekan. Ini sering menjadi tugas yang tidak ingin dilakukan siapa pun—mengekstrak string, mengelola file JSON, dan khawatir tentang aturan pluralisasi.
24
24
 
25
- Baru-baru ini, gelombang baru alat i18n "berbasis Compiler" telah muncul, menjanjikan untuk menghilangkan rasa sakit ini. Janjinya menggoda: **Cukup tulis teks di komponen Anda, dan biarkan alat build yang mengurus sisanya.** Tidak perlu kunci, tidak perlu impor, hanya keajaiban.
25
+ Baru-baru ini, gelombang baru alat i18n **"Berbasis Compiler"** telah muncul, menjanjikan untuk menghilangkan rasa sakit ini. Janjinya menggoda: **Cukup tulis teks di komponen Anda, dan biarkan alat build yang mengurus sisanya.** Tidak perlu kunci, tidak perlu impor, hanya keajaiban.
26
26
 
27
27
  Namun seperti semua abstraksi dalam rekayasa perangkat lunak, keajaiban datang dengan harga.
28
28
 
29
- Dalam posting blog ini, kita akan mengeksplorasi pergeseran dari perpustakaan deklaratif ke pendekatan berbasis compiler, utang arsitektural tersembunyi yang mereka perkenalkan, dan mengapa cara "membosankan" mungkin masih menjadi cara terbaik untuk aplikasi profesional.
29
+ Dalam posting blog ini, kita akan mengeksplorasi pergeseran dari pustaka deklaratif ke pendekatan berbasis compiler, utang arsitektural tersembunyi yang mereka perkenalkan, dan mengapa cara yang "membosankan" mungkin masih menjadi cara terbaik untuk aplikasi profesional.
30
30
 
31
- ## Sejarah Singkat Terjemahan
31
+ ## Daftar Isi
32
32
 
33
- Untuk memahami di mana kita berada, kita harus melihat kembali dari mana kita memulai.
33
+ <TOC/>
34
34
 
35
- Sekitar tahun 2011–2012, lanskap JavaScript sangat berbeda. Bundler seperti yang kita kenal sekarang (Webpack, Vite) belum ada atau masih dalam tahap awal. Kita menggabungkan skrip langsung di browser. Pada era ini, perpustakaan seperti **i18next** lahir.
35
+ ## Sejarah Singkat Internasionalisasi
36
36
 
37
- Mereka memecahkan masalah dengan satu-satunya cara yang mungkin saat itu: **Kamus Runtime**. Anda memuat objek JSON besar ke dalam memori, dan sebuah fungsi mencari kunci secara langsung saat runtime. Ini dapat diandalkan, eksplisit, dan bekerja di mana saja.
37
+ Untuk memahami posisi kita saat ini, kita harus melihat kembali dari mana kita memulai.
38
+
39
+ Sekitar tahun 2011–2012, lanskap JavaScript sangat berbeda. Bundler seperti yang kita kenal sekarang (Webpack, Vite) belum ada atau masih dalam tahap awal. Saat itu, kita menyatukan skrip langsung di browser. Pada era ini, pustaka seperti **i18next** lahir.
40
+
41
+ Mereka memecahkan masalah dengan satu-satunya cara yang mungkin pada waktu itu: **Kamus Runtime**. Anda memuat objek JSON besar ke dalam memori, dan sebuah fungsi mencari kunci secara langsung saat runtime. Cara ini dapat diandalkan, eksplisit, dan bekerja di mana saja.
38
42
 
39
43
  Maju ke hari ini. Kita memiliki compiler yang kuat (SWC, bundler berbasis Rust) yang dapat mengurai Abstract Syntax Trees (AST) dalam hitungan milidetik. Kekuatan ini melahirkan ide baru: _Mengapa kita harus mengelola kunci secara manual? Mengapa compiler tidak langsung melihat teks "Hello World" dan menggantinya untuk kita?_
40
44
 
41
45
  Dengan demikian, i18n berbasis Compiler lahir.
42
46
 
47
+ > **Contoh i18n berbasis compiler:**
48
+ >
49
+ > - Paraglide (Modul tree-shaken yang mengompilasi setiap pesan menjadi fungsi ESM kecil sehingga bundler dapat secara otomatis menghapus locale dan kunci yang tidak digunakan. Anda mengimpor pesan sebagai fungsi daripada melakukan pencarian kunci string.)
50
+ > - LinguiJS (Compiler macro-ke-fungsi yang menulis ulang makro pesan seperti `<Trans>` menjadi panggilan fungsi JS biasa saat build. Anda mendapatkan sintaks ICU/MessageFormat dengan jejak runtime yang sangat kecil.)
51
+ > - Lingo.dev (Berfokus pada otomatisasi pipeline lokalisasi dengan menyuntikkan konten terjemahan langsung selama build aplikasi React Anda. Dapat menghasilkan terjemahan secara otomatis menggunakan AI dan terintegrasi langsung ke dalam CI/CD.)
52
+ > - Wuchale (Preprocessor yang mengutamakan Svelte yang mengekstrak teks inline dalam file .svelte dan mengompilasinya menjadi fungsi terjemahan tanpa pembungkus. Ini menghindari kunci string, dan memisahkan logika ekstraksi konten sepenuhnya dari runtime aplikasi utama.)
53
+ > - Intlayer (Compiler / Extract CLI yang mem-parsing komponen Anda, menghasilkan kamus bertipe, dan dapat secara opsional menulis ulang kode untuk menggunakan konten Intlayer secara eksplisit. Tujuannya adalah menggunakan compiler untuk kecepatan sambil menjaga inti yang deklaratif dan agnostik terhadap framework.)
54
+
55
+ > **Contoh i18n deklaratif:**
56
+ >
57
+ > - i18next / react-i18next / next-i18next (Standar industri matang yang menggunakan kamus JSON runtime dan ekosistem plugin yang luas)
58
+ > - react-intl (Bagian dari perpustakaan FormatJS, berfokus pada sintaks pesan ICU standar dan pemformatan data yang ketat)
59
+ > - next-intl (Dioptimalkan khusus untuk Next.js dengan integrasi untuk App Router dan React Server Components)
60
+ > - vue-i18n / @nuxt/i18n (Solusi ekosistem Vue standar yang menawarkan blok terjemahan tingkat komponen dan integrasi reaktivitas yang ketat)
61
+ > - svelte-i18n (Pembungkus ringan di sekitar Svelte stores untuk terjemahan reaktif saat runtime)
62
+ > - angular-translate (Perpustakaan terjemahan dinamis warisan yang mengandalkan pencarian kunci saat runtime daripada penggabungan saat build)
63
+ > - angular-i18n (Pendekatan asli Angular, ahead-of-time yang menggabungkan file XLIFF langsung ke dalam template selama build)
64
+ > - Tolgee (Menggabungkan kode deklaratif dengan SDK dalam konteks untuk pengeditan "klik-untuk-menerjemahkan" langsung di UI)
65
+ > - Intlayer (Pendekatan per-komponen, menggunakan file deklarasi konten yang memungkinkan tree-shaking native dan validasi TypeScript)
66
+
67
+ ## Kompiler Intlayer
68
+
69
+ Meskipun **Intlayer** adalah solusi yang secara fundamental mendorong **pendekatan deklaratif** untuk konten Anda, ia menyertakan kompiler untuk membantu mempercepat pengembangan atau memfasilitasi prototipe cepat.
70
+
71
+ Kompiler Intlayer menelusuri AST (Abstract Syntax Tree) dari komponen React, Vue, atau Svelte Anda, serta file JavaScript/TypeScript lainnya. Perannya adalah mendeteksi string yang dikodekan secara langsung dan mengekstraknya ke dalam deklarasi `.content` khusus.
72
+
73
+ > Untuk detail lebih lanjut, lihat dokumentasi: [Dokumentasi Compiler Intlayer](https://github.com/aymericzip/intlayer/blob/main/docs/docs/id/compiler.md)
74
+
43
75
  ## Daya Tarik Compiler (Pendekatan "Ajaib")
44
76
 
45
77
  Ada alasan mengapa pendekatan baru ini sedang tren. Bagi seorang developer, pengalamannya terasa luar biasa.
46
78
 
47
79
  ### 1. Kecepatan dan "Aliran"
48
80
 
49
- Saat Anda sedang fokus, berhenti untuk memikirkan nama variabel (`home_hero_title_v2`) akan memutus aliran kerja Anda. Dengan pendekatan compiler, Anda mengetik `<p>Welcome back</p>` dan terus melanjutkan. Hambatannya nol.
81
+ Saat Anda sedang fokus, berhenti untuk memikirkan nama variabel semantik (`home_hero_title_v2`) akan memutus aliran kerja Anda. Dengan pendekatan compiler, Anda mengetik `<p>Welcome back</p>` dan terus melanjutkan. Hambatan menjadi nol.
50
82
 
51
- ### 2. Misi Penyelamatan Warisan
83
+ ### 2. Misi Penyelamatan Legacy
52
84
 
53
- Bayangkan mewarisi codebase besar dengan 5.000 komponen dan tanpa terjemahan sama sekali. Memasang sistem berbasis kunci manual pada ini adalah mimpi buruk yang memakan waktu berbulan-bulan. Alat berbasis compiler bertindak sebagai strategi penyelamatan, langsung mengekstrak ribuan string tanpa Anda perlu menyentuh satu file pun secara manual.
85
+ Bayangkan mewarisi sebuah codebase besar dengan 5.000 komponen dan tanpa terjemahan sama sekali. Memodifikasi ini dengan sistem berbasis kunci manual adalah mimpi buruk yang memakan waktu berbulan-bulan. Alat berbasis compiler bertindak sebagai strategi penyelamatan, secara instan mengekstrak ribuan string tanpa Anda perlu menyentuh satu file pun secara manual.
54
86
 
55
87
  ### 3. Era AI
56
88
 
57
- Ini adalah manfaat modern yang tidak boleh kita abaikan. Asisten pengkodean AI (seperti Copilot atau ChatGPT) secara alami menghasilkan JSX/HTML standar. Mereka tidak mengetahui skema kunci terjemahan spesifik Anda.
89
+ Ini adalah keuntungan modern yang tidak boleh kita abaikan. Asisten pengkodean AI (seperti Copilot atau ChatGPT) secara alami menghasilkan JSX/HTML standar. Mereka tidak mengetahui skema kunci terjemahan spesifik Anda.
58
90
 
59
91
  - **Deklaratif:** Anda harus menulis ulang output AI untuk mengganti teks dengan kunci.
60
92
  - **Compiler:** Anda cukup menyalin-tempel kode AI, dan itu langsung bekerja.
61
93
 
62
- ## Pemeriksaan Realitas: Mengapa "Ajaib" Itu Berbahaya
94
+ ## Pemeriksaan Realitas: Mengapa "Magic" Berbahaya
63
95
 
64
- Meskipun "ajaib" itu menarik, abstraksi tersebut bisa bocor. Mengandalkan alat build untuk memahami niat manusia memperkenalkan kerentanan arsitektural.
96
+ Sementara "keajaiban" itu menarik, abstraksi tersebut bocor. Mengandalkan alat build untuk memahami niat manusia memperkenalkan kerentanan arsitektural.
65
97
 
66
- ### 1. Kerentanan Heuristik (Permainan Tebak-tebakan)
98
+ ### Kerentanan Heuristik (Permainan Tebak-tebakan)
67
99
 
68
- Compiler harus menebak mana yang konten dan mana yang kode.
100
+ Compiler harus menebak mana yang konten dan mana yang kode. Ini menyebabkan kasus-kasus tepi di mana Anda akhirnya "berjuang" dengan alat tersebut.
69
101
 
70
- - Apakah `className="active"` diterjemahkan? Itu adalah string.
71
- - Apakah `status="pending"` diterjemahkan?
72
- - Apakah `<MyComponent errorMessage="An error occurred" />` diterjemahkan?
73
- - Apakah ID produk seperti `"AX-99"` diterjemahkan?
102
+ Pertimbangkan skenario-skenario ini:
74
103
 
75
- Anda pada akhirnya harus "berjuang" dengan compiler, menambahkan komentar khusus (seperti `// ignore-translation`) untuk mencegahnya merusak logika aplikasi Anda.
104
+ - Apakah `<span className="active"></span>` diekstrak? (Ini adalah string, tapi kemungkinan kelas).
105
+ - Apakah `<span status="pending"></span>` diekstrak? (Ini adalah nilai prop).
106
+ - Apakah `<span>{"Hello World"}</span>` diekstrak? (Ini adalah ekspresi JS).
107
+ - Apakah `<span>Hello {name}. How are you?</span>` diekstrak? (Interpolasi itu kompleks).
108
+ - Apakah `<span aria-label="Image of cat"></span>` diekstrak? (Atribut aksesibilitas perlu diterjemahkan).
109
+ - Apakah `<span data-testid="my-element"></span>` diekstrak? (Test ID seharusnya TIDAK diterjemahkan).
110
+ - Apakah `<MyComponent errorMessage="An error occurred" />` diekstrak?
111
+ - Apakah `<p>This is a paragraph{" "}\n containing multiple lines</p>` diekstrak?
112
+ - Apakah hasil fungsi `<p>{getStatusMessage()}</p>` diekstrak?
113
+ - Apakah `<div>{isLoading ? "The page is loading" : <MyComponent/>} </div>` diekstrak?
114
+ - Apakah ID produk seperti `<span>AX-99</span>` diekstrak?
76
115
 
77
- ### 2. Batas Keras Data Dinamis
116
+ Anda pada akhirnya harus menambahkan komentar spesifik (seperti `// ignore-translation`, atau properti spesifik seperti `data-compiler-ignore="true"`) untuk mencegahnya merusak logika aplikasi Anda.
117
+
118
+ ### Bagaimana Intlayer menangani kompleksitas ini?
119
+
120
+ Intlayer menggunakan pendekatan campuran untuk mendeteksi apakah sebuah field harus diekstrak untuk terjemahan, dengan upaya meminimalkan false positives:
121
+
122
+ 1. **Analisis AST:** Memeriksa tipe elemen (misalnya, membedakan antara `reactNode`, `label`, atau properti `title`).
123
+ 2. **Pengenalan Pola:** Mendeteksi apakah string menggunakan huruf kapital atau mengandung spasi, yang menunjukkan kemungkinan besar itu adalah teks yang dapat dibaca manusia daripada sebuah identifier kode.
124
+
125
+ ### Batas Keras Data Dinamis
78
126
 
79
127
  Ekstraksi compiler bergantung pada **analisis statis**. Compiler harus melihat string literal dalam kode Anda untuk menghasilkan ID yang stabil.
80
- Jika API Anda mengembalikan string kode error seperti `server_error`, Anda tidak bisa menerjemahkannya dengan compiler karena compiler tidak mengetahui string tersebut ada saat build time. Anda terpaksa membangun sistem "runtime-only" sekunder hanya untuk data dinamis.
128
+ Jika API Anda mengembalikan string kode error seperti `server_error`, Anda tidak dapat menerjemahkannya dengan compiler karena compiler tidak mengetahui string tersebut ada saat waktu build. Anda terpaksa membangun sistem sekunder "hanya runtime" khusus untuk data dinamis.
129
+
130
+ ### Kekurangan Chunking
131
+
132
+ Beberapa compiler tidak melakukan chunking terjemahan per halaman. Jika compiler Anda menghasilkan file JSON besar per bahasa (misalnya, `./lang/en.json`, `./lang/fr.json`, dll.), Anda kemungkinan akan memuat konten dari semua halaman Anda untuk satu halaman yang dikunjungi saja. Selain itu, setiap komponen yang menggunakan konten Anda kemungkinan akan dihidrasikan dengan konten yang jauh lebih banyak dari yang diperlukan, yang berpotensi menyebabkan masalah performa.
133
+
134
+ Juga berhati-hatilah saat memuat terjemahan Anda secara dinamis. Jika ini tidak dilakukan, Anda akan memuat konten untuk semua bahasa selain bahasa saat ini.
81
135
 
82
- ### 3. "Ledakan Chunk" dan Air Terjun Jaringan
136
+ > Untuk mengilustrasikan masalah ini, pertimbangkan sebuah situs dengan 10 halaman dan 10 bahasa (semuanya 100% unik). Anda akan memuat konten untuk 99 halaman tambahan (10 × 10 - 1).
83
137
 
84
- Untuk memungkinkan tree-shaking, alat compiler sering membagi terjemahan per komponen.
138
+ ### "Ledakan Chunk" dan Jaringan Waterfall
85
139
 
86
- - **Konsekuensinya:** Satu tampilan halaman dengan 50 komponen kecil mungkin memicu **50 permintaan HTTP terpisah** untuk fragmen terjemahan kecil. Bahkan dengan HTTP/2, ini menciptakan waterfall jaringan yang membuat aplikasi Anda terasa lambat dibandingkan memuat satu bundel bahasa yang dioptimalkan.
140
+ Untuk mengatasi masalah chunking, beberapa solusi menawarkan chunking per komponen, atau bahkan per kunci. Namun masalah ini hanya teratasi sebagian. Keunggulan dari solusi ini sering kali dikatakan "Konten Anda di tree-shake."
87
141
 
88
- ### 4. Beban Kinerja Runtime
142
+ Memang, jika Anda memuat konten secara statis, solusi Anda akan melakukan tree-shake pada konten yang tidak digunakan, tetapi Anda tetap akan memuat konten dari semua bahasa bersama aplikasi Anda.
89
143
 
90
- Untuk membuat terjemahan bersifat reaktif (sehingga mereka langsung diperbarui saat Anda mengganti bahasa), compiler sering menyuntikkan hooks manajemen state ke _setiap_ komponen.
144
+ Jadi mengapa tidak memuatnya secara dinamis? Ya, dalam kasus ini Anda akan memuat lebih banyak konten daripada yang diperlukan, tetapi hal ini tidak tanpa kompromi.
91
145
 
92
- - **Biayanya:** Jika Anda merender daftar dengan 5.000 item, Anda menginisialisasi 5.000 hook `useState` dan `useEffect` hanya untuk teks. Ini menghabiskan memori dan siklus CPU yang sebenarnya bisa dihemat oleh pustaka deklaratif (yang biasanya menggunakan satu penyedia Context).
146
+ Memuat konten secara dinamis mengisolasi setiap potongan konten dalam chunk-nya sendiri, yang hanya akan dimuat saat komponen dirender. Ini berarti Anda akan membuat satu permintaan HTTP per blok teks. Ada 1.000 blok teks di halaman Anda? 1.000 permintaan HTTP ke server Anda. Dan untuk membatasi dampak serta mengoptimalkan waktu render pertama aplikasi Anda, Anda perlu menyisipkan beberapa batas Suspense atau Skeleton Loader.
147
+
148
+ > Catatan: Bahkan dengan Next.js dan SSR, komponen Anda masih akan dihidratasi setelah pemuatan, jadi permintaan HTTP tetap akan dilakukan.
149
+
150
+ Solusinya? Mengadopsi solusi yang memungkinkan deklarasi konten yang terlokalisasi, seperti yang dilakukan oleh `i18next`, `next-intl`, atau `intlayer`.
151
+
152
+ > Catatan: `i18next` dan `next-intl` mengharuskan Anda mengelola impor namespace / pesan secara manual untuk setiap halaman guna mengoptimalkan ukuran bundle Anda. Anda harus menggunakan alat analisis bundle seperti `rollup-plugin-visualizer` (vite), `@next/bundle-analyzer` (next.js), atau `webpack-bundle-analyzer` (React CRA / Angular / dll) untuk mendeteksi apakah Anda mencemari bundle Anda dengan terjemahan yang tidak digunakan.
153
+
154
+ ### Beban Kinerja Saat Runtime
155
+
156
+ Untuk membuat terjemahan menjadi reaktif (sehingga mereka langsung diperbarui saat Anda mengganti bahasa), compiler sering menyisipkan hooks manajemen state ke dalam setiap komponen.
157
+
158
+ - **Biaya:** Jika Anda merender daftar berisi 5.000 item, Anda menginisialisasi 5.000 hook `useState` dan `useEffect` hanya untuk teks. React harus mengidentifikasi dan merender ulang semua 5.000 konsumen secara bersamaan. Ini menyebabkan blok besar pada "Main Thread", membekukan UI selama pergantian bahasa. Ini menghabiskan memori dan siklus CPU yang sebenarnya bisa dihemat oleh pustaka deklaratif (yang biasanya menggunakan satu penyedia Context).
159
+
160
+ > Perlu dicatat bahwa masalah ini serupa pada framework lain selain React.
93
161
 
94
162
  ## Perangkap: Vendor Lock-in
95
163
 
96
- Ini mungkin aspek paling berbahaya dari i18n berbasis compiler.
164
+ Berhati-hatilah dalam memilih solusi i18n yang memungkinkan ekstraksi atau migrasi kunci terjemahan.
97
165
 
98
- Dalam pustaka deklaratif, kode sumber Anda mengandung maksud yang eksplisit. Anda memiliki kunci-kuncinya. Jika Anda mengganti pustaka, Anda hanya perlu mengubah impor.
166
+ Dalam kasus library deklaratif, kode sumber Anda secara eksplisit berisi maksud terjemahan Anda: ini adalah kunci Anda, dan Anda mengendalikannya. Jika Anda ingin mengganti library, umumnya Anda hanya perlu memperbarui impor.
99
167
 
100
- Dalam pendekatan berbasis compiler, **kode sumber Anda hanyalah teks bahasa Inggris.** "Logika terjemahan" hanya ada di dalam konfigurasi plugin build.
101
- Jika perpustakaan itu berhenti dipelihara, atau jika Anda merasa sudah tidak cocok lagi, Anda akan terjebak. Anda tidak bisa dengan mudah "eject" karena Anda tidak memiliki kunci terjemahan sama sekali di kode sumber Anda. Anda harus menulis ulang seluruh aplikasi secara manual untuk bermigrasi.
168
+ Dengan pendekatan compiler, kode sumber Anda mungkin hanya berupa teks bahasa Inggris biasa, tanpa jejak logika terjemahan: semuanya tersembunyi dalam konfigurasi alat build. Jika plugin tersebut tidak lagi dipelihara atau Anda ingin mengganti solusi, Anda bisa terjebak. Tidak ada cara mudah untuk "eject": tidak ada kunci yang dapat digunakan dalam kode Anda, dan Anda mungkin perlu menghasilkan ulang semua terjemahan untuk library baru.
169
+
170
+ Beberapa solusi juga menawarkan layanan pembuatan terjemahan. Tidak ada kredit lagi? Tidak ada terjemahan lagi.
171
+
172
+ Compiler sering kali meng-hash teks (misalnya, `"Hello World"` -> `x7f2a`). File terjemahan Anda akan terlihat seperti `{ "x7f2a": "Hola Mundo" }`. Perangkapnya: Jika Anda mengganti library, library baru akan melihat `"Hello World"` dan mencari kunci tersebut. Namun, ia tidak akan menemukannya karena file terjemahan Anda penuh dengan hash (`x7f2a`).
173
+
174
+ ### Keterikatan Platform
175
+
176
+ Dengan memilih pendekatan berbasis compiler, Anda mengikat diri pada platform yang mendasarinya. Misalnya, compiler tertentu tidak tersedia untuk semua bundler (seperti Vite, Turbopack, atau Metro). Ini dapat membuat migrasi di masa depan menjadi sulit, dan Anda mungkin perlu mengadopsi beberapa solusi untuk mencakup semua aplikasi Anda.
102
177
 
103
178
  ## Sisi Lain: Risiko dari Pendekatan Deklaratif
104
179
 
105
- Untuk adilnya, cara deklaratif tradisional juga tidak sempurna. Ia memiliki serangkaian "jebakan" tersendiri.
180
+ Sejujurnya, cara deklaratif tradisional juga tidak sempurna. Ia memiliki serangkaian "jebakan" tersendiri.
106
181
 
107
182
  1. **Namespace Hell:** Anda sering harus mengelola secara manual file JSON mana yang akan dimuat (`common.json`, `dashboard.json`, `footer.json`). Jika Anda lupa satu, pengguna akan melihat kunci mentah.
108
183
  2. **Over-fetching:** Tanpa konfigurasi yang hati-hati, sangat mudah secara tidak sengaja memuat _semua_ kunci terjemahan Anda untuk _semua_ halaman pada pemuatan awal, yang membuat ukuran bundle membengkak.
@@ -110,28 +185,36 @@ Untuk adilnya, cara deklaratif tradisional juga tidak sempurna. Ia memiliki sera
110
185
 
111
186
  ## Jalan Tengah Intlayer
112
187
 
113
- Di sinilah alat seperti **Intlayer** mencoba berinovasi. Intlayer memahami bahwa meskipun compiler itu kuat, sihir implisit itu berbahaya.
188
+ Di sinilah alat seperti **Intlayer** mencoba berinovasi. Intlayer memahami bahwa meskipun compiler sangat kuat, sihir implisit itu berbahaya.
114
189
 
115
- Intlayer menawarkan **perintah `transform`** yang unik. Alih-alih hanya melakukan sihir di langkah build tersembunyi, ia sebenarnya dapat **menulis ulang kode komponen Anda**. Ia memindai teks Anda dan menggantinya dengan deklarasi konten eksplisit di dalam codebase Anda.
190
+ Intlayer menawarkan pendekatan campuran, memungkinkan Anda mendapatkan keuntungan dari kedua pendekatan: manajemen konten deklaratif, yang juga kompatibel dengan compiler-nya untuk menghemat waktu pengembangan.
191
+
192
+ Dan bahkan jika Anda tidak menggunakan compiler Intlayer, Intlayer menawarkan perintah `transform` (juga dapat diakses menggunakan ekstensi VSCode). Alih-alih hanya melakukan magic di langkah build yang tersembunyi, perintah ini sebenarnya dapat **menulis ulang kode komponen Anda**. Ia memindai teks Anda dan menggantinya dengan deklarasi konten eksplisit di dalam codebase Anda.
116
193
 
117
194
  Ini memberi Anda yang terbaik dari kedua dunia:
118
195
 
119
196
  1. **Granularitas:** Anda menjaga terjemahan tetap dekat dengan komponen Anda (meningkatkan modularitas dan tree-shaking).
120
- 2. **Keamanan:** Terjemahan menjadi kode eksplisit, bukan sihir tersembunyi saat build-time.
121
- 3. **Tanpa Lock-in:** Karena kode diubah menjadi struktur deklaratif standar dalam repo Anda, Anda tidak menyembunyikan logika dalam plugin webpack.
197
+ 2. **Keamanan:** Terjemahan menjadi kode eksplisit, bukan magic tersembunyi saat build.
198
+ 3. **Tanpa Lock-in:** Karena kode diubah menjadi struktur deklaratif di dalam repo Anda, Anda dapat dengan mudah menekan tab, atau menggunakan copilot IDE Anda, untuk menghasilkan deklarasi konten Anda, Anda tidak menyembunyikan logika dalam plugin webpack.
122
199
 
123
200
  ## Kesimpulan
124
201
 
125
202
  Jadi, mana yang harus Anda pilih?
126
203
 
127
- **Jika Anda seorang Junior Developer, Solo Founder, atau sedang membangun MVP:**
204
+ **Jika Anda sedang membangun MVP, atau ingin bergerak cepat:**
128
205
  Pendekatan berbasis compiler adalah pilihan yang valid. Ini memungkinkan Anda bergerak sangat cepat. Anda tidak perlu khawatir tentang struktur file atau kunci. Anda hanya membangun. Hutang teknis adalah masalah untuk "Anda di Masa Depan."
129
206
 
130
- **Jika Anda membangun Aplikasi Profesional, Tingkat Enterprise:**
131
- Sihir umumnya adalah ide buruk. Anda membutuhkan kontrol.
207
+ **Jika Anda seorang Junior Developer, atau tidak peduli dengan optimasi:**
208
+ Jika Anda menginginkan manajemen manual yang paling sedikit, pendekatan berbasis compiler kemungkinan adalah yang terbaik. Anda tidak perlu menangani kunci atau file terjemahan sendiri—cukup tulis teks, dan compiler akan mengotomatisasi sisanya. Ini mengurangi usaha setup dan kesalahan i18n umum yang terkait dengan langkah manual.
209
+
210
+ **Jika Anda sedang menginternasionalkan proyek yang sudah ada yang sudah mencakup ribuan komponen untuk direfaktor:**
211
+ Pendekatan berbasis compiler bisa menjadi pilihan pragmatis di sini. Tahap ekstraksi awal dapat menghemat minggu atau bahkan bulan kerja manual. Namun, pertimbangkan untuk menggunakan alat seperti perintah `transform` dari Intlayer, yang dapat mengekstrak string dan mengubahnya menjadi deklarasi konten deklaratif yang eksplisit. Ini memberi Anda kecepatan otomatisasi sambil mempertahankan keamanan dan portabilitas pendekatan deklaratif. Anda mendapatkan yang terbaik dari kedua dunia: migrasi awal yang cepat tanpa utang arsitektur jangka panjang.
212
+
213
+ **Jika Anda membangun Aplikasi Profesional, Kelas Enterprise:**
214
+ Sihir umumnya adalah ide yang buruk. Anda membutuhkan kontrol.
132
215
 
133
216
  - Anda perlu menangani data dinamis dari backend.
134
217
  - Anda perlu memastikan performa pada perangkat kelas bawah (menghindari ledakan hook).
135
- - Anda perlu memastikan Anda tidak terkunci pada alat build tertentu selamanya.
218
+ - Anda perlu memastikan bahwa Anda tidak terkunci pada alat build tertentu untuk selamanya.
136
219
 
137
220
  Untuk aplikasi profesional, **Manajemen Konten Deklaratif** (seperti Intlayer atau pustaka yang sudah mapan) tetap menjadi standar emas. Ini memisahkan kekhawatiran Anda, menjaga arsitektur Anda tetap bersih, dan memastikan kemampuan aplikasi Anda untuk berbicara dalam berbagai bahasa tidak bergantung pada compiler "kotak hitam" yang menebak niat Anda.
@@ -1,8 +1,8 @@
1
1
  ---
2
2
  createdAt: 2025-11-24
3
3
  updatedAt: 2025-11-24
4
- title: Compilatore vs. i18n Dichiarativo
5
- description: Esplorazione dei compromessi architetturali tra l'internazionalizzazione "magica" basata su compilatore e la gestione esplicita e dichiarativa dei contenuti.
4
+ title: Compiler vs. i18n Dichiarativo
5
+ description: Esplorare i compromessi architetturali tra l'internazionalizzazione "magica" basata su compiler e la gestione esplicita e dichiarativa dei contenuti.
6
6
  keywords:
7
7
  - Intlayer
8
8
  - Internazionalizzazione
@@ -11,123 +11,206 @@ keywords:
11
11
  - JavaScript
12
12
  - React
13
13
  - i18n
14
- - Compilatore
14
+ - Compiler
15
15
  - Dichiarativo
16
16
  slugs:
17
17
  - blog
18
18
  - compiler-vs-declarative-i18n
19
19
  ---
20
20
 
21
- # Argomenti a favore e contro l'i18n basata su compilatore
21
+ # Argomenti a favore e contro l'i18n basato su Compiler
22
22
 
23
- Se sviluppi applicazioni web da più di un decennio, sai che l'Internazionalizzazione (i18n) è sempre stata un punto critico. Spesso è il compito che nessuno vuole fare: estrarre stringhe, gestire file JSON e preoccuparsi delle regole di pluralizzazione.
23
+ Se sviluppi applicazioni web da più di un decennio, sai che l'Internazionalizzazione (i18n) è sempre stata un punto di attrito. Spesso è il compito che nessuno vuole fare: estrarre stringhe, gestire file JSON e preoccuparsi delle regole di pluralizzazione.
24
24
 
25
- Recentemente, è emersa una nuova ondata di strumenti i18n "basati su compilatore", promettendo di far sparire questo fastidio. Il messaggio è seducente: **Basta scrivere il testo nei tuoi componenti e lasciare che lo strumento di build gestisca il resto.** Niente chiavi, niente importazioni, solo magia.
25
+ Recentemente, è emersa una nuova ondata di **strumenti i18n "basati su Compiler"**, promettendo di far sparire questo problema. Il messaggio è seducente: **Scrivi semplicemente il testo nei tuoi componenti e lascia che lo strumento di build si occupi del resto.** Niente chiavi, niente importazioni, solo magia.
26
26
 
27
27
  Ma come per tutte le astrazioni nell'ingegneria del software, la magia ha un prezzo.
28
28
 
29
- In questo post del blog, esploreremo il passaggio dalle librerie dichiarative agli approcci basati su compilatore, i debiti architetturali nascosti che introducono e perché il modo "noioso" potrebbe ancora essere il migliore per applicazioni professionali.
29
+ In questo post del blog, esploreremo il passaggio dalle librerie dichiarative agli approcci basati su compiler, i debiti architetturali nascosti che introducono e perché il modo "noioso" potrebbe ancora essere il migliore per applicazioni professionali.
30
30
 
31
- ## Una breve storia della traduzione
31
+ ## Indice
32
+
33
+ <TOC/>
34
+
35
+ ## Una breve storia dell'internazionalizzazione
32
36
 
33
37
  Per capire dove siamo, dobbiamo guardare indietro a dove siamo partiti.
34
38
 
35
- Intorno al 2011–2012, il panorama JavaScript era molto diverso. I bundler come li conosciamo oggi (Webpack, Vite) non esistevano o erano alle prime armi. Incollavamo gli script direttamente nel browser. In quell'epoca nacquero librerie come **i18next**.
39
+ Intorno al 2011–2012, il panorama JavaScript era molto diverso. I bundler come li conosciamo oggi (Webpack, Vite) non esistevano o erano alle prime fasi di sviluppo. Incollavamo gli script direttamente nel browser. In questo periodo nacquero librerie come **i18next**.
40
+
41
+ Risolvevano il problema nel modo unico possibile all'epoca: **Dizionari a Runtime**. Caricavi un enorme oggetto JSON in memoria, e una funzione cercava le chiavi al volo. Era affidabile, esplicito e funzionava ovunque.
42
+
43
+ Avanzando fino ad oggi, abbiamo potenti compiler (SWC, bundler basati su Rust) che possono analizzare Abstract Syntax Trees (AST) in millisecondi. Questa potenza ha dato vita a una nuova idea: _Perché gestiamo manualmente le chiavi? Perché il compiler non può semplicemente vedere il testo "Hello World" e sostituirlo per noi?_
44
+
45
+ Così nacque l'i18n basato su compiler.
46
+
47
+ > **Esempio di i18n basato su compiler:**
48
+ >
49
+ > - Paraglide (Moduli tree-shaken che compilano ogni messaggio in una piccola funzione ESM in modo che i bundler possano eliminare automaticamente le localizzazioni e le chiavi non utilizzate. Importi i messaggi come funzioni invece di fare ricerche con chiavi stringa.)
50
+ > - LinguiJS (Compiler da macro a funzione che riscrive le macro dei messaggi come `<Trans>` in normali chiamate di funzione JS al momento della build. Ottieni la sintassi ICU/MessageFormat con un footprint runtime molto ridotto.)
51
+ > - Lingo.dev (Si concentra sull'automatizzazione della pipeline di localizzazione iniettando contenuti tradotti direttamente durante la build della tua applicazione React. Può generare automaticamente traduzioni usando l'AI e integrarsi direttamente in CI/CD.)
52
+ > - Wuchale (Preprocessore orientato a Svelte che estrae il testo inline nei file .svelte e lo compila in funzioni di traduzione senza wrapper. Evita le chiavi stringa e separa completamente la logica di estrazione del contenuto dal runtime principale dell'applicazione.)
53
+ > - Intlayer (Compiler / CLI di estrazione che analizza i tuoi componenti, genera dizionari tipizzati e può opzionalmente riscrivere il codice per usare contenuti espliciti di Intlayer. L'obiettivo è usare il compiler per velocità mantenendo un core dichiarativo e agnostico rispetto al framework.)
54
+
55
+ > **Esempio di i18n dichiarativo:**
56
+ >
57
+ > - i18next / react-i18next / next-i18next (Lo standard maturo del settore che utilizza dizionari JSON a runtime e un ampio ecosistema di plugin)
58
+ > - react-intl (Parte della libreria FormatJS, focalizzata sulla sintassi standard dei messaggi ICU e sulla formattazione rigorosa dei dati)
59
+ > - next-intl (Ottimizzato specificamente per Next.js con integrazione per l'App Router e React Server Components)
60
+ > - vue-i18n / @nuxt/i18n (La soluzione standard dell'ecosistema Vue che offre blocchi di traduzione a livello di componente e una stretta integrazione con la reattività)
61
+ > - svelte-i18n (Un wrapper leggero attorno agli store di Svelte per traduzioni reattive a runtime)
62
+ > - angular-translate (La libreria di traduzione dinamica legacy che si basa sulla ricerca delle chiavi a runtime anziché sulla fusione a build-time)
63
+ > - angular-i18n (L'approccio nativo di Angular ahead-of-time che fonde i file XLIFF direttamente nei template durante la build)
64
+ > - Tolgee (Combina codice dichiarativo con un SDK in-context per la modifica "click-to-translate" direttamente nell'interfaccia utente)
65
+ > - Intlayer (Approccio per componente, utilizzando file di dichiarazioni di contenuto che abilitano tree-shaking nativo e validazione TypeScript)
66
+
67
+ ## Il Compilatore Intlayer
36
68
 
37
- Risolvevano il problema nel modo unico possibile all'epoca: **Dizionari a runtime**. Caricavi un enorme oggetto JSON in memoria, e una funzione cercava le chiavi al volo. Era affidabile, esplicito e funzionava ovunque.
69
+ Sebbene **Intlayer** sia una soluzione che incoraggia fondamentalmente un **approccio dichiarativo** ai tuoi contenuti, include un compilatore per aiutare ad accelerare lo sviluppo o facilitare il prototipaggio rapido.
38
70
 
39
- Avanzando fino a oggi, abbiamo potenti compilatori (SWC, bundler basati su Rust) che possono analizzare Abstract Syntax Trees (AST) in millisecondi. Questa potenza ha dato vita a una nuova idea: _Perché gestiamo manualmente le chiavi? Perché il compilatore non può semplicemente vedere il testo "Hello World" e sostituirlo per noi?_
71
+ Il compilatore Intlayer attraversa l'AST (Abstract Syntax Tree) dei tuoi componenti React, Vue o Svelte, così come altri file JavaScript/TypeScript. Il suo ruolo è rilevare le stringhe hardcoded ed estrarle in dichiarazioni `.content` dedicate.
40
72
 
41
- Così è nato l'i18n basato su compilatore.
73
+ > Per maggiori dettagli, consulta la documentazione: [Intlayer Compiler Docs](https://github.com/aymericzip/intlayer/blob/main/docs/docs/it/compiler.md)
42
74
 
43
- ## Il Fascino del Compilatore (L'Approccio "Magico")
75
+ ## Il Fascino del Compiler (L'Approccio "Magico")
44
76
 
45
77
  C'è un motivo per cui questo nuovo approccio è di tendenza. Per uno sviluppatore, l'esperienza è incredibile.
46
78
 
47
79
  ### 1. Velocità e "Flow"
48
80
 
49
- Quando sei nel flusso, fermarti a pensare a un nome di variabile (`home_hero_title_v2`) interrompe il tuo flusso. Con un approccio basato sul compilatore, digiti `<p>Welcome back</p>` e continui. L'attrito è zero.
81
+ Quando sei nel flusso, fermarti a pensare a un nome semantico per una variabile (`home_hero_title_v2`) interrompe il tuo flusso. Con un approccio basato su compiler, digiti `<p>Welcome back</p>` e continui. L'attrito è zero.
50
82
 
51
83
  ### 2. La Missione di Salvataggio del Legacy
52
84
 
53
- Immagina di ereditare una codebase enorme con 5.000 componenti e zero traduzioni. Retrofitare questo con un sistema manuale basato su chiavi è un incubo che dura mesi. Uno strumento basato su compilatore agisce come una strategia di salvataggio, estraendo istantaneamente migliaia di stringhe senza che tu debba toccare manualmente un singolo file.
85
+ Immagina di ereditare una codebase enorme con 5.000 componenti e zero traduzioni. Adattare questo con un sistema manuale basato su chiavi è un incubo che dura mesi. Uno strumento basato su compiler agisce come una strategia di salvataggio, estraendo istantaneamente migliaia di stringhe senza che tu debba toccare manualmente un singolo file.
54
86
 
55
87
  ### 3. L'Era dell'AI
56
88
 
57
89
  Questo è un vantaggio moderno che non dovremmo trascurare. Gli assistenti di codifica AI (come Copilot o ChatGPT) generano naturalmente JSX/HTML standard. Non conoscono il tuo schema specifico di chiavi di traduzione.
58
90
 
59
91
  - **Dichiarativo:** Devi riscrivere l'output dell'AI per sostituire il testo con le chiavi.
60
- - **Compilatore:** Copi e incolli il codice dell'AI, e funziona semplicemente.
92
+ - **Compiler:** Copi e incolli il codice dell'AI, e funziona semplicemente.
61
93
 
62
94
  ## Il Controllo della Realtà: Perché la "Magia" è Pericolosa
63
95
 
64
- Sebbene la "magia" sia attraente, l'astrazione perde colpi. Affidarsi a uno strumento di build per comprendere l'intento umano introduce fragilità architetturali.
96
+ Sebbene la "magia" sia allettante, l'astrazione presenta delle falle. Affidarsi a uno strumento di build per comprendere l'intento umano introduce fragilità architetturali.
65
97
 
66
- ### 1. Fragilità Euristica (Il Gioco delle Ipotesi)
98
+ ### Fragilità euristica (Il gioco delle ipotesi)
67
99
 
68
- Il compilatore deve indovinare cosa è contenuto e cosa è codice.
100
+ Il compilatore deve indovinare cosa è contenuto e cosa è codice. Questo porta a casi limite in cui finisci per "combattere" con lo strumento.
69
101
 
70
- - `className="active"` viene tradotto? È una stringa.
71
- - `status="pending"` viene tradotto?
72
- - `<MyComponent errorMessage="An error occurred" />` viene tradotto?
73
- - Un ID prodotto come `"AX-99"` viene tradotto?
102
+ Considera questi scenari:
74
103
 
75
- Inevitabilmente finisci per "combattere" con il compilatore, aggiungendo commenti specifici (come `// ignore-translation`) per evitare che rompa la logica della tua applicazione.
104
+ - Viene estratto `<span className="active"></span>`? una stringa, ma probabilmente una classe).
105
+ - Viene estratto `<span status="pending"></span>`? (È un valore di prop).
106
+ - Viene estratto `<span>{"Hello World"}</span>`? (È un'espressione JS).
107
+ - Viene estratto `<span>Hello {name}. How are you?</span>`? (L'interpolazione è complessa).
108
+ - Viene estratto `<span aria-label="Image of cat"></span>`? (Gli attributi di accessibilità necessitano traduzione).
109
+ - `<span data-testid="my-element"></span>` viene estratto? (Gli ID di test NON devono essere tradotti).
110
+ - `<MyComponent errorMessage="An error occurred" />` viene estratto?
111
+ - `<p>This is a paragraph{" "}\n containing multiple lines</p>` viene estratto?
112
+ - Il risultato della funzione `<p>{getStatusMessage()}</p>` viene estratto?
113
+ - `<div>{isLoading ? "The page is loading" : <MyComponent/>} </div>` viene estratto?
114
+ - Un ID prodotto come `<span>AX-99</span>` viene estratto?
76
115
 
77
- ### 2. Il Limite Rigido dei Dati Dinamici
116
+ Inevitabilmente si finisce per aggiungere commenti specifici (come `// ignore-translation`, o proprietà specifiche come `data-compiler-ignore="true"`) per evitare che ciò comprometta la logica della tua applicazione.
117
+
118
+ ### Come gestisce Intlayer questa complessità?
119
+
120
+ Intlayer utilizza un approccio misto per rilevare se un campo deve essere estratto per la traduzione, cercando di minimizzare i falsi positivi:
121
+
122
+ 1. **Analisi AST:** Controlla il tipo di elemento (ad esempio, distinguendo tra un `reactNode`, un `label` o una prop `title`).
123
+ 2. **Riconoscimento di pattern:** Rileva se la stringa è maiuscola o include spazi, suggerendo che probabilmente si tratta di testo leggibile dall'utente piuttosto che di un identificatore di codice.
124
+
125
+ ### Il limite massimo per i dati dinamici
78
126
 
79
127
  L'estrazione del compilatore si basa sull'**analisi statica**. Deve vedere la stringa letterale nel tuo codice per generare un ID stabile.
80
- Se la tua API restituisce una stringa di codice errore come `server_error`, non puoi tradurla con un compilatore perché il compilatore non conosce quella stringa al momento della build. Sei costretto a costruire un sistema secondario "solo a runtime" solo per i dati dinamici.
128
+ Se la tua API restituisce una stringa di codice errore come `server_error`, non puoi tradurla con un compilatore perché il compilatore non sa che quella stringa esiste al momento della build. Sei costretto a costruire un sistema secondario "solo a runtime" esclusivamente per i dati dinamici.
129
+
130
+ ### Mancanza di suddivisione in chunk
131
+
132
+ Alcuni compilatori non suddividono le traduzioni per pagina. Se il tuo compilatore genera un grande file JSON per lingua (ad esempio, `./lang/en.json`, `./lang/fr.json`, ecc.), probabilmente finirai per caricare il contenuto di tutte le tue pagine per una singola pagina visitata. Inoltre, ogni componente che utilizza il tuo contenuto sarà probabilmente idratato con molto più contenuto del necessario, causando potenzialmente problemi di performance.
133
+
134
+ Fai anche attenzione a caricare le tue traduzioni dinamicamente. Se questo non viene fatto, caricherai contenuti per tutte le lingue oltre a quella corrente.
81
135
 
82
- ### 3. "Esplosione di Chunk" e Cascate di Rete
136
+ > Per illustrare il problema, considera un sito con 10 pagine e 10 lingue (tutte al 100% uniche). Caricheresti contenuti per 99 pagine aggiuntive (10 × 10 - 1).
83
137
 
84
- Per consentire il tree-shaking, gli strumenti del compilatore spesso suddividono le traduzioni per componente.
138
+ ### "Esplosione di chunk" e Network Waterfalls
85
139
 
86
- - **La conseguenza:** Una singola visualizzazione di pagina con 50 piccoli componenti potrebbe generare **50 richieste HTTP separate** per minuscoli frammenti di traduzione. Anche con HTTP/2, questo crea un effetto "network waterfall" che rende la tua applicazione lenta rispetto al caricamento di un singolo bundle linguistico ottimizzato.
140
+ Per risolvere il problema del chunking, alcune soluzioni offrono il chunking per componente, o addirittura per chiave. Tuttavia, il problema è solo parzialmente risolto. Il punto di forza di queste soluzioni è spesso dire "Il tuo contenuto è tree-shaken."
87
141
 
88
- ### 4. Sovraccarico delle Prestazioni a Runtime
142
+ Infatti, se carichi contenuti staticamente, la tua soluzione eliminerà tramite tree-shaking i contenuti inutilizzati, ma finirai comunque per avere contenuti di tutte le lingue caricati con la tua applicazione.
89
143
 
90
- Per rendere le traduzioni reattive (in modo che si aggiornino istantaneamente quando cambi lingua), il compilatore spesso inietta hook di gestione dello stato in _ogni_ componente.
144
+ Allora perché non caricarlo dinamicamente? Sì, in quel caso caricherai più contenuti del necessario, ma non è senza compromessi.
91
145
 
92
- - **Il costo:** Se renderizzi una lista di 5.000 elementi, stai inizializzando 5.000 hook `useState` e `useEffect` solo per il testo. Questo consuma memoria e cicli CPU che le librerie dichiarative (che tipicamente usano un singolo provider Context) risparmiano.
146
+ Caricare i contenuti dinamicamente isola ogni pezzo di contenuto nel proprio chunk, che verrà caricato solo quando il componente viene renderizzato. Questo significa che farai una richiesta HTTP per ogni blocco di testo. 1.000 blocchi di testo nella tua pagina? → 1.000 richieste HTTP ai tuoi server. E per limitare i danni e ottimizzare il tempo di primo rendering della tua applicazione, dovrai inserire più confini di Suspense o Skeleton Loaders.
147
+
148
+ > Nota: Anche con Next.js e SSR, i tuoi componenti verranno comunque idratati dopo il caricamento, quindi le richieste HTTP verranno comunque effettuate.
149
+
150
+ La soluzione? Adottare una soluzione che consenta di dichiarare contenuti con ambito limitato, come fanno `i18next`, `next-intl` o `intlayer`.
151
+
152
+ > Nota: `i18next` e `next-intl` richiedono di gestire manualmente l'importazione dei namespace / messaggi per ogni pagina per ottimizzare la dimensione del bundle. Dovresti utilizzare un analizzatore di bundle come `rollup-plugin-visualizer` (vite), `@next/bundle-analyzer` (next.js) o `webpack-bundle-analyzer` (React CRA / Angular / ecc.) per rilevare se stai inquinando il tuo bundle con traduzioni inutilizzate.
153
+
154
+ ### Sovraccarico delle Prestazioni a Runtime
155
+
156
+ Per rendere le traduzioni reattive (così si aggiornano istantaneamente quando cambi lingua), il compilatore spesso inietta hook di gestione dello stato in ogni componente.
157
+
158
+ - **Il costo:** Se renderizzi una lista di 5.000 elementi, stai inizializzando 5.000 hook `useState` e `useEffect` solo per il testo. React deve identificare e ri-renderizzare simultaneamente tutti e 5.000 i consumatori. Questo causa un enorme blocco del "Main Thread", congelando l'interfaccia utente durante il cambio. Questo consuma memoria e cicli CPU che le librerie dichiarative (che tipicamente usano un singolo provider Context) risparmiano.
159
+
160
+ > Nota che il problema è simile anche per altri framework oltre a React.
93
161
 
94
162
  ## La trappola: Vendor Lock-in
95
163
 
96
- Questo è probabilmente l'aspetto più pericoloso dell'i18n basato su compilatori.
164
+ Fai attenzione a scegliere una soluzione i18n che permetta l'estrazione o la migrazione delle chiavi di traduzione.
97
165
 
98
- In una libreria dichiarativa, il tuo codice sorgente contiene un intento esplicito. Possiedi le chiavi. Se cambi libreria, devi solo modificare l'import.
166
+ Nel caso di una libreria dichiarativa, il tuo codice sorgente contiene esplicitamente la tua intenzione di traduzione: queste sono le tue chiavi, e le controlli tu. Se vuoi cambiare libreria, generalmente devi solo aggiornare l'import.
99
167
 
100
- In un approccio basato su compilatori, **il tuo codice sorgente è solo testo in inglese.** La "logica di traduzione" esiste solo all'interno della configurazione del plugin di build.
101
- Se quella libreria smette di essere mantenuta, o se la superi, rimani bloccato. Non puoi "espellere" facilmente perché non hai chiavi di traduzione nel tuo codice sorgente. Dovresti riscrivere manualmente l'intera applicazione per migrare.
168
+ Con un approccio basato su un compilatore, il tuo codice sorgente potrebbe essere solo testo in inglese semplice, senza traccia della logica di traduzione: tutto è nascosto nella configurazione dello strumento di build. Se quel plugin non viene più mantenuto o vuoi cambiare soluzione, potresti rimanere bloccato. Non c'è un modo semplice per "estrarre": non ci sono chiavi utilizzabili nel tuo codice, e potresti dover rigenerare tutte le tue traduzioni per una nuova libreria.
169
+
170
+ Alcune soluzioni offrono anche servizi di generazione delle traduzioni. Finiscono i crediti? Finiscono le traduzioni.
171
+
172
+ I compilatori spesso hashano il testo (ad esempio, `"Hello World"` -> `x7f2a`). I tuoi file di traduzione appaiono come `{ "x7f2a": "Hola Mundo" }`. La trappola: se cambi libreria, la nuova libreria vede `"Hello World"` e cerca quella chiave. Non la troverà perché il tuo file di traduzione è pieno di hash (`x7f2a`).
173
+
174
+ ### Dipendenza dalla Piattaforma
175
+
176
+ Scegliendo un approccio basato su compilatore, ti leghi alla piattaforma sottostante. Ad esempio, alcuni compilatori non sono disponibili per tutti i bundler (come Vite, Turbopack o Metro). Questo può rendere difficili le migrazioni future e potresti dover adottare più soluzioni per coprire tutte le tue applicazioni.
102
177
 
103
178
  ## L'altro lato: rischi dell'approccio dichiarativo
104
179
 
105
- Per essere onesti, il modo dichiarativo tradizionale non è perfetto nemmeno. Ha i suoi "tranelli".
180
+ Per essere onesti, anche il modo dichiarativo tradizionale non è perfetto. Ha i suoi "colpi mancini".
106
181
 
107
182
  1. **Inferno dei namespace:** Spesso devi gestire manualmente quali file JSON caricare (`common.json`, `dashboard.json`, `footer.json`). Se ne dimentichi uno, l'utente vede le chiavi raw.
108
- 2. **Over-fetching:** Senza una configurazione attenta, è molto facile caricare accidentalmente _tutte_ le tue chiavi di traduzione per _tutte_ le pagine al caricamento iniziale, gonfiando la dimensione del bundle.
109
- 3. **Deriva di sincronizzazione:** È comune che le chiavi rimangano nel file JSON molto tempo dopo che il componente che le utilizzava è stato eliminato. I tuoi file di traduzione crescono indefinitamente, pieni di "chiavi zombie".
183
+ 2. **Over-fetching:** Senza una configurazione attenta, è molto facile caricare accidentalmente _tutte_ le tue chiavi di traduzione per _tutte_ le pagine al caricamento iniziale, gonfiando la dimensione del tuo bundle.
184
+ 3. **Sync Drift:** È comune che le chiavi rimangano nel file JSON molto tempo dopo che il componente che le utilizzava è stato eliminato. I tuoi file di traduzione crescono indefinitamente, pieni di "chiavi zombie".
110
185
 
111
- ## La via di mezzo di Intlayer
186
+ ## Il Giusto Mezzo di Intlayer
112
187
 
113
188
  È qui che strumenti come **Intlayer** cercano di innovare. Intlayer comprende che, sebbene i compilatori siano potenti, la magia implicita è pericolosa.
114
189
 
115
- Intlayer offre un comando unico **`transform`**. Invece di fare solo magia nel passaggio di build nascosto, può effettivamente **riscrivere il codice del tuo componente**. Scansiona il tuo testo e lo sostituisce con dichiarazioni di contenuto esplicite nel tuo codebase.
190
+ Intlayer offre un approccio misto, permettendoti di beneficiare dei vantaggi di entrambi gli approcci: gestione dichiarativa dei contenuti, anche compatibile con il suo compilatore per risparmiare tempo di sviluppo.
191
+
192
+ E anche se non usi il compilatore Intlayer, Intlayer offre un comando `transform` (accessibile anche tramite l'estensione VSCode). Invece di fare solo magia nel passaggio di build nascosto, può effettivamente **riscrivere il codice del tuo componente**. Scansiona il tuo testo e lo sostituisce con dichiarazioni di contenuto esplicite nel tuo codebase.
116
193
 
117
194
  Questo ti offre il meglio di entrambi i mondi:
118
195
 
119
- 1. **Granularità:** Mantieni le tue traduzioni vicine ai tuoi componenti (migliorando modularità e tree-shaking).
120
- 2. **Sicurezza:** La traduzione diventa codice esplicito, non una magia nascosta al momento della build.
121
- 3. **Nessun Lock-in:** Poiché il codice viene trasformato in una struttura dichiarativa standard all'interno del tuo repository, non stai nascondendo la logica in un plugin di webpack.
196
+ 1. **Granularità:** Mantieni le tue traduzioni vicine ai tuoi componenti (migliorando la modularità e il tree-shaking).
197
+ 2. **Sicurezza:** La traduzione diventa codice esplicito, non magia nascosta a tempo di build.
198
+ 3. **Nessun Lock-in:** Poiché il codice viene trasformato in una struttura dichiarativa all'interno del tuo repository, puoi facilmente premere tab, o usare il copilot del tuo IDE, per generare le tue dichiarazioni di contenuto, senza nascondere logica in un plugin webpack.
122
199
 
123
200
  ## Conclusione
124
201
 
125
202
  Quindi, quale dovresti scegliere?
126
203
 
127
- **Se sei uno Sviluppatore Junior, un Fondatore Solitario o stai costruendo un MVP:**
128
- L'approccio basato sul compilatore è una scelta valida. Ti permette di muoverti incredibilmente velocemente. Non devi preoccuparti delle strutture dei file o delle chiavi. Devi solo costruire. Il debito tecnico è un problema per il "Te Futuro".
204
+ **Se stai costruendo un MVP, o vuoi muoverti rapidamente:**
205
+ L'approccio basato sul compilatore è una scelta valida. Ti permette di muoverti incredibilmente velocemente. Non devi preoccuparti della struttura dei file o delle chiavi. Devi solo costruire. Il debito tecnico sarà un problema per il "Te futuro".
206
+
207
+ **Se sei uno sviluppatore junior, o non ti interessa l'ottimizzazione:**
208
+ Se vuoi la gestione manuale minima, un approccio basato sul compilatore è probabilmente il migliore. Non dovrai gestire tu stesso chiavi o file di traduzione—scrivi semplicemente il testo, e il compilatore automatizza il resto. Questo riduce lo sforzo di configurazione e gli errori comuni di i18n legati ai passaggi manuali.
209
+
210
+ **Se stai internazionalizzando un progetto esistente che include già migliaia di componenti da rifattorizzare:**
211
+ Un approccio basato sul compilatore può essere una scelta pragmatica in questo caso. La fase iniziale di estrazione può far risparmiare settimane o mesi di lavoro manuale. Tuttavia, considera l'uso di uno strumento come il comando `transform` di Intlayer, che può estrarre le stringhe e convertirle in dichiarazioni di contenuto dichiarativo esplicite. Questo ti offre la velocità dell'automazione mantenendo la sicurezza e la portabilità di un approccio dichiarativo. Ottieni il meglio di entrambi i mondi: una migrazione iniziale rapida senza debito architetturale a lungo termine.
129
212
 
130
- **Se stai costruendo un'Applicazione Professionale di livello Enterprise:**
213
+ **Se stai costruendo un'applicazione professionale di livello enterprise:**
131
214
  La magia è generalmente una cattiva idea. Hai bisogno di controllo.
132
215
 
133
216
  - Devi gestire dati dinamici provenienti dai backend.