@intlayer/docs 8.6.10 → 8.7.0-canary.1

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.
Files changed (129) hide show
  1. package/blog/ar/i18n_using_next-i18next.md +1 -1
  2. package/blog/ar/next-i18next_vs_next-intl_vs_intlayer.md +2 -2
  3. package/blog/de/i18n_using_next-i18next.md +1 -1
  4. package/blog/de/next-i18next_vs_next-intl_vs_intlayer.md +2 -2
  5. package/blog/en/i18n_using_next-i18next.md +1 -1
  6. package/blog/en/next-i18next_vs_next-intl_vs_intlayer.md +2 -2
  7. package/blog/en-GB/i18n_using_next-i18next.md +1 -1
  8. package/blog/en-GB/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  9. package/blog/es/i18n_using_next-i18next.md +1 -1
  10. package/blog/es/next-i18next_vs_next-intl_vs_intlayer.md +2 -2
  11. package/blog/fr/i18n_using_next-i18next.md +1 -1
  12. package/blog/fr/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  13. package/blog/hi/i18n_using_next-i18next.md +1 -1
  14. package/blog/id/i18n_using_next-i18next.md +1 -1
  15. package/blog/id/next-i18next_vs_next-intl_vs_intlayer.md +2 -2
  16. package/blog/it/i18n_using_next-i18next.md +1 -1
  17. package/blog/it/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  18. package/blog/ja/i18n_using_next-i18next.md +1 -1
  19. package/blog/ja/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  20. package/blog/ko/i18n_using_next-i18next.md +1 -1
  21. package/blog/ko/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  22. package/blog/pl/i18n_using_next-i18next.md +1 -1
  23. package/blog/pl/next-i18next_vs_next-intl_vs_intlayer.md +2 -2
  24. package/blog/pt/i18n_using_next-i18next.md +1 -1
  25. package/blog/pt/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  26. package/blog/ru/i18n_using_next-i18next.md +1 -1
  27. package/blog/ru/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  28. package/blog/tr/i18n_using_next-i18next.md +1 -1
  29. package/blog/uk/i18n_using_next-i18next.md +1 -1
  30. package/blog/uk/next-i18next_vs_next-intl_vs_intlayer.md +2 -2
  31. package/blog/vi/i18n_using_next-i18next.md +1 -1
  32. package/blog/vi/next-i18next_vs_next-intl_vs_intlayer.md +2 -2
  33. package/blog/zh/i18n_using_next-i18next.md +1 -1
  34. package/blog/zh/next-i18next_vs_next-intl_vs_intlayer.md +1 -1
  35. package/docs/ar/bundle_optimization.md +454 -0
  36. package/docs/ar/intlayer_with_next-i18next.md +1 -1
  37. package/docs/ar/intlayer_with_next-intl.md +1 -1
  38. package/docs/ar/intlayer_with_tanstack+solid.md +24 -5
  39. package/docs/ar/intlayer_with_tanstack.md +45 -68
  40. package/docs/bn/bundle_optimization.md +454 -0
  41. package/docs/cs/bundle_optimization.md +454 -0
  42. package/docs/de/bundle_optimization.md +454 -0
  43. package/docs/de/intlayer_with_next-i18next.md +1 -1
  44. package/docs/de/intlayer_with_next-intl.md +1 -1
  45. package/docs/de/intlayer_with_tanstack+solid.md +24 -5
  46. package/docs/de/intlayer_with_tanstack.md +45 -68
  47. package/docs/en/bundle_optimization.md +36 -8
  48. package/docs/en/intlayer_with_next-i18next.md +1 -1
  49. package/docs/en/intlayer_with_next-intl.md +1 -1
  50. package/docs/en/intlayer_with_tanstack+solid.md +24 -5
  51. package/docs/en/intlayer_with_tanstack.md +45 -68
  52. package/docs/en-GB/bundle_optimization.md +454 -0
  53. package/docs/en-GB/intlayer_with_next-i18next.md +1 -1
  54. package/docs/en-GB/intlayer_with_next-intl.md +1 -1
  55. package/docs/en-GB/intlayer_with_tanstack+solid.md +24 -5
  56. package/docs/en-GB/intlayer_with_tanstack.md +47 -70
  57. package/docs/es/bundle_optimization.md +454 -0
  58. package/docs/es/intlayer_with_next-i18next.md +1 -1
  59. package/docs/es/intlayer_with_next-intl.md +1 -1
  60. package/docs/es/intlayer_with_tanstack+solid.md +24 -5
  61. package/docs/es/intlayer_with_tanstack.md +45 -68
  62. package/docs/fr/bundle_optimization.md +454 -0
  63. package/docs/fr/intlayer_with_next-i18next.md +1 -1
  64. package/docs/fr/intlayer_with_next-intl.md +1 -1
  65. package/docs/fr/intlayer_with_tanstack+solid.md +24 -5
  66. package/docs/fr/intlayer_with_tanstack.md +45 -68
  67. package/docs/hi/bundle_optimization.md +454 -0
  68. package/docs/hi/intlayer_with_next-i18next.md +1 -1
  69. package/docs/hi/intlayer_with_next-intl.md +1 -1
  70. package/docs/hi/intlayer_with_tanstack+solid.md +24 -5
  71. package/docs/hi/intlayer_with_tanstack.md +45 -68
  72. package/docs/id/bundle_optimization.md +454 -0
  73. package/docs/id/intlayer_with_next-i18next.md +1 -1
  74. package/docs/id/intlayer_with_next-intl.md +1 -1
  75. package/docs/id/intlayer_with_tanstack+solid.md +24 -5
  76. package/docs/id/intlayer_with_tanstack.md +45 -68
  77. package/docs/it/bundle_optimization.md +454 -0
  78. package/docs/it/intlayer_with_next-i18next.md +1 -1
  79. package/docs/it/intlayer_with_next-intl.md +1 -1
  80. package/docs/it/intlayer_with_tanstack+solid.md +24 -5
  81. package/docs/it/intlayer_with_tanstack.md +45 -68
  82. package/docs/ja/bundle_optimization.md +454 -0
  83. package/docs/ja/intlayer_with_next-i18next.md +1 -1
  84. package/docs/ja/intlayer_with_next-intl.md +1 -1
  85. package/docs/ja/intlayer_with_tanstack+solid.md +24 -5
  86. package/docs/ja/intlayer_with_tanstack.md +45 -36
  87. package/docs/ko/bundle_optimization.md +454 -0
  88. package/docs/ko/intlayer_with_next-i18next.md +1 -1
  89. package/docs/ko/intlayer_with_next-intl.md +1 -1
  90. package/docs/ko/intlayer_with_tanstack+solid.md +24 -5
  91. package/docs/ko/intlayer_with_tanstack.md +45 -68
  92. package/docs/nl/bundle_optimization.md +454 -0
  93. package/docs/pl/bundle_optimization.md +454 -0
  94. package/docs/pl/intlayer_with_next-i18next.md +1 -1
  95. package/docs/pl/intlayer_with_next-intl.md +1 -1
  96. package/docs/pl/intlayer_with_tanstack+solid.md +24 -5
  97. package/docs/pl/intlayer_with_tanstack.md +45 -68
  98. package/docs/pt/bundle_optimization.md +454 -0
  99. package/docs/pt/intlayer_with_next-i18next.md +1 -1
  100. package/docs/pt/intlayer_with_next-intl.md +1 -1
  101. package/docs/pt/intlayer_with_tanstack+solid.md +24 -5
  102. package/docs/pt/intlayer_with_tanstack.md +45 -68
  103. package/docs/ru/bundle_optimization.md +454 -0
  104. package/docs/ru/intlayer_with_next-i18next.md +1 -1
  105. package/docs/ru/intlayer_with_next-intl.md +1 -1
  106. package/docs/ru/intlayer_with_tanstack+solid.md +24 -5
  107. package/docs/ru/intlayer_with_tanstack.md +45 -68
  108. package/docs/tr/bundle_optimization.md +454 -0
  109. package/docs/tr/intlayer_with_next-i18next.md +1 -1
  110. package/docs/tr/intlayer_with_next-intl.md +1 -1
  111. package/docs/tr/intlayer_with_tanstack+solid.md +24 -5
  112. package/docs/tr/intlayer_with_tanstack.md +45 -68
  113. package/docs/uk/bundle_optimization.md +454 -0
  114. package/docs/uk/intlayer_with_next-i18next.md +1 -1
  115. package/docs/uk/intlayer_with_next-intl.md +1 -1
  116. package/docs/uk/intlayer_with_tanstack+solid.md +24 -5
  117. package/docs/uk/intlayer_with_tanstack.md +45 -68
  118. package/docs/ur/bundle_optimization.md +454 -0
  119. package/docs/vi/bundle_optimization.md +454 -0
  120. package/docs/vi/intlayer_with_next-i18next.md +1 -1
  121. package/docs/vi/intlayer_with_next-intl.md +1 -1
  122. package/docs/vi/intlayer_with_tanstack+solid.md +24 -5
  123. package/docs/vi/intlayer_with_tanstack.md +45 -68
  124. package/docs/zh/bundle_optimization.md +454 -0
  125. package/docs/zh/intlayer_with_next-i18next.md +1 -1
  126. package/docs/zh/intlayer_with_next-intl.md +1 -1
  127. package/docs/zh/intlayer_with_tanstack+solid.md +24 -5
  128. package/docs/zh/intlayer_with_tanstack.md +45 -68
  129. package/package.json +7 -7
