@intlayer/docs 7.5.13 → 7.5.14

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 (35) hide show
  1. package/blog/ar/per-component_vs_centralized_i18n.md +248 -0
  2. package/blog/de/per-component_vs_centralized_i18n.md +248 -0
  3. package/blog/en/_per-component_vs_centralized_i18n.md +252 -0
  4. package/blog/en/per-component_vs_centralized_i18n.md +248 -0
  5. package/blog/en-GB/per-component_vs_centralized_i18n.md +247 -0
  6. package/blog/es/per-component_vs_centralized_i18n.md +245 -0
  7. package/blog/fr/per-component_vs_centralized_i18n.md +245 -0
  8. package/blog/hi/per-component_vs_centralized_i18n.md +249 -0
  9. package/blog/id/per-component_vs_centralized_i18n.md +248 -0
  10. package/blog/it/per-component_vs_centralized_i18n.md +247 -0
  11. package/blog/ja/per-component_vs_centralized_i18n.md +247 -0
  12. package/blog/ko/per-component_vs_centralized_i18n.md +246 -0
  13. package/blog/pl/per-component_vs_centralized_i18n.md +247 -0
  14. package/blog/pt/per-component_vs_centralized_i18n.md +246 -0
  15. package/blog/ru/per-component_vs_centralized_i18n.md +251 -0
  16. package/blog/tr/per-component_vs_centralized_i18n.md +244 -0
  17. package/blog/uk/per-component_vs_centralized_i18n.md +248 -0
  18. package/blog/vi/per-component_vs_centralized_i18n.md +246 -0
  19. package/blog/zh/per-component_vs_centralized_i18n.md +248 -0
  20. package/dist/cjs/common.cjs.map +1 -1
  21. package/dist/cjs/generated/blog.entry.cjs +20 -0
  22. package/dist/cjs/generated/blog.entry.cjs.map +1 -1
  23. package/dist/cjs/generated/docs.entry.cjs.map +1 -1
  24. package/dist/cjs/generated/frequentQuestions.entry.cjs.map +1 -1
  25. package/dist/cjs/generated/legal.entry.cjs.map +1 -1
  26. package/dist/esm/common.mjs.map +1 -1
  27. package/dist/esm/generated/blog.entry.mjs +20 -0
  28. package/dist/esm/generated/blog.entry.mjs.map +1 -1
  29. package/dist/esm/generated/docs.entry.mjs.map +1 -1
  30. package/dist/esm/generated/frequentQuestions.entry.mjs.map +1 -1
  31. package/dist/esm/generated/legal.entry.mjs.map +1 -1
  32. package/dist/types/generated/blog.entry.d.ts +1 -0
  33. package/dist/types/generated/blog.entry.d.ts.map +1 -1
  34. package/package.json +9 -9
  35. package/src/generated/blog.entry.ts +20 -0
@@ -0,0 +1,251 @@
1
+ ---
2
+ createdAt: 2025-09-10
3
+ updatedAt: 2025-09-10
4
+ title: i18n на уровне компонента против централизованного: новый подход с Intlayer
5
+ description: Глубокое погружение в стратегии интернационализации в React, сравнение централизованного, по-ключевого и по-компонентного подходов, и представление Intlayer.
6
+ keywords:
7
+ - i18n
8
+ - React
9
+ - Интернационализация
10
+ - Intlayer
11
+ - Оптимизация
12
+ - Размер бандла
13
+ slugs:
14
+ - blog
15
+ - per-component-vs-centralized-i18n
16
+ ---
17
+
18
+ # По-компонентный vs централизованный i18n
19
+
20
+ Подход по компонентам — не новое понятие. Например, в экосистеме Vue `vue-i18n` поддерживает [i18n SFC (Single File Component)](https://vue-i18n.intlify.dev/guide/advanced/sfc.html). Nuxt также предлагает [переводы на уровне компонента](https://i18n.nuxtjs.org/docs/guide/per-component-translations), а Angular использует похожий паттерн через свои [Feature Modules](https://v17.angular.io/guide/feature-modules).
21
+
22
+ Даже в Flutter-приложении часто встречается следующий паттерн:
23
+
24
+ ```bash
25
+ lib/
26
+ └── features/
27
+ └── login/
28
+ ├── login_screen.dart
29
+ └── login_screen.i18n.dart # <- Переводы находятся здесь
30
+ ```
31
+
32
+ ```dart fileName='lib/features/login/login_screen.i18n.dart'
33
+ import 'package:i18n_extension/i18n_extension.dart';
34
+
35
+ extension Localization on String {
36
+ static var _t = Translations.byText("en") +
37
+ {
38
+ "Hello": {
39
+ "en": "Hello",
40
+ "fr": "Bonjour",
41
+ },
42
+ };
43
+
44
+ String get i18n => localize(this, _t);
45
+ }
46
+ ```
47
+
48
+ Однако в мире React мы в основном видим разные подходы, которые я сгруппирую в три категории:
49
+
50
+ <Columns>
51
+ <Column>
52
+
53
+ **Централизованный подход** (i18next, next-intl, react-intl, lingui)
54
+
55
+ - (без пространств имён) рассматривает единый источник для получения контента. По умолчанию вы загружаете контент со всех страниц при загрузке приложения.
56
+
57
+ </Column>
58
+ <Column>
59
+
60
+ **Гранулярный подход** (intlayer, inlang)
61
+
62
+ - более тонко настраивает получение контента — по ключу или по компоненту.
63
+
64
+ </Column>
65
+ </Columns>
66
+
67
+ > В этом блоге я не буду фокусироваться на решениях, основанных на компиляции, которые я уже рассмотрел здесь: [Компилятор vs декларативный i18n](https://github.com/aymericzip/intlayer/blob/main/docs/blog/ru/compiler_vs_declarative_i18n.md).
68
+ > Обратите внимание, что i18n, основанный на компиляции (например, Lingui), просто автоматизирует извлечение и загрузку контента. Под капотом они часто имеют те же ограничения, что и другие подходы.
69
+
70
+ > Обратите внимание: чем тоньше вы разбиваете механизм получения контента, тем больше риск внедрения дополнительного состояния и логики в ваши компоненты.
71
+
72
+ Гранулярные подходы более гибкие, чем централизованные, но часто это компромисс. Даже если библиотеки рекламируют "tree shaking", на практике вы часто в итоге будете загружать страницу на каждом языке.
73
+
74
+ В целом решение сводится к следующему:
75
+
76
+ - Если в вашем приложении страниц больше, чем языков, стоит отдавать предпочтение гранулярному подходу.
77
+ - Если языков больше, чем страниц, стоит склоняться к централизованному подходу.
78
+
79
+ Разработчики библиотек, разумеется, знают об этих ограничениях и предлагают обходные решения. Среди них: разделение на namespaces, динамическая загрузка JSON-файлов (`await import()`), или очистка контента на этапе сборки.
80
+
81
+ В то же время следует учитывать, что при динамической подгрузке контента вы создаёте дополнительные запросы к серверу. Каждое дополнительное `useState` или hook означает ещё один запрос к серверу.
82
+
83
+ > Чтобы решить эту проблему, Intlayer предлагает группировать несколько определений контента под одним и тем же ключом; Intlayer затем объединит этот контент.
84
+
85
+ Исходя из всего этого, очевидно, что наиболее популярным подходом является централизованный.
86
+
87
+ ### Почему же централизованный подход так популярен?
88
+
89
+ /// Во-первых, i18next был первым решением, ставшим широко используемым, следуя философии, вдохновлённой архитектурами PHP и Java (MVC), которые опираются на строгую сегрегацию обязанностей (содержание отделено от кода). Он появился в 2011 году, установив свои стандарты ещё до масштабного перехода к компонентно-ориентированным архитектурам (например, React).
90
+
91
+ - Затем, как только библиотека становится широко принятой, переход экосистемы на другие паттерны становится затруднительным.
92
+ - Использование централизованного подхода также упрощает работу с системами управления переводами, такими как Crowdin, Phrase или Localized.
93
+ - Логика подхода per-component более сложна, чем у централизованного, и требует дополнительного времени на разработку, особенно когда приходится решать такие задачи, как определение местоположения контента.
94
+
95
+ ### Хорошо, но почему просто не придерживаться централизованного подхода?
96
+
97
+ Давайте я объясню, почему это может стать проблемой для вашего приложения:
98
+
99
+ - **Неиспользуемые данные:**
100
+ Когда загружается страница, вы часто загружаете содержимое со всех остальных страниц. (В приложении из 10 страниц это 90% загруженного, но неиспользуемого контента). Ленивая загрузка модального окна? Библиотека i18n всё равно не обращает внимания — она сначала загружает строки.
101
+
102
+ - **Производительность:**
103
+ При каждом повторном рендере каждый ваш компонент гидратируется массивной JSON‑нагрузкой, что негативно влияет на реактивность приложения по мере его роста.
104
+
105
+ - **Поддержка:**
106
+ Поддерживать большие JSON‑файлы болезненно. Приходится переходить между файлами, чтобы вставить перевод, при этом нужно следить, чтобы не было отсутствующих переводов и чтобы не осталось **orphan keys**.
107
+
108
+ - **Дизайн‑система:**
109
+ Это создаёт несовместимость с design systems (например, компонент `LoginForm`) и ограничивает дублирование компонентов между разными приложениями.
110
+
111
+ **"Но мы придумали Namespaces!"**
112
+
113
+ Конечно, и это значительный шаг вперёд. Давайте сравним размер основного бандла для конфигурации `Vite + React + React Router v7 + Intlayer`. Мы симулировали 20-страничное приложение.
114
+
115
+ Первый пример не включает ленивую загрузку переводов по локалям и не содержит разделения на namespaces. Во втором примере используется content purging + динамическая загрузка переводов.
116
+
117
+ | Оптимизированный бандл | Неоптимизированный бандл |
118
+ | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ |
119
+ | ![неоптимизированный bundle](https://github.com/aymericzip/intlayer/blob/main/docs/assets/bundle_no_optimization.png?raw=true) | ![оптимизированный bundle](https://github.com/aymericzip/intlayer/blob/main/docs/assets/bundle.png?raw=true) |
120
+
121
+ Таким образом, благодаря namespaces, мы перешли от этой структуры:
122
+
123
+ ```bash
124
+ locale/
125
+ ├── en.json
126
+ ├── fr.json
127
+ └── es.json
128
+ ```
129
+
130
+ To this one:
131
+
132
+ ```bash
133
+ locale/
134
+ ├── en/
135
+ │ ├── common.json
136
+ │ ├── navbar.json
137
+ │ ├── footer.json
138
+ │ ├── home.json
139
+ │ └── about.json
140
+ ├── fr/
141
+ │ └── ...
142
+ └── es/
143
+ └── ...
144
+
145
+ ```
146
+
147
+ Теперь вам нужно тонко управлять тем, какую часть контента вашего приложения следует загружать и где. В результате подавляющее большинство проектов просто пропускают эту часть из‑за сложности (см. руководство [next-i18next](https://github.com/aymericzip/intlayer/blob/main/docs/blog/ru/i18n_using_next-i18next.md), чтобы увидеть, какие вызовы представляет собой (даже) следование лучшим практикам).
148
+ Вследствие этого такие проекты в конечном итоге сталкиваются с проблемой массовой загрузки JSON, описанной ранее.
149
+
150
+ > Обратите внимание, что эта проблема не является специфичной для i18next, а относится ко всем централизованным подходам, перечисленным выше.
151
+
152
+ Однако хочу напомнить, что не все гранулярные подходы решают эту проблему. Например, подходы `vue-i18n SFC` или `inlang` по сути не выполняют ленивую подгрузку переводов по локалям, поэтому вы просто меняете проблему размера бандла (bundle size) на другую.
153
+
154
+ Кроме того, без правильного разделения ответственности становится гораздо сложнее извлечь и передать ваши переводы переводчикам для проверки.
155
+
156
+ ### Как покомпонентный подход Intlayer решает эту проблему
157
+
158
+ Intlayer работает в несколько шагов:
159
+
160
+ 1. **Declaration:** Объявляйте ваш контент в любом месте codebase, используя файлы `*.content.{ts|jsx|cjs|json|json5|...}`. Это обеспечивает разделение ответственности при одновременном размещении контента рядом с кодом (colocated). Файл контента может быть для одной локали или мультиязычным.
161
+ 2. **Обработка:** Intlayer выполняет шаг сборки для обработки JS-логики, обработки отсутствующих переводов (fallbacks), генерации типов TypeScript, управления дублирующимся контентом, получения контента из вашей CMS и прочего.
162
+ 3. **Очистка:** Когда ваше приложение собирается, Intlayer удаляет неиспользуемый контент (немного похожим образом на то, как Tailwind управляет вашими классами), заменяя контент следующим образом:
163
+
164
+ **Декларация:**
165
+
166
+ ```tsx
167
+ // src/MyComponent.tsx
168
+ export const MyComponent = () => {
169
+ const content = useIntlayer("my-key");
170
+ return <h1>{content.title}</h1>;
171
+ };
172
+ ```
173
+
174
+ ```tsx
175
+ // src/myComponent.content.ts
176
+ export const {
177
+ key: "my-key",
178
+ content: t({
179
+ ru: { title: "Мой заголовок" },
180
+ en: { title: "My title" },
181
+ fr: { title: "Mon titre" }
182
+ })
183
+ }
184
+
185
+ ```
186
+
187
+ **Обработка:** Intlayer собирает словарь на основе файла `.content` и генерирует:
188
+
189
+ ```json5
190
+ // .intlayer/dynamic_dictionary/en/my-key.json
191
+ {
192
+ "key": "my-key",
193
+ "content": { "title": "Мой заголовок" },
194
+ }
195
+ ```
196
+
197
+ **Замена:** Intlayer преобразует ваш компонент во время сборки приложения.
198
+
199
+ **- Режим статического импорта:**
200
+
201
+ ```tsx
202
+ // Representation of the component in JSX-like syntax
203
+ export const MyComponent = () => {
204
+ const content = useDictionary({
205
+ key: "my-key",
206
+ content: {
207
+ nodeType: "translation",
208
+ translation: {
209
+ en: { title: "Мой заголовок" },
210
+ fr: { title: "Мой заголовок" },
211
+ },
212
+ },
213
+ });
214
+
215
+ return <h1>{content.title}</h1>;
216
+ };
217
+ ```
218
+
219
+ **- Режим динамического импорта:**
220
+
221
+ ```tsx
222
+ // Representation of the component in JSX-like syntax
223
+ export const MyComponent = () => {
224
+ const content = useDictionaryAsync({
225
+ en: () =>
226
+ import(".intlayer/dynamic_dictionary/en/my-key.json", {
227
+ with: { type: "json" },
228
+ }).then((mod) => mod.default),
229
+ // То же самое для других языков
230
+ });
231
+
232
+ return <h1>{content.title}</h1>;
233
+ };
234
+ ```
235
+
236
+ > `useDictionaryAsync` использует механизм, похожий на Suspense, чтобы загружать локализованный JSON только по мере необходимости.
237
+
238
+ **Ключевые преимущества этого подхода на уровне компонентов:**
239
+
240
+ - Держать объявление контента рядом с компонентами повышает удобство сопровождения (например, при переносе компонентов в другое приложение или дизайн-систему. Удаление папки компонента также удаляет связанный контент, как вы, вероятно, уже делаете для ваших `.test`, `.stories`)
241
+
242
+ - Подход «по компонентам» избавляет AI-агентов от необходимости перескакивать между множеством разных файлов. Он собирает все переводы в одном месте, снижая сложность задачи и количество используемых токенов.
243
+
244
+ ### Ограничения
245
+
246
+ Разумеется, у такого подхода есть компромиссы:
247
+
248
+ - Сложнее интегрироваться с другими l10n‑системами и дополнительным tooling'ом (инструментариями).
249
+ - Возникает привязка к выбранному решению (что, по сути, уже характерно для любых i18n‑решений из‑за их специфического синтаксиса).
250
+
251
+ Именно поэтому Intlayer стремится предоставить полный набор инструментов для i18n (100% бесплатно и с открытым исходным кодом), включая AI‑перевод с использованием вашего собственного AI Provider и API‑ключей. Intlayer также предоставляет tooling для синхронизации ваших JSON‑файлов, функционируя как message formatters ICU / vue-i18n / i18next для сопоставления контента с их специфичными форматами.
@@ -0,0 +1,244 @@
1
+ ---
2
+ createdAt: 2025-09-10
3
+ updatedAt: 2025-09-10
4
+ title: Bileşen-Başına vs Merkezileştirilmiş i18n: Intlayer ile Yeni Bir Yaklaşım
5
+ description: React'te uluslararasılaştırma stratejilerine derinlemesine bir bakış; merkezi, per-key (anahtar-başına) ve bileşen-başına yaklaşımları karşılaştırır ve Intlayer'ı tanıtır.
6
+ keywords:
7
+ - i18n
8
+ - React
9
+ - Uluslararasılaştırma
10
+ - Intlayer
11
+ - Optimizasyon
12
+ - Bundle Boyutu
13
+ slugs:
14
+ - blog
15
+ - per-component-vs-centralized-i18n
16
+ ---
17
+
18
+ # Bileşen-Başına (Per-Component) vs Merkezileştirilmiş (Centralized) i18n
19
+
20
+ Bileşen başına yaklaşımı yeni bir kavram değildir. Örneğin, Vue ekosisteminde `vue-i18n` [SFC i18n (Single File Component)](https://vue-i18n.intlify.dev/guide/advanced/sfc.html) destekler. Nuxt ayrıca [bileşen başına çeviriler](https://i18n.nuxtjs.org/docs/guide/per-component-translations) sunar ve Angular, [Feature Modules](https://v17.angular.io/guide/feature-modules) aracılığıyla benzer bir desen kullanır.
21
+
22
+ Hatta bir Flutter uygulamasında bile genellikle şu desenle karşılaşırız:
23
+
24
+ ```bash
25
+ lib/
26
+ └── features/
27
+ └── login/
28
+ ├── login_screen.dart
29
+ └── login_screen.i18n.dart # <- Çeviriler burada yer alır
30
+ ```
31
+
32
+ ```dart fileName='lib/features/login/login_screen.i18n.dart'
33
+ import 'package:i18n_extension/i18n_extension.dart';
34
+
35
+ extension Localization on String {
36
+ static var _t = Translations.byText("en") +
37
+ {
38
+ "Hello": {
39
+ "en": "Hello",
40
+ "fr": "Bonjour",
41
+ },
42
+ };
43
+
44
+ String get i18n => localize(this, _t);
45
+ }
46
+ ```
47
+
48
+ Ancak React dünyasında genellikle farklı yaklaşımlar görüyoruz; bunları üç kategoride toplayacağım:
49
+
50
+ <Columns>
51
+ <Column>
52
+
53
+ **Merkezi yaklaşım** (i18next, next-intl, react-intl, lingui)
54
+
55
+ - (namespace olmadan) içeriği almak için tek bir kaynak kullanır. Varsayılan olarak, uygulamanız yüklendiğinde tüm sayfalardaki içeriği yüklersiniz.
56
+
57
+ </Column>
58
+ <Column>
59
+
60
+ **Granüler yaklaşım** (intlayer, inlang)
61
+
62
+ - içerik alımını anahtar başına veya bileşen başına ince taneli olarak yapar.
63
+
64
+ </Column>
65
+ </Columns>
66
+
67
+ > Bu blogda, zaten burada ele aldığım derleyici tabanlı çözümlere odaklanmayacağım: [Derleyici vs Deklaratif i18n](https://github.com/aymericzip/intlayer/blob/main/docs/blog/tr/compiler_vs_declarative_i18n.md).
68
+ > Derleyici tabanlı i18n (ör. Lingui) yalnızca içeriğin çıkarılmasını ve yüklenmesini otomatikleştirir. İçeride genellikle diğer yaklaşımlarla aynı sınırlamaları paylaşırlar.
69
+
70
+ > İçeriği ne kadar ince taneli alırsanız, bileşenlerinize ekstra state ve mantık ekleme riski o kadar artar.
71
+
72
+ Granüler yaklaşımlar merkezi olanlardan daha esnektir, ancak bu genellikle bir ödündür. Bu kütüphaneler "tree shaking" sunduklarını iddia etseler bile, pratikte genellikle bir sayfayı her dil için yüklersiniz.
73
+
74
+ Genel olarak karar kabaca şu şekilde özetlenebilir:
75
+
76
+ - Uygulamanızda dil sayısından daha fazla sayfa varsa, granüler yaklaşımı tercih etmelisiniz.
77
+ - Sayfa sayısından daha fazla diliniz varsa, merkezi yaklaşıma yönelmelisiniz.
78
+
79
+ Elbette, kütüphane yazarları bu sınırlamaların farkındadır ve çözüm yolları sağlarlar. Bunlar arasında: namespaces'lere bölme, JSON dosyalarını dinamik olarak yükleme (`await import()`), veya derleme zamanında içeriği temizleme yer alır.
80
+
81
+ Aynı zamanda, içeriğinizi dinamik olarak yüklediğinizde sunucunuza ek istekler gönderdiğinizi bilmelisiniz. Her ek `useState` veya hook, ekstra bir sunucu isteği anlamına gelir.
82
+
83
+ > Bu noktayı düzeltmek için, Intlayer birden fazla içerik tanımını aynı anahtar altında gruplamanızı önerir; Intlayer daha sonra bu içerikleri birleştirecektir.
84
+
85
+ Ancak tüm bu çözümlere bakıldığında, en popüler yaklaşımın merkezi (centralized) yaklaşım olduğu açıktır.
86
+
87
+ ### Peki Merkezi yaklaşım neden bu kadar popüler?
88
+
89
+ - Öncelikle, i18next yaygın olarak kullanılan ilk çözümdü; PHP ve Java mimarilerinden (MVC) esinlenen, sorumlulukların sıkı bir ayrımına (içeriği koddan ayrı tutma) dayanan bir felsefeyi takip etti. 2011'de ortaya çıktı ve Component-Based Architectures (React gibi) yönündeki büyük değişimden bile önce kendi standartlarını belirledi.
90
+ - Sonra, bir kütüphane yaygın olarak benimsendiğinde, ekosistemi farklı yaklaşımlara kaydırmak zorlaşır.
91
+ - Merkezi bir yaklaşım kullanmak ayrıca Crowdin, Phrase veya Localized gibi Çeviri Yönetim Sistemlerinde işleri kolaylaştırır.
92
+ - Bileşen başına (per-component) yaklaşımın mantığı merkezi olandan daha karmaşıktır ve geliştirilmesi daha fazla zaman alır, özellikle içeriğin nerede bulunduğunu tespit etmek gibi problemleri çözmeniz gerektiğinde.
93
+
94
+ ### Peki, ama neden sadece Centralized bir yaklaşıma bağlı kalmayalım?
95
+
96
+ Uygulamanız için neden sorunlu olabileceğini söyleyeyim:
97
+
98
+ - **Kullanılmayan Veri:** Bir sayfa yüklendiğinde genellikle tüm diğer sayfaların içeriğini de yüklersiniz. (10 sayfalık bir uygulamada bu, yüklenen içeriğin %90'ının kullanılmaması demektir). Bir modal'ı tembel yükleme (lazy load) ile mi yüklüyorsunuz? i18n kütüphanesi umursamaz, önce yine de stringleri yükler.
99
+ - **Performans:** Her yeniden render'da, bileşenlerinizin her biri devasa bir JSON payload ile hydrate edilir; bu, uygulamanız büyüdükçe reaktivitesini etkiler.
100
+ - **Bakım:** Büyük JSON dosyalarını sürdürmek zahmetlidir. Bir çeviri eklemek için dosyalar arasında atlamanız gerekir; eksik çeviri olmadığından ve geride **orphan keys** kalmadığından emin olmalısınız.
101
+ - **Tasarım sistemi:**
102
+ Bu, design system'lerle uyumsuzluk yaratır (örn. bir `LoginForm` bileşeni) ve bileşenlerin farklı uygulamalar arasında çoğaltılmasını kısıtlar.
103
+
104
+ **"Ama Namespaces'i icat ettik!"**
105
+
106
+ Evet, bu büyük bir ilerleme. Vite + React + React Router v7 + Intlayer kurulumu için ana bundle boyutunun karşılaştırmasına bakalım. 20 sayfalık bir uygulama simüle ettik.
107
+
108
+ İlk örnek locale başına lazy-loaded çeviriler içermez ve namespace ayrımı yapmaz. İkinci örnek içerik temizleme + çeviriler için dinamik yükleme içerir.
109
+
110
+ | Optimize edilmiş bundle | Optimize edilmemiş bundle |
111
+ | ------------------------------------------------------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------ |
112
+ | ![optimize edilmemiş bundle](https://github.com/aymericzip/intlayer/blob/main/docs/assets/bundle_no_optimization.png?raw=true) | ![optimize edilmiş bundle](https://github.com/aymericzip/intlayer/blob/main/docs/assets/bundle.png?raw=true) |
113
+
114
+ Bu nedenle namespaces sayesinde şu yapıdan şu yapıya geçtik:
115
+
116
+ ```bash
117
+ locale/
118
+ ├── en.json
119
+ ├── fr.json
120
+ └── es.json
121
+ ```
122
+
123
+ To this one:
124
+
125
+ ```bash
126
+ locale/
127
+ ├── en/
128
+ │ ├── common.json
129
+ │ ├── navbar.json
130
+ │ ├── footer.json
131
+ │ ├── home.json
132
+ │ └── about.json
133
+ ├── fr/
134
+ │ └── ...
135
+ └── es/
136
+ └── ...
137
+
138
+ ```
139
+
140
+ Artık uygulamanızın hangi içeriğinin nerede ve ne zaman yükleneceğini ince ayrıntısına kadar yönetmeniz gerekiyor. Sonuç olarak, karmaşıklık nedeniyle projelerin büyük çoğunluğu bu kısmı atlıyor (örneğin (sadece) iyi uygulamaları takip etmenin getirdiği zorlukları görmek için [next-i18next rehberi](https://github.com/aymericzip/intlayer/blob/main/docs/blog/tr/i18n_using_next-i18next.md)'ne bakın).
141
+ Buna bağlı olarak, bu projeler daha önce açıklanan devasa JSON yükleme sorunuyla karşılaşıyor.
142
+
143
+ > Not: Bu sorun yalnızca i18next'e özgü değildir; yukarıda listelenen tüm merkezi yaklaşımlar için geçerlidir.
144
+
145
+ Ancak size hatırlatmak isterim ki tüm granüler yaklaşımlar bunu çözmez. Örneğin, `vue-i18n SFC` veya `inlang` yaklaşımları çevirileri her locale için varsayılan olarak tembel yükleme (lazy load) yapmaz; böylece paket boyutu sorununu başka bir sorunla takas etmiş olursunuz.
146
+
147
+ Ayrıca, uygun bir sorumluluk ayrımı olmadan, çevirilerinizi inceleme için çevirmenlere çıkarmak ve sağlamak çok daha zor hale gelir.
148
+
149
+ ### Intlayer'ın bileşen başına yaklaşımı bunu nasıl çözer
150
+
151
+ Intlayer birkaç adımda ilerler:
152
+
153
+ 1. **Deklarasyon:** İçeriğinizi kod tabanınızın herhangi bir yerine `*.content.{ts|jsx|cjs|json|json5|...}` dosyaları kullanarak tanımlayın. Bu, içeriği aynı konumda tutarken sorumlulukların ayrılmasını sağlar. Bir content dosyası locale başına veya çokdilli olabilir.
154
+ 2. **İşleme:** Intlayer, JS mantığını işlemek, eksik çeviri fallback'larını yönetmek, TypeScript tipleri üretmek, yinelenen içeriği yönetmek, CMS'inizden içerik almak ve daha fazlası için bir build adımı çalıştırır.
155
+ 3. **Temizleme:** Uygulamanız build edildiğinde, Intlayer kullanılmayan içeriği (Tailwind'in sınıfları nasıl yönettiğine biraz benzer şekilde) aşağıdaki gibi içerikleri değiştirerek temizler:
156
+
157
+ **Deklarasyon:**
158
+
159
+ ```tsx
160
+ // src/MyComponent.tsx
161
+ export const MyComponent = () => {
162
+ const content = useIntlayer("my-key");
163
+ return <h1>{content.title}</h1>;
164
+ };
165
+ ```
166
+
167
+ ```tsx
168
+ // src/myComponent.content.ts
169
+ export const {
170
+ key: "my-key",
171
+ content: t({
172
+ tr: { title: "Başlığım" },
173
+ en: { title: "My title" },
174
+ fr: { title: "Mon titre" }
175
+ })
176
+ }
177
+
178
+ ```
179
+
180
+ **İşleme:** Intlayer, `.content` dosyasına dayanarak sözlüğü oluşturur ve şunları üretir:
181
+
182
+ ```json5
183
+ // .intlayer/dynamic_dictionary/en/my-key.json (JSON dosyası)
184
+ {
185
+ "key": "my-key",
186
+ "content": { "title": "My title" },
187
+ }
188
+ ```
189
+
190
+ **Yerine Koyma:** Intlayer, uygulama derlemesi sırasında bileşeninizi dönüştürür.
191
+
192
+ **- Statik İçe Aktarma Modu:**
193
+
194
+ ```tsx
195
+ // Bileşenin JSX-benzeri sözdizimindeki gösterimi
196
+ export const MyComponent = () => {
197
+ const content = useDictionary({
198
+ key: "my-key",
199
+ content: {
200
+ nodeType: "translation",
201
+ translation: {
202
+ en: { title: "My title" },
203
+ fr: { title: "Mon titre" },
204
+ },
205
+ },
206
+ });
207
+
208
+ return <h1>{content.title}</h1>;
209
+ };
210
+ ```
211
+
212
+ **- Dinamik İçe Aktarma Modu:**
213
+
214
+ ```tsx
215
+ // Bileşenin JSX-benzeri sözdizimindeki gösterimi
216
+ export const MyComponent = () => {
217
+ const content = useDictionaryAsync({
218
+ en: () =>
219
+ import(".intlayer/dynamic_dictionary/en/my-key.json", {
220
+ with: { type: "json" },
221
+ }).then((mod) => mod.default),
222
+ // Same for other languages
223
+ });
224
+
225
+ return <h1>{content.title}</h1>;
226
+ };
227
+ ```
228
+
229
+ > `useDictionaryAsync`, yalnızca gerektiğinde yerelleştirilmiş JSON'u yüklemek için Suspense-benzeri bir mekanizma kullanır.
230
+
231
+ **Bu bileşen-bağımlı yaklaşımın ana faydaları:**
232
+
233
+ - İçerik bildiriminizi bileşenlerinize yakın tutmak, daha iyi bakım kolaylığı sağlar (ör. bir bileşeni başka bir uygulamaya veya tasarım sistemine taşımak). Bileşen klasörünü silmek, ilgili içeriği de kaldırır; tıpkı muhtemelen `.test`, `.stories` dosyalarınız için yaptığınız gibi.
234
+
235
+ - Bileşen başına yaklaşım, AI ajanlarının tüm farklı dosyalarınız arasında atlamasına gerek kalmasını engeller. Tüm çevirileri tek bir yerde ele alarak görevin karmaşıklığını ve kullanılan token miktarını sınırlar.
236
+
237
+ ### Sınırlamalar
238
+
239
+ Elbette, bu yaklaşım bazı ödünler gerektirir:
240
+
241
+ - Diğer l10n sistemlerine ve ek araçlara bağlanmak daha zor olur.
242
+ - Bağımlı hale gelirsiniz (ki bu, belirli sözdizimleri nedeniyle zaten her i18n çözümünde olan bir durumdur).
243
+
244
+ İşte bu yüzden Intlayer, kendi AI Provider ve API keys'inizi kullanarak AI çevirisini de içeren i18n için eksiksiz bir araç seti sağlamaya çalışır (100% ücretsiz ve OSS). Intlayer ayrıca JSON'unuzu senkronize etmeye yarayan araçlar da sağlar; bu araçlar ICU / vue-i18n / i18next mesaj formatlayıcıları gibi çalışarak içeriği bu özel formatlara eşler.