@@ -0,0 +1,454 @@
1
+ ---
2
+ createdAt: 2025-11-25
3
+ updatedAt: 2026-04-08
4
+ title: Otimizando o tamanho e desempenho do bundle i18n
5
+ description: Reduza o tamanho do bundle da sua aplicação otimizando o conteúdo de internacionalização (i18n). Aprenda a aproveitar o tree shaking e o lazy loading para dicionários com Intlayer.
6
+ keywords:
7
+ - Otimização de bundle
8
+ - Automação de conteúdo
9
+ - Conteúdo dinâmico
10
+ - Intlayer
11
+ - Next.js
12
+ - JavaScript
13
+ - React
14
+ slugs:
15
+ - doc
16
+ - concept
17
+ - bundle-optimization
18
+ history:
19
+ - version: 8.7.0
20
+ date: 2026-04-08
21
+ changes: "Adicionadas as opções `minify` e `purge` à configuração de build"
22
+ ---
23
+
24
+ # Otimizando o tamanho e desempenho do bundle i18n
25
+
26
+ Um dos desafios mais comuns com as soluções i18n tradicionais que dependem de arquivos JSON é o gerenciamento do tamanho do conteúdo. Se os desenvolvedores não separarem manualmente o conteúdo em namespaces, os usuários muitas vezes acabam baixando traduções para cada página e potencialmente para cada idioma apenas para visualizar uma única página.
27
+
28
+ Por exemplo, uma aplicação com 10 páginas traduzidas em 10 idiomas pode resultar em um usuário baixando o conteúdo de 100 páginas, embora precise apenas de **uma** (a página atual no idioma atual). Isso leva a desperdício de largura de banda e tempos de carregamento mais lentos.
29
+
30
+ **O Intlayer resolve esse problema através da otimização em tempo de build.** Ele analisa seu código para detectar quais dicionários são realmente usados por componente e reinjeta apenas o conteúdo necessário no seu bundle.
31
+
32
+ ## Índice
33
+
34
+ <TOC />
35
+
36
+ ## Escaneie seu bundle
37
+
38
+ Analisar seu bundle é o primeiro passo para identificar arquivos JSON "pesados" e oportunidades de code-splitting. Essas ferramentas geram um mapa de árvore (treemap) visual do código compilado da sua aplicação, permitindo que você veja exatamente quais bibliotecas estão consumindo mais espaço.
39
+
40
+ <Tabs>
41
+ <Tab value="vite">
42
+
43
+ ### Vite / Rollup
44
+
45
+ O Vite usa o Rollup por baixo do pano. O plugin `rollup-plugin-visualizer` gera um arquivo HTML interativo que mostra o tamanho de cada módulo no seu gráfico.
46
+
47
+ ```bash
48
+ npm install -D rollup-plugin-visualizer
49
+ ```
50
+
51
+ ```typescript fileName="vite.config.ts"
52
+ import { defineConfig } from "vite";
53
+ import { visualizer } from "rollup-plugin-visualizer";
54
+
55
+ export default defineConfig({
56
+ plugins: [
57
+ visualizer({
58
+ open: true, // Abrir automaticamente o relatório no seu navegador
59
+ filename: "stats.html",
60
+ gzipSize: true,
61
+ brotliSize: true,
62
+ }),
63
+ ],
64
+ });
65
+ ```
66
+
67
+ </Tab>
68
+ <Tab value="nextjs (turbopack)">
69
+
70
+ ### Next.js (Turbopack)
71
+
72
+ Para projetos que usam o App Router e o Turbopack, o Next.js fornece um analisador experimental integrado que não requer dependências extras.
73
+
74
+ ```bash packageManager='npm'
75
+ npx next experimental-analyze
76
+ ```
77
+
78
+ ```bash packageManager='yarn'
79
+ yarn next experimental-analyze
80
+ ```
81
+
82
+ ```bash packageManager='pnpm'
83
+ pnpm next experimental-analyze
84
+ ```
85
+
86
+ ```bash packageManager='bun'
87
+ bun next experimental-analyze
88
+ ```
89
+
90
+ </Tab>
91
+ <Tab value="nextjs (Webpack)">
92
+
93
+ ### Next.js (Webpack)
94
+
95
+ Se você estiver usando o bundler Webpack padrão no Next.js, use o analisador de bundle oficial. Ative-o definindo uma variável de ambiente durante o build.
96
+
97
+ ```bash packageManager='npm'
98
+ npm install -D @next/bundle-analyzer
99
+ ```
100
+
101
+ ```bash packageManager='yarn'
102
+ yarn add -D @next/bundle-analyzer
103
+ ```
104
+
105
+ ```bash packageManager='pnpm'
106
+ pnpm add -D @next/bundle-analyzer
107
+ ```
108
+
109
+ ```bash packageManager='bun'
110
+ bun add -d @next/bundle-analyzer
111
+ ```
112
+
113
+ ```javascript fileName="next.config.js"
114
+ const withBundleAnalyzer = require("@next/bundle-analyzer")({
115
+ enabled: process.env.ANALYZE === "true",
116
+ });
117
+
118
+ module.exports = withBundleAnalyzer({
119
+ // Sua configuração do Next.js
120
+ });
121
+ ```
122
+
123
+ **Uso:**
124
+
125
+ ```bash
126
+ ANALYZE=true npm run build
127
+ ```
128
+
129
+ </Tab>
130
+ <Tab value="Webpack (CRA / Angular / etc)">
131
+
132
+ ### Webpack Padrão
133
+
134
+ Para o Create React App (ejected), Angular ou configurações personalizadas do Webpack, use o padrão da indústria `webpack-bundle-analyzer`.
135
+
136
+ ```bash packageManager='npm'
137
+ npm install -D webpack-bundle-analyzer
138
+ ```
139
+
140
+ ```bash packageManager='yarn'
141
+ yarn add -D webpack-bundle-analyzer
142
+ ```
143
+
144
+ ```bash packageManager='pnpm'
145
+ pnpm add -D webpack-bundle-analyzer
146
+ ```
147
+
148
+ ```bash packageManager='bun'
149
+ bun add -d webpack-bundle-analyzer
150
+ ```
151
+
152
+ ```typescript fileName="webpack.config.ts
153
+ import { BundleAnalyzerPlugin } from "webpack-bundle-analyzer";
154
+
155
+ export default {
156
+ plugins: [
157
+ new BundleAnalyzerPlugin({
158
+ analyzerMode: "static",
159
+ reportFilename: "bundle-analyzer.html",
160
+ openAnalyzer: false,
161
+ }),
162
+ ],
163
+ };
164
+ ```
165
+
166
+ </Tab>
167
+ </Tabs>
168
+
169
+ ## Como Funciona
170
+
171
+ O Intlayer usa uma **abordagem por componente**. Ao contrário dos arquivos JSON globais, seu conteúdo é definido ao lado ou dentro de seus componentes. Durante o processo de build, o Intlayer:
172
+
173
+ 1. **Analisa** seu código para encontrar chamadas `useIntlayer`.
174
+ 2. **Gera** o conteúdo do dicionário correspondente.
175
+ 3. **Substitui** a chamada `useIntlayer` por código otimizado com base na sua configuração.
176
+
177
+ Isso garante que:
178
+
179
+ - Se um componente não for importado, seu conteúdo não será incluído no bundle (Dead Code Elimination).
180
+ - Se um componente for carregado via lazy-loading, seu conteúdo também será carregado dessa forma.
181
+
182
+ ## Configuração por Plataforma
183
+
184
+ <Tabs>
185
+ <Tab value="nextjs">
186
+
187
+ ### Next.js
188
+
189
+ O Next.js requer o plugin `@intlayer/swc` para lidar com a transformação, já que o Next.js usa SWC para builds.
190
+
191
+ > Este plugin não é instalado por padrão porque os plugins SWC ainda são experimentais para o Next.js. Isso pode mudar no futuro.
192
+
193
+ ```bash packageManager="npm"
194
+ npm install -D @intlayer/swc
195
+ ```
196
+
197
+ ```bash packageManager="yarn"
198
+ yarn add -D @intlayer/swc
199
+ ```
200
+
201
+ ```bash packageManager="pnpm"
202
+ pnpm add -D @intlayer/swc
203
+ ```
204
+
205
+ ```bash packageManager="bun"
206
+ bun add -d @intlayer/swc
207
+ ```
208
+
209
+ Uma vez instalado, o Intlayer detectará e usará automaticamente o plugin.
210
+
211
+ </Tab>
212
+ <Tab value="vite">
213
+
214
+ ### Vite
215
+
216
+ O Vite usa o plugin `@intlayer/babel`, que está incluído como dependência do `vite-intlayer`. A otimização é habilitada por padrão. Nada mais precisa ser feito.
217
+
218
+ </Tab>
219
+ <Tab value="webpack">
220
+
221
+ ### Webpack
222
+
223
+ Para habilitar a otimização de bundle com Intlayer no Webpack, você precisa instalar e configurar o plugin Babel (`@intlayer/babel`) ou SWC (`@intlayer/swc`) apropriado.
224
+
225
+ ```bash packageManager="npm"
226
+ npm install -D @intlayer/babel
227
+ ```
228
+
229
+ ```bash packageManager="yarn"
230
+ yarn add -D @intlayer/babel
231
+ ```
232
+
233
+ ```bash packageManager="pnpm"
234
+ pnpm add -D @intlayer/babel
235
+ ```
236
+
237
+ ```bash packageManager="bun"
238
+ bun add -d @intlayer/babel
239
+ ```
240
+
241
+ ```typescript fileName="babel.config.js"
242
+ const {
243
+ getOptimizePluginOptions,
244
+ intlayerOptimizeBabelPlugin,
245
+ } = require("@intlayer/babel");
246
+
247
+ module.exports = {
248
+ plugins: [[intlayerOptimizeBabelPlugin, getOptimizePluginOptions()]],
249
+ };
250
+ ```
251
+
252
+ </Tab>
253
+ </Tabs>
254
+
255
+ ## Configuração
256
+
257
+ Você pode controlar como o Intlayer otimiza seu bundle através da propriedade `build` no seu `intlayer.config.ts`.
258
+
259
+ ```typescript fileName="intlayer.config.ts"
260
+ import { Locales, type IntlayerConfig } from "intlayer";
261
+
262
+ const config: IntlayerConfig = {
263
+ internationalization: {
264
+ locales: [Locales.ENGLISH, Locales.FRENCH],
265
+ defaultLocale: Locales.ENGLISH,
266
+ },
267
+ dictionary: {
268
+ importMode: "dynamic",
269
+ },
270
+ build: {
271
+ /**
272
+ * Minificar os dicionários para reduzir o tamanho do bundle.
273
+ */
274
+ minify: true;
275
+
276
+ /**
277
+ * Remover (purge) as chaves não utilizadas nos dicionários
278
+ */
279
+ purge: true;
280
+
281
+ /**
282
+ * Indica se o build deve verificar tipos TypeScript
283
+ */
284
+ checkTypes: false;
285
+ },
286
+ };
287
+
288
+ export default config;
289
+ ```
290
+
291
+ > Manter a opção padrão para `optimize` é recomendado na grande maioria dos casos.
292
+
293
+ > Veja a doc de configuração para mais detalhes: [Configuração](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pt/configuration.md)
294
+
295
+ ### Opções de Build
296
+
297
+ As seguintes opções estão disponíveis sob o objeto de configuração `build`:
298
+
299
+ | Propriedade | Tipo | Padrão | Descrição |
300
+ | :------------- | :-------- | :---------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
301
+ | **`optimize`** | `boolean` | `undefined` | Controla se a otimização de build está habilitada. Se `true`, o Intlayer substitui as chamadas de dicionário por injeções otimizadas. Se `false`, a otimização é desabilitada. Idealmente definido como `true` em prod. |
302
+ | **`minify`** | `boolean` | `false` | Se deve minificar os dicionários para reduzir o tamanho do bundle. |
303
+ | **`purge`** | `boolean` | `false` | Se deve remover as chaves não utilizadas nos dicionários. |
304
+
305
+ ### Minificação
306
+
307
+ Minificar dicionários remove espaços em branco desnecessários, comentários e reduz o tamanho do conteúdo JSON. Isso é especialmente útil para dicionários grandes.
308
+
309
+ ```typescript fileName="intlayer.config.ts"
310
+ import type { IntlayerConfig } from "intlayer";
311
+
312
+ const config: IntlayerConfig = {
313
+ build: {
314
+ minify: true,
315
+ },
316
+ };
317
+
318
+ export default config;
319
+ ```
320
+
321
+ > Nota: A minificação é ignorada se `optimize` estiver desabilitado ou se o Visual Editor estiver habilitado (pois o editor precisa do conteúdo completo para permitir a edição).
322
+
323
+ ### Purging (Remoção)
324
+
325
+ O purging garante que apenas as chaves realmente usadas no seu código sejam incluídas no bundle final de dicionários. Isso pode reduzir significativamente o tamanho do seu bundle se você tiver dicionários grandes com muitas chaves que não são usadas em todas as partes da sua aplicação.
326
+
327
+ ```typescript fileName="intlayer.config.ts"
328
+ import type { IntlayerConfig } from "intlayer";
329
+
330
+ const config: IntlayerConfig = {
331
+ build: {
332
+ purge: true,
333
+ },
334
+ };
335
+
336
+ export default config;
337
+ ```
338
+
339
+ > Nota: O purging é ignorado se `optimize` estiver desabilitado.
340
+
341
+ ### Modo de Importação
342
+
343
+ Para grandes aplicações, incluindo várias páginas e locais, seus arquivos JSON podem representar uma parte significativa do tamanho do seu bundle. O Intlayer permite que você controle como os dicionários são carregados.
344
+
345
+ O modo de importação pode ser definido por padrão globalmente no seu arquivo `intlayer.config.ts`.
346
+
347
+ ```typescript fileName="intlayer.config.ts"
348
+ import type { IntlayerConfig } from "intlayer";
349
+
350
+ const config: IntlayerConfig = {
351
+ build: {
352
+ minify: true,
353
+ },
354
+ };
355
+
356
+ export default config;
357
+ ```
358
+
359
+ Assim como para cada dicionário nos seus arquivos `.content.{{ts|tsx|js|jsx|mjs|cjs|json|jsonc|json5}}`.
360
+
361
+ ```ts
362
+ import { type Dictionary, t } from "intlayer";
363
+
364
+ const appContent: Dictionary = {
365
+ key: "app",
366
+ importMode: "dynamic", // Sobrescrever o modo de importação padrão
367
+ content: {
368
+ // ...
369
+ },
370
+ };
371
+
372
+ export default appContent;
373
+ ```
374
+
375
+ | Propriedade | Tipo | Padrão | Descrição |
376
+ | :--------------- | :--------------------------------- | :--------- | :-------------------------------------------------------------------------------------------------------------------------- |
377
+ | **`importMode`** | `'static'`, `'dynamic'`, `'fetch'` | `'static'` | **Obsoleto**: Use `dictionary.importMode` em seu lugar. Determina como os dicionários são carregados (ver detalhes abaixo). |
378
+
379
+ A configuração `importMode` dita como o conteúdo do dicionário é injetado no seu componente.
380
+ Você pode defini-lo globalmente no arquivo `intlayer.config.ts` sob o objeto `dictionary`, ou pode sobrescrevê-lo para um dicionário específico em seu arquivo `.content.ts`.
381
+
382
+ ### 1. Modo Estático (`default`)
383
+
384
+ No modo estático, o Intlayer substitui `useIntlayer` por `useDictionary` e injeta o dicionário diretamente no bundle JavaScript.
385
+
386
+ - **Prós:** Renderização instantânea (síncrona), zero solicitações de rede extras durante a hidratação.
387
+ - **Contras:** O bundle inclui traduções para **todos** os idiomas disponíveis para aquele componente específico.
388
+ - **Ideal para:** Single Page Applications (SPA).
389
+
390
+ **Exemplo de código transformado:**
391
+
392
+ ```tsx
393
+ // Seu código
394
+ const content = useIntlayer("my-key");
395
+
396
+ // Código otimizado (Estático)
397
+ const content = useDictionary({
398
+ key: "my-key",
399
+ content: {
400
+ nodeType: "translation",
401
+ translation: {
402
+ en: "My title",
403
+ fr: "Mon titre",
404
+ },
405
+ },
406
+ });
407
+ ```
408
+
409
+ ### 2. Modo Dinâmico
410
+
411
+ No modo dinâmico, o Intlayer substitui `useIntlayer` por `useDictionaryAsync`. Isso usa `import()` (mecanismo semelhante ao Suspense) para carregar de forma assíncrona (lazy-load) especificamente o JSON para o local atual.
412
+
413
+ - **Prós:** **Tree shaking a nível de local.** Um usuário visualizando a versão em inglês baixará _apenas_ o dicionário em inglês. O dicionário em francês nunca é carregado.
414
+ - **Contras:** Dispara uma solicitação de rede (busca de asset) por componente durante a hidratação.
415
+ - **Ideal para:** Grandes blocos de texto, artigos ou aplicações que suportam muitos idiomas onde o tamanho do bundle é crítico.
416
+
417
+ **Exemplo de código transformado:**
418
+
419
+ ```tsx
420
+ // Seu código
421
+ const content = useIntlayer("my-key");
422
+
423
+ // Código otimizado (Dinâmico)
424
+ const content = useDictionaryAsync({
425
+ en: () =>
426
+ import(".intlayer/dynamic_dictionary/my-key/en.json").then(
427
+ (mod) => mod.default
428
+ ),
429
+ fr: () =>
430
+ import(".intlayer/dynamic_dictionary/my-key/fr.json").then(
431
+ (mod) => mod.default
432
+ ),
433
+ });
434
+ ```
435
+
436
+ > Ao usar `importMode: 'dynamic'`, se você tiver 100 componentes usando `useIntlayer` em uma única página, o navegador tentará 100 buscas separadas. Para evitar essa "cascata" de solicitações, agrupe o conteúdo em menos arquivos `.content` (ex: um dicionário por seção da página) em vez de um por componente átomo.
437
+
438
+ ### 3. Modo Fetch
439
+
440
+ Comporta-se de forma semelhante ao modo Dinâmico, mas tenta buscar dicionários da API Intlayer Live Sync primeiro. Se a chamada da API falhar ou o conteúdo não estiver marcado para atualizações ao vivo, ele recorre à importação dinâmica.
441
+
442
+ > Consulte a documentação do CMS para mais detalhes: [CMS](https://github.com/aymericzip/intlayer/blob/main/docs/docs/pt/intlayer_CMS.md)
443
+
444
+ > No modo fetch, purge e minificação não podem ser usados.
445
+
446
+ ## Resumo: Estático vs Dinâmico
447
+
448
+ | Recurso | Modo Estático | Modo Dinâmico |
449
+ | :-------------------- | :------------------------------------------------ | :-------------------------------------- |
450
+ | **Tamanho Bundle JS** | Maior (inclui todos os idiomas para o componente) | Menor (apenas código, sem conteúdo) |
451
+ | **Carga Inicial** | Instantânea (O conteúdo está no bundle) | Pequeno atraso (Busca o JSON) |
452
+ | **Solicitações Rede** | 0 solicitações extras | 1 solicitação por dicionário |
453
+ | **Tree Shaking** | Nível de componente | Nível de componente + Nível de local |
454
+ | **Melhor Caso Uso** | Componentes de UI, pequenas aplicações | Páginas com muito texto, muitos idiomas |
@@ -256,7 +256,7 @@ export default function LocaleLayout({
256
256
  params: { locale: string };
257
257
  }) {
258
258
  const locale: Locale = (locales as readonly string[]).includes(params.locale)
259
- ? (params.locale as any)
259
+ ? params.locale
260
260
  : defaultLocale;
261
261
 
262
262
  const dir = isRtl(locale) ? "rtl" : "ltr";
@@ -103,7 +103,7 @@ async function loadMessages(locale: string) {
103
103
  }
104
104
 
105
105
  export default getRequestConfig(async ({ locale }) => {
106
- if (!locales.includes(locale as any)) notFound();
106
+ if (!locales.includes(locale)) notFound();
107
107
 
108
108
  return {
109
109
  messages: await loadMessages(locale),
@@ -194,9 +194,7 @@ const RootComponent: ParentComponent = (props) => {
194
194
  </head>
195
195
  <body>
196
196
  <IntlayerProvider locale={locale}>
197
- <Suspense>
198
- {props.children}
199
- </Suspense>
197
+ <Suspense>{props.children}</Suspense>
200
198
  </IntlayerProvider>
201
199
  <Scripts />
202
200
  </body>
@@ -506,12 +504,33 @@ export const Route = createFileRoute("/{-$locale}/")({
506
504
  component: RouteComponent,
507
505
  head: ({ params }) => {
508
506
  const { locale } = params;
509
- const metaContent = getIntlayer("page-metadata", locale);
507
+ const path = "/"; // The path for this route
508
+
509
+ const metaContent = getIntlayer("app", locale);
510
510
 
511
511
  return {
512
+ links: [
513
+ // Canonical link: Points to the current localized page
514
+ { rel: "canonical", href: getLocalizedUrl(path, locale) },
515
+
516
+ // Hreflang: Tell Google about all localized versions
517
+ ...localeMap(({ locale: mapLocale }) => ({
518
+ rel: "alternate",
519
+ hrefLang: mapLocale,
520
+ href: getLocalizedUrl(path, mapLocale),
521
+ })),
522
+
523
+ // x-default: For users in unmatched languages
524
+ // Define the default fallback locale (usually your primary language)
525
+ {
526
+ rel: "alternate",
527
+ hrefLang: "x-default",
528
+ href: getLocalizedUrl(path, defaultLocale),
529
+ },
530
+ ],
512
531
  meta: [
513
532
  { title: metaContent.title },
514
- { content: metaContent.description, name: "description" },
533
+ { name: "description", content: metaContent.meta.description },
515
534
  ],
516
535
  };
517
536
  },
@@ -225,9 +225,7 @@ function RootDocument({ children }: { children: ReactNode }) {
225
225
  <HeadContent />
226
226
  </head>
227
227
  <body>
228
- <IntlayerProvider locale={locale}>
229
- {children}
230
- </IntlayerProvider>
228
+ <IntlayerProvider locale={locale}>{children}</IntlayerProvider>
231
229
  <Scripts />
232
230
  </body>
233
231
  </html>
@@ -327,30 +325,20 @@ import { getPrefix } from "intlayer";
327
325
 
328
326
  export const LOCALE_ROUTE = "{-$locale}" as const;
329
327
 
330
- // Utilitário principal
331
- export type RemoveLocaleParam<T> = T extends string
332
- ? RemoveLocaleFromString<T>
333
- : T;
328
+ export type To = StripLocalePrefix<LinkComponentProps["to"]>;
334
329
 
335
- export type To = RemoveLocaleParam<LinkComponentProps["to"]>;
336
-
337
- type CollapseDoubleSlashes<S extends string> =
338
- S extends `${infer H}//${infer T}` ? CollapseDoubleSlashes<`${H}/${T}`> : S;
330
+ export type StripLocalePrefix<T extends string | undefined> = T extends
331
+ | `/${typeof LOCALE_ROUTE}/`
332
+ | `/${typeof LOCALE_ROUTE}`
333
+ ? "/"
334
+ : T extends `/${typeof LOCALE_ROUTE}/${infer Rest}`
335
+ ? `/${Rest}`
336
+ : T;
339
337
 
340
338
  type LocalizedLinkProps = {
341
339
  to?: To;
342
340
  } & Omit<LinkComponentProps, "to">;
343
341
 
344
- // Auxiliares
345
- type RemoveAll<
346
- S extends string,
347
- Sub extends string,
348
- > = S extends `${infer H}${Sub}${infer T}` ? RemoveAll<`${H}${T}`, Sub> : S;
349
-
350
- type RemoveLocaleFromString<S extends string> = CollapseDoubleSlashes<
351
- RemoveAll<S, typeof LOCALE_ROUTE>
352
- >;
353
-
354
342
  export const LocalizedLink: FC<LocalizedLinkProps> = (props) => {
355
343
  const { locale } = useLocale();
356
344
  const { localePrefix } = getPrefix(locale);
@@ -379,26 +367,26 @@ Então, podemos criar um hook `useLocalizedNavigate` para navegação programát
379
367
  import { useNavigate } from "@tanstack/react-router";
380
368
  import { getPrefix } from "intlayer";
381
369
  import { useLocale } from "react-intlayer";
382
- import { LOCALE_ROUTE } from "@/components/localized-link";
370
+ import type { StripLocalePrefix } from "@/components/localized-link";
383
371
  import type { FileRouteTypes } from "@/routeTree.gen";
384
372
 
385
- type StripLocalePrefix<T extends string> = T extends
386
- | `/${typeof LOCALE_ROUTE}`
387
- | `/${typeof LOCALE_ROUTE}/`
388
- ? "/"
389
- : T extends `/${typeof LOCALE_ROUTE}/${infer Rest}`
390
- ? `/${Rest}`
391
- : never;
373
+ type NavigateFn = ReturnType<typeof useNavigate>;
374
+ type BaseNavigateOptions = Parameters<NavigateFn>[0];
392
375
 
393
376
  type LocalizedTo = StripLocalePrefix<FileRouteTypes["to"]>;
394
377
 
395
- type LocalizedNavigate = {
396
- (to: LocalizedTo): ReturnType<ReturnType<typeof useNavigate>>;
397
- (
398
- opts: { to: LocalizedTo } & Record<string, unknown>
399
- ): ReturnType<ReturnType<typeof useNavigate>>;
378
+ export type LocalizedNavigateOptions = Omit<
379
+ BaseNavigateOptions,
380
+ "to" | "params"
381
+ > & {
382
+ to: LocalizedTo;
383
+ params?: Omit<NonNullable<BaseNavigateOptions["params"]>, "locale">;
400
384
  };
401
385
 
386
+ type LocalizedNavigate = (
387
+ options: LocalizedNavigateOptions
388
+ ) => ReturnType<NavigateFn>;
389
+
402
390
  export const useLocalizedNavigate = () => {
403
391
  const navigate = useNavigate();
404
392
 
@@ -445,38 +433,6 @@ import { useLocalizedNavigate } from "@/hooks/useLocalizedNavigate";
445
433
 
446
434
  export const Route = createFileRoute("/{-$locale}/")({
447
435
  component: RouteComponent,
448
- head: ({ params }) => {
449
- const { locale } = params;
450
- const path = "/"; // The path for this route
451
-
452
- const metaContent = getIntlayer("app", locale);
453
-
454
- return {
455
- links: [
456
- // Canonical link: Points to the current localized page
457
- { rel: "canonical", href: getLocalizedUrl(path, locale) },
458
-
459
- // Hreflang: Tell Google about all localized versions
460
- ...localeMap(({ locale: mapLocale }) => ({
461
- rel: "alternate",
462
- hrefLang: mapLocale,
463
- href: getLocalizedUrl(path, mapLocale),
464
- })),
465
-
466
- // x-default: For users in unmatched languages
467
- // Define the default fallback locale (usually your primary language)
468
- {
469
- rel: "alternate",
470
- hrefLang: "x-default",
471
- href: getLocalizedUrl(path, defaultLocale),
472
- },
473
- ],
474
- meta: [
475
- { title: metaContent.title },
476
- { name: "description", content: metaContent.meta.description },
477
- ],
478
- };
479
- },
480
436
  });
481
437
 
482
438
  function RouteComponent() {
@@ -631,12 +587,33 @@ export const Route = createFileRoute("/{-$locale}/")({
631
587
  component: RouteComponent,
632
588
  head: ({ params }) => {
633
589
  const { locale } = params;
634
- const metaContent = getIntlayer("page-metadata", locale);
590
+ const path = "/"; // The path for this route
591
+
592
+ const metaContent = getIntlayer("app", locale);
635
593
 
636
594
  return {
595
+ links: [
596
+ // Canonical link: Points to the current localized page
597
+ { rel: "canonical", href: getLocalizedUrl(path, locale) },
598
+
599
+ // Hreflang: Tell Google about all localized versions
600
+ ...localeMap(({ locale: mapLocale }) => ({
601
+ rel: "alternate",
602
+ hrefLang: mapLocale,
603
+ href: getLocalizedUrl(path, mapLocale),
604
+ })),
605
+
606
+ // x-default: For users in unmatched languages
607
+ // Define the default fallback locale (usually your primary language)
608
+ {
609
+ rel: "alternate",
610
+ hrefLang: "x-default",
611
+ href: getLocalizedUrl(path, defaultLocale),
612
+ },
613
+ ],
637
614
  meta: [
638
615
  { title: metaContent.title },
639
- { content: metaContent.description, name: "description" },
616
+ { name: "description", content: metaContent.meta.description },
640
617
  ],
641
618
  };
642
619
  },