@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,118 +20,201 @@ slugs:
20
20
 
21
21
  # Аргументы за и против интернационализации на основе компилятора
22
22
 
23
- Если вы разрабатываете веб-приложения более десяти лет, вы знаете, что интернационализация (i18n) всегда была источником сложностей. Это часто та задача, которую никто не хочет выполнять — извлечение строк, управление JSON-файлами и заботы о правилах множественного числа.
23
+ Если вы разрабатываете веб-приложения более десяти лет, вы знаете, что интернационализация (i18n) всегда была проблемной зоной. Это часто та задача, которую никто не хочет выполнять — извлечение строк, управление JSON-файлами и заботы о правилах множественного числа.
24
24
 
25
- В последнее время появилась новая волна инструментов i18n на основе «компилятора», обещающих избавить от этих проблем. Обещание звучит заманчиво: **Просто пишите текст в своих компонентах, а остальное пусть сделает инструмент сборки.** Без ключей, без импортов, просто магия.
25
+ В последнее время появилась новая волна **инструментов i18n на основе компилятора**, обещающих избавить от этих проблем. Обещание звучит заманчиво: **просто пишите текст в своих компонентах, а остальное пусть делает сборщик.** Без ключей, без импортов, просто магия.
26
26
 
27
- Но, как и во всех абстракциях в программной инженерии, магия имеет свою цену.
27
+ Но, как и со всеми абстракциями в программной инженерии, магия имеет свою цену.
28
28
 
29
29
  В этом блоге мы рассмотрим переход от декларативных библиотек к подходам на основе компилятора, скрытые архитектурные долги, которые они вносят, и почему «скучный» способ может оставаться лучшим для профессиональных приложений.
30
30
 
31
- ## Краткая история перевода
31
+ ## Содержание
32
32
 
33
- Чтобы понять, где мы сейчас, нужно оглянуться назад и вспомнить, с чего мы начинали.
33
+ <TOC/>
34
34
 
35
- Около 2011–2012 годов ландшафт JavaScript был кардинально другим. Такие бандлеры, как мы их знаем сегодня (Webpack, Vite), либо не существовали, либо только зарождались. Мы склеивали скрипты прямо в браузере. В эту эпоху появились библиотеки, такие как **i18next**.
35
+ ## Краткая история интернационализации
36
+
37
+ Чтобы понять, где мы сейчас, нужно оглянуться назад, с чего мы начинали.
38
+
39
+ Около 2011–2012 годов ландшафт JavaScript был кардинально другим. Такие сборщики, как мы их знаем сегодня (Webpack, Vite), либо не существовали, либо только начинали развиваться. Мы склеивали скрипты прямо в браузере. В эту эпоху появились библиотеки, такие как **i18next**.
36
40
 
37
41
  Они решили проблему единственным возможным на тот момент способом: **словарями во время выполнения**. Вы загружали огромный JSON-объект в память, и функция искала ключи на лету. Это было надежно, явно и работало везде.
38
42
 
39
- Перенесемся в настоящее. У нас есть мощные компиляторы (SWC, бандлеры на базе Rust), которые могут парсить абстрактные синтаксические деревья (AST) за миллисекунды. Эта мощь породила новую идею: _Зачем нам вручную управлять ключами? Почему компилятор просто не видит текст "Hello World" и не заменит его за нас?_
43
+ Перенесемся в сегодняшний день. У нас есть мощные компиляторы (SWC, сборщики на базе Rust), которые могут парсить абстрактные синтаксические деревья (AST) за миллисекунды. Эта мощь породила новую идею: _Почему мы вручную управляем ключами? Почему компилятор не может просто увидеть текст "Hello World" и заменить его за нас?_
44
+
45
+ Так родилась интернационализация на основе компилятора.
46
+
47
+ > **Пример компиляторного i18n:**
48
+ >
49
+ > - Paraglide (Модули с tree-shaking, которые компилируют каждое сообщение в маленькую ESM-функцию, чтобы сборщики могли автоматически исключать неиспользуемые локали и ключи. Вы импортируете сообщения как функции вместо поиска по строковым ключам.)
50
+ > - LinguiJS (Компилятор макросов в функции, который переписывает макросы сообщений, такие как `<Trans>`, в обычные вызовы JS-функций во время сборки. Вы получаете синтаксис ICU/MessageFormat с очень маленьким runtime-футпринтом.)
51
+ > - Lingo.dev (Сфокусирован на автоматизации локализационного пайплайна путем внедрения переведенного контента непосредственно во время сборки вашего React-приложения. Может автоматически генерировать переводы с помощью ИИ и интегрироваться напрямую в CI/CD.)
52
+ > - Wuchale (Препроцессор, ориентированный на Svelte, который извлекает встроенный текст из файлов .svelte и компилирует его в функции перевода без обёрток. Избегает использования строковых ключей и полностью отделяет логику извлечения контента от основного runtime приложения.)
53
+ > - Intlayer (Компилятор / CLI для извлечения, который парсит ваши компоненты, генерирует типизированные словари и может опционально переписывать код для использования явного контента Intlayer. Цель — использовать компилятор для скорости, сохраняя декларативное, фреймворк-независимое ядро.)
54
+
55
+ > **Пример декларативного i18n:**
56
+ >
57
+ > - i18next / react-i18next / next-i18next (Зрелый промышленный стандарт, использующий JSON-словарь во время выполнения и обширную экосистему плагинов)
58
+ > - react-intl (Часть библиотеки FormatJS, ориентированная на стандартный синтаксис сообщений ICU и строгий формат данных)
59
+ > - next-intl (Оптимизирован специально для Next.js с интеграцией для App Router и React Server Components)
60
+ > - vue-i18n / @nuxt/i18n (Стандартное решение экосистемы Vue, предлагающее блоки перевода на уровне компонентов и тесную интеграцию реактивности)
61
+ > - svelte-i18n (Легковесная обёртка вокруг Svelte stores для реактивных переводов во время выполнения)
62
+ > - angular-translate (Устаревшая библиотека динамического перевода, основанная на поиске ключей во время выполнения, а не на слиянии во время сборки)
63
+ > - angular-i18n (Нативный подход Angular с предварительной компиляцией, объединяющий XLIFF файлы непосредственно в шаблоны во время сборки)
64
+ > - Tolgee (Сочетает декларативный код с SDK для редактирования «клик для перевода» непосредственно в интерфейсе)
65
+ > - Intlayer (Подход на уровне компонентов с использованием файлов деклараций контента, обеспечивающих нативный tree-shaking и валидацию TypeScript)
66
+
67
+ ## Компилятор Intlayer
68
+
69
+ Хотя **Intlayer** — это решение, которое в основе своей поощряет **декларативный подход** к вашему контенту, оно включает компилятор, который помогает ускорить разработку или облегчить быстрое прототипирование.
70
+
71
+ Компилятор Intlayer проходит по AST (Абстрактному Синтаксическому Дереву) ваших компонентов React, Vue или Svelte, а также других файлов JavaScript/TypeScript. Его задача — обнаруживать жестко закодированные строки и извлекать их в выделенные декларации `.content`.
40
72
 
41
- Так родился i18n на основе компилятора.
73
+ > Для получения дополнительной информации ознакомьтесь с документацией: [Документация компилятора Intlayer](https://github.com/aymericzip/intlayer/blob/main/docs/docs/ru/compiler.md)
42
74
 
43
75
  ## Привлекательность компилятора (подход "магии")
44
76
 
45
- Есть причина, по которой этот новый подход набирает популярность. Для разработчика опыт кажется невероятным.
77
+ Есть причина, по которой этот новый подход становится популярным. Для разработчика опыт кажется невероятным.
46
78
 
47
- ### 1. Скорость и "погружение"
79
+ ### 1. Скорость и "поток"
48
80
 
49
- Когда вы полностью сосредоточены, остановка, чтобы придумать имя переменной (`home_hero_title_v2`), нарушает ваш поток работы. С подходом компилятора вы просто пишете `<p>Welcome back</p>` и продолжаете. Трения нет.
81
+ Когда вы полностью погружены в работу, остановка, чтобы придумать семантическое имя переменной (`home_hero_title_v2`), прерывает ваш поток. С подходом компилятора вы просто вводите `<p>Welcome back</p>` и продолжаете работать. Трения нет.
50
82
 
51
- ### 2. Миссия спасения наследия
83
+ ### 2. Миссия по спасению наследия
52
84
 
53
- Представьте, что вы унаследовали огромную кодовую базу с 5000 компонентов и нулевыми переводами. Переделка этого с помощью ручной системы ключей — это кошмар, который может занять месяцы. Инструмент на базе компилятора действует как стратегия спасения, мгновенно извлекая тысячи строк без необходимости вручную трогать ни один файл.
85
+ Представьте, что вы унаследовали огромную кодовую базу с 5000 компонентов и отсутствием переводов. Переделка этого с помощью ручной системы на основе ключей — это кошмар, который может занять месяцы. Инструмент на основе компилятора выступает как спасательная стратегия, мгновенно извлекая тысячи строк без необходимости вручную трогать ни один файл.
54
86
 
55
87
  ### 3. Эра ИИ
56
88
 
57
- Это современное преимущество, которое не стоит упускать из виду. Ассистенты по написанию кода на базе ИИ (например, Copilot или ChatGPT) естественным образом генерируют стандартный JSX/HTML. Они не знают вашу конкретную схему ключей для перевода.
89
+ Это современное преимущество, которое не стоит упускать из виду. Помощники по программированию на базе ИИ (такие как Copilot или ChatGPT) естественным образом генерируют стандартный JSX/HTML. Они не знают вашу конкретную схему ключей перевода.
58
90
 
59
- - **Декларативный:** вам нужно переписать вывод ИИ, чтобы заменить текст на ключи.
60
- - **Компилятор:** вы копируете и вставляете код ИИ, и он просто работает.
91
+ - **Декларативный подход:** Вам нужно переписать вывод ИИ, чтобы заменить текст на ключи.
92
+ - **Компилятор:** Вы копируете и вставляете код ИИ, и он просто работает.
61
93
 
62
- ## Проверка реальности: почему "магия" опасна
94
+ ## Проверка реальности: почему «магия» опасна
63
95
 
64
- Хотя "магия" привлекательна, абстракция протекает. Полагаться на инструмент сборки, чтобы понять человеческие намерения, вводит архитектурную хрупкость.
96
+ Хотя «магия» и привлекательна, абстракция протекает. Полагаться на инструмент сборки, чтобы он понимал человеческие намерения, приводит к архитектурной хрупкости.
65
97
 
66
- ### 1. Эвристическая хрупкость (игра в угадайку)
98
+ ### Эвристическая хрупкость (Игра в угадайку)
67
99
 
68
- Компилятор должен угадывать, что является контентом, а что — кодом.
100
+ Компилятору приходится угадывать, что является контентом, а что — кодом. Это приводит к крайним случаям, когда вы в итоге «боретесь» с инструментом.
69
101
 
70
- - Переводится ли `className="active"`? Это строка.
71
- - Переводится ли `status="pending"`?
72
- - Переводится ли `<MyComponent errorMessage="An error occurred" />`?
73
- - Переводится ли идентификатор продукта, например `"AX-99"`?
102
+ Рассмотрим эти сценарии:
74
103
 
75
- В конечном итоге вы неизбежно начинаете "бороться" с компилятором, добавляя специальные комментарии (например, `// ignore-translation`), чтобы предотвратить нарушение логики вашего приложения.
104
+ - Будет ли извлечён `<span className="active"></span>`? (Это строка, но скорее всего класс).
105
+ - Будет ли извлечён `<span status="pending"></span>`? (Это значение пропса).
106
+ - Будет ли извлечён `<span>{"Hello World"}</span>`? (Это JS-выражение).
107
+ - Будет ли извлечён `<span>Hello {name}. How are you?</span>`? (Интерполяция сложна).
108
+ - Будет ли извлечён `<span aria-label="Image of cat"></span>`? (Атрибуты доступности требуют перевода).
109
+ - Извлекается ли `<span data-testid="my-element"></span>`? (Идентификаторы тестов НЕ должны переводиться).
110
+ - Извлекается ли `<MyComponent errorMessage="An error occurred" />`?
111
+ - Извлекается ли `<p>This is a paragraph{" "}\n containing multiple lines</p>`?
112
+ - Извлекается ли результат функции `<p>{getStatusMessage()}</p>`?
113
+ - Извлекается ли `<div>{isLoading ? "The page is loading" : <MyComponent/>} </div>`?
114
+ - Извлекается ли идентификатор продукта, например `<span>AX-99</span>`?
76
115
 
77
- ### 2. Жесткое ограничение динамических данных
116
+ В конечном итоге вы неизбежно добавляете специальные комментарии (например, `// ignore-translation` или специальные пропсы, такие как `data-compiler-ignore="true"`), чтобы предотвратить нарушение логики вашего приложения.
117
+
118
+ ### Как Intlayer справляется с этой сложностью?
119
+
120
+ Intlayer использует смешанный подход для определения, следует ли извлекать поле для перевода, пытаясь минимизировать ложные срабатывания:
121
+
122
+ 1. **Анализ AST:** Проверяется тип элемента (например, различие между `reactNode`, `label` или пропсом `title`).
123
+ 2. **Распознавание шаблонов:** Определяется, начинается ли строка с заглавной буквы или содержит пробелы, что указывает на то, что это, скорее всего, читаемый человеком текст, а не идентификатор кода.
124
+
125
+ ### Жесткое ограничение для динамических данных
78
126
 
79
127
  Извлечение компилятором основано на **статическом анализе**. Он должен видеть буквальную строку в вашем коде, чтобы сгенерировать стабильный ID.
80
- Если ваш API возвращает строку с кодом ошибки, например `server_error`, вы не сможете перевести её с помощью компилятора, потому что компилятор не знает о существовании этой строки во время сборки. Вам придется создавать вторичную систему "только во время выполнения" специально для динамических данных.
128
+ Если ваш API возвращает строку с кодом ошибки, например `server_error`, вы не можете перевести её с помощью компилятора, потому что компилятор не знает о существовании этой строки во время сборки. Вам придется создать вторичную систему, работающую только во время выполнения, специально для динамических данных.
129
+
130
+ ### Отсутствие разбиения на чанки
131
+
132
+ Некоторые компиляторы не разбивают переводы по страницам. Если ваш компилятор генерирует большой JSON-файл на каждый язык (например, `./lang/en.json`, `./lang/fr.json` и т.д.), вы, вероятно, загрузите контент со всех ваших страниц при посещении только одной. Кроме того, каждый компонент, использующий ваш контент, скорее всего, будет гидратирован с гораздо большим объемом данных, чем необходимо, что потенциально может вызвать проблемы с производительностью.
133
+
134
+ Также будьте осторожны с динамической загрузкой переводов. Если этого не сделать, вы загрузите контент для всех языков помимо текущего.
81
135
 
82
- ### 3. "Взрыв чанков" и сетевые водопады
136
+ > Чтобы проиллюстрировать проблему, рассмотрим сайт с 10 страницами и 10 языками (все 100% уникальные). Вы загрузите контент для 99 дополнительных страниц (10 × 10 - 1).
83
137
 
84
- Для поддержки tree-shaking инструменты компилятора часто разбивают переводы по компонентам.
138
+ ### «Взрыв чанков» и сетевые водопады
85
139
 
86
- - **Последствие:** Один просмотр страницы с 50 небольшими компонентами может вызвать **50 отдельных HTTP-запросов** для маленьких фрагментов перевода. Даже с HTTP/2 это создает сетевой "водопад", из-за которого ваше приложение кажется медленным по сравнению с загрузкой одного оптимизированного языкового пакета.
140
+ Для решения проблемы чанкинга некоторые решения предлагают делить контент на чанки по компонентам или даже по ключам. Однако проблема решается лишь частично. Основным аргументом в пользу таких решений часто является утверждение «Ваш контент подвергается tree-shaking».
87
141
 
88
- ### 4. Нагрузка на производительность во время выполнения
142
+ Действительно, если вы загружаете контент статически, ваше решение удалит неиспользуемый контент, но в итоге вы всё равно загрузите контент со всех языков вместе с вашим приложением.
89
143
 
90
- Чтобы сделать переводы реактивными (чтобы они обновлялись мгновенно при переключении языков), компилятор часто внедряет хуки управления состоянием в _каждый_ компонент.
144
+ Так почему бы не загружать контент динамически? Да, в этом случае вы загрузите больше, чем необходимо, но это не обходится без компромиссов.
91
145
 
92
- - **Стоимость:** Если вы рендерите список из 5000 элементов, вы инициализируете 5000 хуков `useState` и `useEffect` исключительно для текста. Это потребляет память и ресурсы процессора, которые декларативные библиотеки (которые обычно используют один провайдер Context) экономят.
146
+ Динамическая загрузка контента изолирует каждый фрагмент контента в отдельный чанк, который загружается только при рендеринге компонента. Это означает, что вы будете делать один HTTP-запрос на каждый текстовый блок. 1000 текстовых блоков на вашей странице? → 1000 HTTP-запросов к вашим серверам. И чтобы ограничить ущерб и оптимизировать время первого рендера вашего приложения, вам придется вставить несколько границ Suspense или Skeleton Loaders.
147
+
148
+ > Примечание: Даже с Next.js и SSR ваши компоненты будут гидратированы после загрузки, поэтому HTTP-запросы все равно будут сделаны.
149
+
150
+ Решение? Использовать подход, который позволяет объявлять локализованные декларации контента, как это делают `i18next`, `next-intl` или `intlayer`.
151
+
152
+ > Примечание: `i18next` и `next-intl` требуют от вас вручную управлять импортами пространств имён / сообщений для каждой страницы, чтобы оптимизировать размер бандла. Рекомендуется использовать анализатор бандлов, такой как `rollup-plugin-visualizer` (vite), `@next/bundle-analyzer` (next.js) или `webpack-bundle-analyzer` (React CRA / Angular / и т.д.), чтобы определить, не засоряете ли вы бандл неиспользуемыми переводами.
153
+
154
+ ### Накладные расходы на производительность во время выполнения
155
+
156
+ Чтобы сделать переводы реактивными (чтобы они обновлялись мгновенно при переключении языков), компилятор часто внедряет хуки управления состоянием в каждый компонент.
157
+
158
+ - **Стоимость:** Если вы рендерите список из 5000 элементов, вы инициализируете 5000 хуков `useState` и `useEffect` исключительно для текста. React должен идентифицировать и повторно отрендерить всех 5000 потребителей одновременно. Это вызывает масштабную блокировку "Главного потока", замораживая UI во время переключения. Это потребляет память и ресурсы CPU, которые декларативные библиотеки (которые обычно используют одного провайдера Context) экономят.
159
+
160
+ > Обратите внимание, что подобная проблема возникает и в других фреймворках, не только в React.
93
161
 
94
162
  ## Ловушка: Зависимость от поставщика
95
163
 
96
- Это, пожалуй, самый опасный аспект i18n на основе компилятора.
164
+ Будьте осторожны при выборе решения для i18n, которое позволяет извлекать или мигрировать ключи переводов.
97
165
 
98
- В декларативной библиотеке ваш исходный код содержит явное намерение. Вы владеете ключами. Если вы меняете библиотеку, вы просто меняете импорт.
166
+ В случае декларативной библиотеки ваш исходный код явно содержит ваш переводческий замысел: это ваши ключи, и вы ими управляете. Если вы хотите сменить библиотеку, обычно достаточно просто обновить импорт.
99
167
 
100
- В подходе на основе компилятора **ваш исходный код это просто английский текст.** "Логика перевода" существует только внутри конфигурации плагина сборки.
101
- Если эта библиотека перестанет поддерживаться или вы перерастёте её, вы окажетесь в ловушке. Вы не сможете легко "выйти" из неё, потому что в вашем исходном коде нет ни одного ключа перевода. Вам придётся вручную переписать всё приложение, чтобы мигрировать на другую систему.
168
+ При использовании подхода с компилятором ваш исходный код может содержать просто обычный английский текст, без следов логики перевода: всё скрыто в конфигурации сборочного инструмента. Если этот плагин перестанет поддерживаться или вы захотите сменить решение, вы можете оказаться в затруднительном положении. Нет простого способа «выйти»: в вашем коде нет используемых ключей, и возможно, вам придётся заново сгенерировать все переводы для новой библиотеки.
102
169
 
103
- ## Другая сторона: риски декларативного подхода
170
+ Некоторые решения также предлагают сервисы генерации переводов. Нет кредитов? Нет переводов.
104
171
 
105
- Честно говоря, традиционный декларативный способ тоже не идеален. У него есть свои "подводные камни".
172
+ Компиляторы часто хешируют текст (например, `"Hello World"` -> `x7f2a`). Ваши файлы переводов выглядят как `{ "x7f2a": "Hola Mundo" }`. Ловушка: если вы смените библиотеку, новая библиотека увидит `"Hello World"` и будет искать этот ключ. Она не найдёт его, потому что ваш файл перевода заполнен хешами (`x7f2a`).
106
173
 
107
- 1. **Ад namespace:** Часто приходится вручную управлять тем, какие JSON-файлы загружать (`common.json`, `dashboard.json`, `footer.json`). Если вы забудете один из них, пользователь увидит необработанные ключи.
108
- 2. **Перезагрузка:** Без тщательной настройки очень легко случайно загрузить _все_ ключи перевода для _всех_ страниц при первоначальной загрузке, что увеличивает размер вашего бандла.
109
- 3. **Синхронизационный дрейф:** Часто ключи остаются в JSON-файле задолго после того, как компонент, использующий их, был удалён. Ваши файлы перевода растут бесконечно, заполненные "зомби-ключами".
174
+ ### Привязка к платформе
175
+
176
+ Выбирая подход на основе компилятора, вы привязываете себя к базовой платформе. Например, некоторые компиляторы недоступны для всех бандлеров (таких как Vite, Turbopack или Metro). Это может затруднить будущие миграции, и вам может потребоваться принять несколько решений для покрытия всех ваших приложений.
177
+
178
+ ## Обратная сторона: риски декларативного подхода
179
+
180
+ Если быть честным, традиционный декларативный способ тоже не идеален. У него есть свои "подводные камни".
181
+
182
+ 1. **Адская путаница с пространствами имён:** часто приходится вручную управлять тем, какие JSON-файлы загружать (`common.json`, `dashboard.json`, `footer.json`). Если вы забудете один, пользователь увидит необработанные ключи.
183
+ 2. **Перегрузка запросов:** Без тщательной настройки очень легко случайно загрузить _все_ ваши ключи перевода для _всех_ страниц при первоначальной загрузке, что увеличивает размер вашего бандла.
184
+ 3. **Синхронизационный дрейф:** Часто ключи остаются в JSON-файле долго после того, как компонент, использующий их, был удалён. Ваши файлы перевода растут бесконечно, заполненные "зомби-ключами".
110
185
 
111
186
  ## Средний путь Intlayer
112
187
 
113
- Именно здесь такие инструменты, как **Intlayer**, пытаются внести инновации. Intlayer понимает, что хотя компиляторы мощные, неявная магия опасна.
188
+ Именно здесь инструменты, такие как **Intlayer**, пытаются внести инновации. Intlayer понимает, что хотя компиляторы мощные, неявная магия опасна.
114
189
 
115
- Intlayer предлагает уникальную команду **`transform`**. Вместо того чтобы просто делать магию на скрытом этапе сборки, она фактически может **переписать ваш код компонента**. Она сканирует ваш текст и заменяет его явными декларациями контента в вашей кодовой базе.
190
+ Intlayer предлагает смешанный подход, позволяющий вам воспользоваться преимуществами обоих подходов: декларативное управление контентом, также совместимое с его компилятором для экономии времени разработки.
116
191
 
117
- Это даёт вам лучшее из обоих миров:
192
+ И даже если вы не используете компилятор Intlayer, Intlayer предлагает команду `transform` (также доступную через расширение VSCode). Вместо того чтобы просто делать магию на скрытом этапе сборки, она фактически **переписывает ваш код компонента**. Она сканирует ваш текст и заменяет его явными декларациями контента в вашей кодовой базе.
193
+
194
+ Это дает вам лучшее из обоих миров:
118
195
 
119
196
  1. **Гранулярность:** Вы держите переводы рядом с вашими компонентами (улучшая модульность и tree-shaking).
120
- 2. **Безопасность:** Перевод становится явным кодом, а не скрытой магией на этапе сборки.
121
- 3. **Отсутствие зависимости:** Поскольку код преобразуется в стандартную декларативную структуру внутри вашего репозитория, вы не скрываете логику в плагине webpack.
197
+ 2. **Безопасность:** Перевод становится явным кодом, а не скрытой магией времени сборки.
198
+ 3. **Отсутствие привязки:** Поскольку код преобразуется в декларативную структуру внутри вашего репозитория, вы можете легко нажать tab или использовать copilot вашего IDE для генерации деклараций контента, вы не прячете логику в плагине webpack.
122
199
 
123
200
  ## Заключение
124
201
 
125
202
  Итак, что же выбрать?
126
203
 
127
- **Если вы начинающий разработчик, соло-фаундер или создаёте MVP:**
128
- Подход на основе компилятора — это приемлемый выбор. Он позволяет двигаться невероятно быстро. Вам не нужно беспокоиться о структуре файлов или ключах. Вы просто создаёте. Технический долг — это проблема "будущего вас".
204
+ **Если вы создаёте MVP или хотите двигаться быстро:**
205
+ Подход на основе компилятора — это разумный выбор. Он позволяет двигаться невероятно быстро. Вам не нужно беспокоиться о структуре файлов или ключах. Просто создавайте. Технический долг — это проблема для «будущего вас».
206
+
207
+ **Если вы младший разработчик или не заботитесь об оптимизации:**
208
+ Если вы хотите минимизировать ручное управление, подход на основе компилятора, вероятно, лучший вариант. Вам не нужно будет самостоятельно обрабатывать ключи или файлы переводов — просто пишите текст, а компилятор автоматизирует остальное. Это снижает усилия по настройке и уменьшает распространённые ошибки i18n, связанные с ручными шагами.
209
+
210
+ **Если вы интернационализируете существующий проект, который уже включает тысячи компонентов для рефакторинга:**
211
+ Компиляторный подход может быть прагматичным выбором в этом случае. Начальная фаза извлечения может сэкономить недели или месяцы ручной работы. Однако рассмотрите возможность использования инструмента, такого как команда `transform` в Intlayer, которая может извлекать строки и преобразовывать их в явные декларативные объявления контента. Это дает вам скорость автоматизации при сохранении безопасности и переносимости декларативного подхода. Вы получаете лучшее из обоих миров: быструю начальную миграцию без долгосрочного архитектурного долга.
129
212
 
130
- **Если вы создаёте профессиональное корпоративное приложение:**
213
+ **Если вы создаете профессиональное приложение корпоративного уровня:**
131
214
  Магия обычно — плохая идея. Вам нужен контроль.
132
215
 
133
216
  - Вам нужно обрабатывать динамические данные с бэкендов.
134
217
  - Вам нужно обеспечить производительность на устройствах с низкими характеристиками (избегая взрывов хуков).
135
- - Вам нужно гарантировать, что вы не будете навсегда привязаны к конкретному инструменту сборки.
218
+ - Вам нужно убедиться, что вы не окажетесь навсегда привязаны к конкретному инструменту сборки.
136
219
 
137
- Для профессиональных приложений **Декларативное управление контентом** (например, Intlayer или проверенные библиотеки) остается золотым стандартом. Оно разделяет ваши задачи, сохраняет архитектуру чистой и гарантирует, что способность вашего приложения поддерживать несколько языков не зависит от "черного ящика" компилятора, который пытается угадать ваши намерения.
220
+ Для профессиональных приложений **Декларативное управление контентом** (например, Intlayer или проверенные библиотеки) остается золотым стандартом. Оно разделяет ваши задачи, сохраняет архитектуру чистой и гарантирует, что способность вашего приложения поддерживать несколько языков не зависит от «черного ящика» компилятора, который пытается угадать ваши намерения.
@@ -20,118 +20,201 @@ slugs:
20
20
 
21
21
  # Derleyici Tabanlı i18n İçin ve Karşı Argümanlar
22
22
 
23
- On yıldan fazla süredir web uygulamaları geliştiriyorsanız, Uluslararasılaştırmanın (i18n) her zaman bir zorluk noktası olduğunu bilirsiniz. Genellikle kimsenin yapmak istemediği bir görevdir—metinleri çıkarmak, JSON dosyalarını yönetmek ve çoğul ek kurallarıyla uğraşmak.
23
+ On yıldan fazla süredir web uygulamaları geliştiriyorsanız, Uluslararasılaştırmanın (i18n) her zaman bir sürtüşme noktası olduğunu bilirsiniz. Genellikle kimsenin yapmak istemediği bir görevdir—metinleri çıkarmak, JSON dosyalarını yönetmek ve çoğul kurallarıyla uğraşmak.
24
24
 
25
- Son zamanlarda, bu acıyı ortadan kaldırmayı vaat eden yeni bir "Derleyici tabanlı" i18n araç dalgası ortaya çıktı. Teklif cazip: **Sadece bileşenlerinizde metni yazın, gerisini derleme aracı halletsin.** Anahtar yok, import yok, sadece sihir.
25
+ Son zamanlarda, bu acıyı ortadan kaldırmayı vaat eden yeni bir **"Derleyici tabanlı" i18n araçları** dalgası ortaya çıktı. Sunum çok cazip: **Sadece bileşenlerinizde metni yazın ve geri kalanını derleme aracı halletsin.** Anahtar yok, import yok, sadece sihir.
26
26
 
27
27
  Ancak yazılım mühendisliğindeki tüm soyutlamalarda olduğu gibi, sihrin de bir bedeli vardır.
28
28
 
29
- Bu blog yazısında, deklaratif kütüphanelerden derleyici tabanlı yaklaşımlara geçişi, getirdikleri gizli mimari borçları ve neden "sıkıcı" yolun profesyonel uygulamalar için hala en iyi yol olabileceğini inceleyeceğiz.
29
+ Bu blog yazısında, deklaratif kütüphanelerden derleyici tabanlı yaklaşımlara geçişi, beraberinde getirdikleri gizli mimari borçları ve neden "sıkıcı" yolun profesyonel uygulamalar için hâlâ en iyi yol olabileceğini inceleyeceğiz.
30
30
 
31
- ## Çevirinin Kısa Tarihi
31
+ ## İçindekiler
32
32
 
33
- Nerede olduğumuzu anlamak için, başladığımız yere bakmamız gerekiyor.
33
+ <TOC/>
34
34
 
35
- 2011–2012 yıllarında, JavaScript dünyası oldukça farklıydı. Bildiğimiz bundlerlar (Webpack, Vite) ya yoktu ya da çok erken aşamalardaydı. Tarayıcıda scriptleri birbirine yapıştırıyorduk. Bu dönemde, **i18next** gibi kütüphaneler doğdu.
35
+ ## Uluslararasılaştırmanın Kısa Tarihi
36
36
 
37
- O zamanlar problemi çözmenin tek yolu vardı: **Çalışma Zamanı Sözlükleri**. Büyük bir JSON nesnesini belleğe yüklüyordunuz ve bir fonksiyon anahtarları anında arıyordu. Bu yöntem güvenilir, açık ve her yerde çalışıyordu.
37
+ Nerede olduğumuzu anlamak için, nereden başladığımıza bakmalıyız.
38
38
 
39
- Bugüne hızlıca gelirsek. Milisaniyeler içinde Abstract Syntax Tree (AST) çözümleyebilen güçlü derleyicilerimiz var (SWC, Rust tabanlı bundlerlar). Bu güç yeni bir fikrin doğmasına yol açtı: _Neden anahtarları manuel olarak yönetiyoruz? Derleyici neden "Hello World" metnini görüp bizim için değiştirmesin?_
39
+ 2011–2012 yıllarında, JavaScript ortamı oldukça farklıydı. Bildiğimiz bundlerlar (Webpack, Vite) ya yoktu ya da çok erken aşamalardaydı. Tarayıcıda scriptleri birbirine yapıştırıyorduk. Bu dönemde, **i18next** gibi kütüphaneler doğdu.
40
+
41
+ O zamanlar problemi çözmenin tek yolu vardı: **Çalışma Zamanı Sözlükleri**. Belleğe devasa bir JSON nesnesi yüklüyordunuz ve bir fonksiyon anahtarları anında arıyordu. Bu yöntem güvenilirdi, açıktı ve her yerde çalışıyordu.
42
+
43
+ Bugüne hızlıca gelirsek, Abstract Syntax Tree (AST) yapısını milisaniyeler içinde analiz edebilen güçlü derleyicilere (SWC, Rust tabanlı bundlerlar) sahibiz. Bu güç yeni bir fikrin doğmasına yol açtı: _Neden anahtarları manuel olarak yönetiyoruz? Derleyici neden "Hello World" metnini görüp bizim için değiştirmesin?_
40
44
 
41
45
  Böylece, Derleyici tabanlı i18n doğdu.
42
46
 
47
+ > **Derleyici tabanlı i18n örnekleri:**
48
+ >
49
+ > - Paraglide (Her mesajı küçük bir ESM fonksiyonuna derleyen ve kullanılmayan yerellerin ve anahtarların bundlerlar tarafından otomatik olarak atılmasını sağlayan tree-shaken modüller. Mesajları string-anahtar araması yapmak yerine fonksiyon olarak import edersiniz.)
50
+ > - LinguiJS (Mesaj makrolarını, örneğin `<Trans>`, derleme zamanında sade JS fonksiyon çağrılarına dönüştüren makrodan-fonksiyona derleyici. Çok küçük bir çalışma zamanı ayak izi ile ICU/MessageFormat sözdizimi sağlar.)
51
+ > - Lingo.dev (React uygulamanızın derlemesi sırasında çevrilmiş içeriği doğrudan enjekte ederek yerelleştirme sürecini otomatikleştirmeye odaklanır. AI kullanarak çevirileri otomatik oluşturabilir ve doğrudan CI/CD süreçlerine entegre olabilir.)
52
+ > - Wuchale (.svelte dosyalarındaki satır içi metni çıkaran ve bunu sıfır-sarmalayıcı çeviri fonksiyonlarına derleyen Svelte-öncelikli bir ön işlemci. String anahtarlarından kaçınır ve içerik çıkarma mantığını ana uygulama çalışma zamanından tamamen ayırır.)
53
+ > - Intlayer (Bileşenlerinizi ayrıştıran, tiplenmiş sözlükler üreten ve isteğe bağlı olarak kodu açık Intlayer içeriği kullanacak şekilde yeniden yazabilen Derleyici / Extract CLI. Amaç, bildirimsel, çerçeveden bağımsız bir çekirdek tutarken derleyiciyi hız için kullanmaktır.)
54
+
55
+ > **Bildirimsel i18n örneği:**
56
+ >
57
+ > - i18next / react-i18next / next-i18next (Çalışma zamanı JSON sözlükleri ve kapsamlı bir eklenti ekosistemi kullanan olgun endüstri standardı)
58
+ > - react-intl (FormatJS kütüphanesinin bir parçası olup, standart ICU mesaj sözdizimi ve sıkı veri biçimlendirmeye odaklanır)
59
+ > - next-intl (Özellikle Next.js için optimize edilmiş olup App Router ve React Server Components ile entegrasyon sağlar)
60
+ > - vue-i18n / @nuxt/i18n (Bileşen düzeyinde çeviri blokları ve sıkı reaktivite entegrasyonu sunan standart Vue ekosistemi çözümü)
61
+ > - svelte-i18n (Reaktif, çalışma zamanı çevirileri için Svelte mağazalarının etrafında hafif bir sarmalayıcı)
62
+ > - angular-translate (Derleme zamanında birleştirme yerine çalışma zamanı anahtar aramalarına dayanan eski dinamik çeviri kütüphanesi)
63
+ > - angular-i18n (Angular'ın yerel, derleme sırasında XLIFF dosyalarını doğrudan şablonlara birleştiren önceden derleme yaklaşımı)
64
+ > - Tolgee (Bildirimsel kodu, kullanıcı arayüzünde doğrudan "tıklayarak çeviri" düzenlemesi için bağlam içi bir SDK ile birleştirir)
65
+ > - Intlayer (Bileşen başına yaklaşım, yerel tree-shaking ve TypeScript doğrulamasını mümkün kılan içerik bildirim dosyalarını kullanır)
66
+
67
+ ## Intlayer Derleyicisi
68
+
69
+ **Intlayer** temelde içeriğinize **bildirimsel bir yaklaşımı** teşvik eden bir çözüm olmasına rağmen, geliştirmeyi hızlandırmak veya hızlı prototiplemeyi kolaylaştırmak için bir derleyici içerir.
70
+
71
+ Intlayer derleyicisi, React, Vue veya Svelte bileşenlerinizin yanı sıra diğer JavaScript/TypeScript dosyalarının AST'sini (Soyut Sözdizim Ağacı) tarar. Görevi, sabit kodlanmış dizeleri tespit etmek ve bunları özel `.content` bildirimlerine çıkarmaktır.
72
+
73
+ > Daha fazla detay için dokümantasyona göz atın: [Intlayer Derleyici Dokümantasyonu](https://github.com/aymericzip/intlayer/blob/main/docs/docs/tr/compiler.md)
74
+
43
75
  ## Derleyicinin Cazibesi ("Sihirli" Yaklaşım)
44
76
 
45
77
  Bu yeni yaklaşımın popüler olmasının bir nedeni var. Bir geliştirici için deneyim inanılmazdır.
46
78
 
47
79
  ### 1. Hız ve "Akış"
48
80
 
49
- İşin içindeyken, bir değişken adı (`home_hero_title_v2`) düşünmek için durmak akışınızı bozar. Derleyici yaklaşımıyla, `<p>Welcome back</p>` yazarsınız ve devam edersiniz. Sürtünme sıfırdır.
81
+ İşin içindeyken, anlamsal bir değişken adı (`home_hero_title_v2`) düşünmek için durmak akışınızı bozar. Derleyici yaklaşımıyla, `<p>Welcome back</p>` yazarsınız ve devam edersiniz. Sürtünme sıfırdır.
50
82
 
51
83
  ### 2. Miras Kurtarma Görevi
52
84
 
53
- 5.000 bileşenli ve hiç çevirisi olmayan devasa bir kod tabanını devraldığınızı hayal edin. Bunu manuel anahtar tabanlı bir sistemle sonradan uyarlamak aylar süren bir kabus olur. Derleyici tabanlı bir araç, tek bir dosyaya elle dokunmanıza gerek kalmadan binlerce metni anında çıkaran bir kurtarma stratejisi olarak görev yapar.
85
+ Büyük, 5.000 bileşenli ve hiç çevirisi olmayan devasa bir kod tabanını devraldığınızı hayal edin. Bunu manuel anahtar tabanlı bir sistemle sonradan uyarlamak aylar süren bir kabus olur. Derleyici tabanlı bir araç ise, tek bir dosyaya elle dokunmanıza gerek kalmadan binlerce metni anında çıkaran bir kurtarma stratejisi olarak çalışır.
54
86
 
55
87
  ### 3. Yapay Zeka Çağı
56
88
 
57
- Bu, göz ardı etmememiz gereken modern bir avantajdır. AI kodlama asistanları (Copilot veya ChatGPT gibi) doğal olarak standart JSX/HTML üretir. Özel çeviri anahtarı şemanızı bilmezler.
89
+ Göz ardı etmememiz gereken modern bir avantajdır bu. Yapay zeka kodlama asistanları (Copilot veya ChatGPT gibi) doğal olarak standart JSX/HTML üretirler. Özel çeviri anahtarı şemanızı bilmezler.
58
90
 
59
- - **Deklaratif:** AI'nın çıktısını, metni anahtarlarla değiştirmek için yeniden yazmanız gerekir.
60
- - **Derleyici:** AI'nın kodunu kopyalayıp yapıştırırsınız ve sadece çalışır.
91
+ - **Deklaratif:** Yapay zekanın çıktısını, metni anahtarlarla değiştirmek için yeniden yazmanız gerekir.
92
+ - **Derleyici:** Yapay zekanın kodunu kopyalayıp yapıştırırsınız, ve bu sadece çalışır.
61
93
 
62
94
  ## Gerçeklik Kontrolü: Neden "Sihir" Tehlikelidir
63
95
 
64
96
  "Sihir" çekici olsa da, soyutlama sızar. İnsan niyetini anlaması için bir derleme aracına güvenmek mimari kırılganlık getirir.
65
97
 
66
- ### 1. Sezgisel Kırılganlık (Tahmin Oyunu)
98
+ ### Sezgisel Kırılganlık (Tahmin Oyunu)
99
+
100
+ Derleyici, içeriğin ne olduğunu ve kodun ne olduğunu tahmin etmek zorundadır. Bu, aracın "karşısında savaşmanıza" neden olan uç durumlara yol açar.
101
+
102
+ Bu senaryoları düşünün:
103
+
104
+ - `<span className="active"></span>` çıkarılır mı? (Bir string, ama muhtemelen bir sınıf).
105
+ - `<span status="pending"></span>` çıkarılır mı? (Bir prop değeri).
106
+ - `<span>{"Hello World"}</span>` çıkarılır mı? (Bir JS ifadesi).
107
+ - `<span>Hello {name}. How are you?</span>` çıkarılır mı? (İnterpolasyon karmaşıktır).
108
+ - `<span aria-label="Image of cat"></span>` çıkarılır mı? (Erişilebilirlik öznitelikleri çeviri gerektirir).
109
+ - `<span data-testid="my-element"></span>` çıkarılır mı? (Test ID'leri ÇEVRİLMEMELİDİR).
110
+ - `<MyComponent errorMessage="An error occurred" />` çıkarılır mı?
111
+ - `<p>This is a paragraph{" "}\n containing multiple lines</p>` çıkarılır mı?
112
+ - `<p>{getStatusMessage()}</p>` fonksiyon sonucu çıkarılır mı?
113
+ - `<div>{isLoading ? "The page is loading" : <MyComponent/>} </div>` çıkarılır mı?
114
+ - `<span>AX-99</span>` gibi bir ürün ID'si çıkarılır mı?
115
+
116
+ Sonuç olarak, uygulama mantığınızın bozulmasını önlemek için belirli yorumlar (örneğin `// ignore-translation`) veya belirli prop'lar (örneğin `data-compiler-ignore="true"`) eklemek zorunda kalırsınız.
117
+
118
+ ### Intlayer bu karmaşıklığı nasıl ele alıyor?
119
+
120
+ Intlayer, bir alanın çeviri için çıkarılıp çıkarılmayacağını tespit etmek için karma bir yaklaşım kullanır ve yanlış pozitifleri en aza indirmeye çalışır:
121
+
122
+ 1. **AST Analizi:** Eleman türünü kontrol eder (örneğin, bir `reactNode`, bir `label` veya bir `title` prop'u arasında ayrım yapar).
123
+ 2. **Desen Tanıma:** Dizgenin büyük harfle başlayıp başlamadığını veya boşluk içerip içermediğini tespit eder; bu, dizgenin muhtemelen bir kod tanımlayıcısı değil, insan tarafından okunabilir metin olduğunu gösterir.
67
124
 
68
- Derleyici, içeriğin ne olduğunu ve kodun ne olduğunu tahmin etmek zorundadır.
125
+ ### Dinamik Veri Zorunlu Sınırı
69
126
 
70
- - `className="active"` çevrilir mi? Bu bir string.
71
- - `status="pending"` çevrilir mi?
72
- - `<MyComponent errorMessage="An error occurred" />` çevrilir mi?
73
- - `"AX-99"` gibi bir ürün kimliği çevrilir mi?
127
+ Compiler çıkarımı **statik analiz**e dayanır. Kararlı bir ID oluşturmak için kodunuzdaki literal dizgeyi görmesi gerekir.
128
+ Eğer API'niz `server_error` gibi bir hata kodu stringi döndürüyorsa, bunu bir derleyici ile çeviremezsiniz çünkü derleyici, bu stringin derleme zamanında var olduğunu bilmez. Dinamik veriler için yalnızca çalışma zamanı "runtime-only" bir sistem kurmak zorunda kalırsınız.
74
129
 
75
- Sonuç olarak, derleyiciyle "mücadele" etmek zorunda kalırsınız ve uygulama mantığınızı bozmasını önlemek için `// ignore-translation` gibi özel yorumlar eklersiniz.
130
+ ### Parçalama Eksikliği
76
131
 
77
- ### 2. Dinamik Veri Sert Sınırı
132
+ Bazı derleyiciler, çevirileri sayfa bazında parçalara ayırmaz. Eğer derleyiciniz her dil için büyük bir JSON dosyası oluşturuyorsa (örneğin, `./lang/en.json`, `./lang/fr.json` vb.), tek bir ziyaret edilen sayfa için tüm sayfalarınızın içeriğini yüklemeniz muhtemeldir. Ayrıca, içeriğinizi kullanan her bileşen, muhtemelen gereğinden çok daha fazla içerikle yüklenir ve bu da performans sorunlarına yol açabilir.
78
133
 
79
- Derleyici çıkarımı **statik analiz**e dayanır. Kararlı bir ID oluşturmak için kodunuzda literal stringi görmesi gerekir.
80
- API'niz `server_error` gibi bir hata kodu stringi dönerse, derleyici bunu derleme zamanında bilmediği için çeviremezsiniz. Dinamik veriler için yalnızca çalışma zamanı "runtime-only" ikinci bir sistem kurmak zorunda kalırsınız.
134
+ Ayrıca çevirilerinizi dinamik olarak yüklerken dikkatli olun. Eğer bu yapılmazsa, mevcut dilin yanı sıra tüm diller için içerik yüklersiniz.
81
135
 
82
- ### 3. "Parça Patlaması" ve Şelaleleri
136
+ > Problemi açıklamak için, 10 sayfa ve 10 dilin (tamamen benzersiz) olduğu bir siteyi düşünün. 99 ek sayfa için içerik yüklersiniz (10 × 10 - 1).
83
137
 
84
- Ağaç sarsma (tree-shaking) için, derleyici araçları genellikle çevirileri bileşen bazında böler.
138
+ ### "Chunk Patlaması" ve Şelaleleri
85
139
 
86
- - **Sonuç:** 50 küçük bileşene sahip tek bir sayfa görüntülemesi, küçük çeviri parçaları için **50 ayrı HTTP isteği** tetikleyebilir. HTTP/2 olsa bile, bu durum tek, optimize edilmiş bir dil paketi yüklemeye kıyasla uygulamanızın yavaş hissetmesine neden olan bir ağ şelalesi oluşturur.
140
+ Chunking sorununu çözmek için bazı çözümler, bileşen başına veya hatta anahtar başına chunking sunar. Ancak sorun yalnızca kısmen çözülür. Bu çözümlerin satış noktası genellikle "İçeriğiniz tree-shaken olur." demektir.
87
141
 
88
- ### 4. Çalışma Zamanı Performans Yükü
142
+ Gerçekten de, içeriği statik olarak yüklerseniz, çözümünüz kullanılmayan içeriği tree-shake yapar, ancak yine de uygulamanızla birlikte tüm dillerden içerik yüklersiniz.
89
143
 
90
- Çevirilerin reaktif olmasını sağlamak (yani dil değiştirdiğinizde anında güncellenmesi için), derleyici genellikle _her_ bileşene durum yönetimi (state management) hook'ları enjekte eder.
144
+ Peki neden dinamik olarak yüklemiyorsunuz? Evet, bu durumda gerekli olandan daha fazla içerik yüklersiniz, ancak bunun da bazı dezavantajları vardır.
91
145
 
92
- - **Maliyet:** Eğer 5.000 öğeden oluşan bir liste render ederseniz, yalnızca metin için 5.000 `useState` ve `useEffect` hook'u başlatıyorsunuz demektir. Bu, deklaratif kütüphanelerin (genellikle tek bir Context sağlayıcı kullanan) tasarruf ettiği bellek ve CPU döngülerini tüketir.
146
+ İçeriği dinamik olarak yüklemek, her içerik parçasını kendi chunk'ında izole eder ve bu chunk yalnızca bileşen render edildiğinde yüklenir. Bu, her metin bloğu için bir HTTP isteği yapacağınız anlamına gelir. Sayfanızda 1.000 metin bloğu mu var? Sunucularınıza 1.000 HTTP isteği. Ve zararı sınırlamak ve uygulamanızın ilk render süresini optimize etmek için, birden fazla Suspense sınırı veya Skeleton Loader eklemeniz gerekecektir.
93
147
 
94
- ## Tuzak: Vendor Lock-in (Tedarikçi Bağımlılığı)
148
+ > Not: Next.js ve SSR ile bile, bileşenleriniz yüklemeden sonra hala hydrate edilir, bu yüzden HTTP istekleri yine de yapılacaktır.
95
149
 
96
- Bu, derleyici tabanlı i18n'nin muhtemelen en tehlikeli yönüdür.
150
+ Çözüm mü? `i18next`, `next-intl` veya `intlayer` gibi kapsamlı içerik bildirimleri yapmanıza olanak tanıyan bir çözüm benimsemek.
97
151
 
98
- Deklaratif bir kütüphanede, kaynak kodunuz açık niyet içerir. Anahtarlar size aittir. Kütüphane değiştirirseniz, sadece import'u değiştirirsiniz.
152
+ > Not: `i18next` ve `next-intl`, paket boyutunuzu optimize etmek için her sayfa için namespace / mesaj importlarını manuel olarak yönetmenizi gerektirir. Paketinizin kullanılmayan çevirilerle kirlenip kirlenmediğini tespit etmek için `rollup-plugin-visualizer` (vite), `@next/bundle-analyzer` (next.js) veya `webpack-bundle-analyzer` (React CRA / Angular / vb.) gibi bir paket analizörü kullanmalısınız.
99
153
 
100
- Derleyici tabanlı bir yaklaşımda, **kaynak kodunuz sadece İngilizce metindir.** "Çeviri mantığı" sadece build eklentisinin yapılandırması içinde vardır.
101
- Eğer o kütüphane bakım dışı kalırsa veya ihtiyaçlarınızı karşılamaz hale gelirse, sıkışıp kalırsınız. Kaynak kodunuzda hiç çeviri anahtarı olmadığından kolayca "eject" yapamazsınız. Göç etmek için tüm uygulamanızı manuel olarak yeniden yazmanız gerekir.
154
+ ### Çalışma Zamanı Performans Yükü
155
+
156
+ Çevirileri reaktif hale getirmek (yani dil değiştirdiğinizde anında güncellenmelerini sağlamak) için derleyici genellikle her bileşene durum yönetimi hook'ları enjekte eder.
157
+
158
+ - **Maliyet:** Eğer 5.000 öğelik bir liste render ederseniz, yalnızca metin için 5.000 `useState` ve `useEffect` hook'u başlatıyorsunuz demektir. React, tüm 5.000 tüketiciyi aynı anda tanımlayıp yeniden render etmek zorundadır. Bu, geçiş sırasında kullanıcı arayüzünü donduran büyük bir "Ana İş Parçacığı" tıkanıklığına neden olur. Bu durum, deklaratif kütüphanelerin (genellikle tek bir Context sağlayıcı kullanan) tasarruf ettiği bellek ve CPU döngülerini tüketir.
159
+
160
+ > Not: Bu sorun React dışındaki diğer frameworkler için de benzerdir.
161
+
162
+ ## Tuzak: Vendor Lock-in
163
+
164
+ Çeviri anahtarlarının çıkarılmasına veya taşınmasına izin veren bir i18n çözümü seçerken dikkatli olun.
165
+
166
+ Deklaratif bir kütüphane durumunda, kaynak kodunuz açıkça çeviri niyetinizi içerir: bunlar sizin anahtarlarınızdır ve onları kontrol edersiniz. Kütüphaneleri değiştirmek isterseniz, genellikle sadece import'u güncellemeniz yeterlidir.
167
+
168
+ Derleyici yaklaşımıyla, kaynak kodunuz sadece düz İngilizce metin olabilir, çeviri mantığının hiçbir izi yoktur: her şey derleme aracı yapılandırmasında gizlidir. Eğer o eklenti bakımsız kalırsa veya çözümleri değiştirmek isterseniz, takılıp kalabilirsiniz. “Eject” etmek için kolay bir yol yoktur: kodunuzda kullanılabilir anahtarlar yoktur ve yeni bir kütüphane için tüm çevirilerinizi yeniden oluşturmanız gerekebilir.
169
+
170
+ Bazı çözümler ayrıca çeviri oluşturma hizmetleri sunar. Krediniz bitti mi? Çeviri de yok.
171
+
172
+ Derleyiciler genellikle metni hashler (örneğin, `"Hello World"` -> `x7f2a`). Çeviri dosyalarınız `{ "x7f2a": "Hola Mundo" }` gibi görünür. Tuzak: Eğer kütüphaneler arasında geçiş yaparsanız, yeni kütüphane `"Hello World"` anahtarını görür ve onu arar. Ancak bulamaz çünkü çeviri dosyanız hashlerle (`x7f2a`) doludur.
173
+
174
+ ### Platform Bağımlılığı
175
+
176
+ Derleyici tabanlı bir yaklaşım seçerek, kendinizi altta yatan platforma bağlarsınız. Örneğin, belirli derleyiciler tüm bundler'lar (Vite, Turbopack veya Metro gibi) için mevcut değildir. Bu, gelecekteki geçişleri zorlaştırabilir ve tüm uygulamalarınızı kapsamak için birden fazla çözüm benimsemeniz gerekebilir.
102
177
 
103
178
  ## Diğer Taraf: Deklaratif Yaklaşımın Riskleri
104
179
 
105
- Adil olmak gerekirse, geleneksel deklaratif yöntem de mükemmel değildir. Kendi "kendi ayağına sıkma" sorunları vardır.
180
+ Adil olmak gerekirse, geleneksel deklaratif yöntem de mükemmel değildir. Kendi "tuzağı" vardır.
106
181
 
107
182
  1. **Namespace Cehennemi:** Hangi JSON dosyalarının yükleneceğini (`common.json`, `dashboard.json`, `footer.json`) genellikle manuel olarak yönetmeniz gerekir. Birini unutursanız, kullanıcı ham anahtarları görür.
108
- 2. **Aşırı Yükleme:** Dikkatli yapılandırma yapılmazsa, başlangıç yüklemesinde _tüm_ sayfalarınız için _tüm_ çeviri anahtarlarınızı yanlışlıkla yüklemek çok kolaydır ve bu da paket boyutunuzu şişirir.
109
- 3. **Senkronizasyon Kayması:** Bir bileşeni kullanan anahtarlar silindikten sonra bile JSON dosyasında kalması yaygındır. Çeviri dosyalarınız "zombi anahtarlarla" dolarak sonsuz şekilde büyür.
183
+ 2. **Aşırı Yükleme:** Dikkatli yapılandırma yapılmadığında, başlangıç yüklemesinde _tüm_ sayfalarınız için _tüm_ çeviri anahtarlarınızı yanlışlıkla yüklemek çok kolaydır ve bu da paket boyutunuzu şişirir.
184
+ 3. **Senkronizasyon Kayması:** Bir bileşen kullanımdan kaldırıldıktan sonra bile, anahtarların JSON dosyasında kalması yaygındır. Çeviri dosyalarınız sonsuz şekilde büyür ve "zombi anahtarlarla" dolar.
110
185
 
111
- ## Intlayer Orta Yolu
186
+ ## Intlayer'ın Orta Yolu
112
187
 
113
188
  İşte **Intlayer** gibi araçların yenilik yapmaya çalıştığı yer burasıdır. Intlayer, derleyicilerin güçlü olduğunu ancak örtük sihrin tehlikeli olduğunu anlar.
114
189
 
115
- Intlayer benzersiz bir **`transform` komutu** sunar. Gizli derleme adımında sadece sihir yapmak yerine, aslında **bileşen kodunuzu yeniden yazabilir**. Metninizi tarar ve kod tabanınızda açık içerik beyanları ile değiştirir.
190
+ Intlayer, her iki yaklaşımın avantajlarından faydalanmanızı sağlayan karma bir yöntem sunar: deklaratif içerik yönetimi ve geliştirme süresini kısaltmak için kendi derleyicisiyle uyumluluk.
191
+
192
+ Ve hatta Intlayer derleyicisini kullanmasanız bile, Intlayer bir `transform` komutu sunar (VSCode uzantısı kullanılarak da erişilebilir). Gizli derleme adımında sadece sihir yapmak yerine, aslında **bileşen kodunuzu yeniden yazabilir**. Metninizi tarar ve kod tabanınızdaki açık içerik beyanlarıyla değiştirir.
116
193
 
117
194
  Bu size her iki dünyanın en iyisini sunar:
118
195
 
119
196
  1. **Detaylılık:** Çevirilerinizi bileşenlerinize yakın tutarsınız (modülerliği ve tree-shaking'i geliştirir).
120
197
  2. **Güvenlik:** Çeviri, gizli derleme zamanı sihri değil, açık kod haline gelir.
121
- 3. **Kilitlenme Yok:** Kod, depo içinde standart bir deklaratif yapıya dönüştürüldüğünden, mantığı bir webpack eklentisinde gizlememiş olursunuz.
198
+ 3. **Kilitlenme Yok:** Kod, depo içinde deklaratif bir yapıya dönüştürüldüğünden, içerik beyanlarınızı oluşturmak için kolayca tab tuşuna basabilir veya IDE'nizin copilot'unu kullanabilirsiniz; mantığı bir webpack eklentisinde gizlemiyorsunuz.
122
199
 
123
200
  ## Sonuç
124
201
 
125
202
  Peki, hangisini seçmelisiniz?
126
203
 
127
- **Eğer Junior Geliştirici, Tek Kurucu ya da bir MVP geliştiriyorsanız:**
128
- Derleyici tabanlı yaklaşım geçerli bir seçimdir. Çok hızlı ilerlemenizi sağlar. Dosya yapıları veya anahtarlar hakkında endişelenmenize gerek yoktur. Sadece inşa edersiniz. Teknik borç "Gelecekteki Siz" için bir sorundur.
204
+ **Eğer bir MVP (Minimum Viable Product) geliştiriyorsanız veya hızlı ilerlemek istiyorsanız:**
205
+ Derleyici tabanlı yaklaşım geçerli bir seçimdir. Çok hızlı ilerlemenizi sağlar. Dosya yapıları veya anahtarlar hakkında endişelenmenize gerek yoktur. Sadece inşa edersiniz. Teknik borç, "Gelecekteki Siz" için bir sorundur.
206
+
207
+ **Eğer Junior Geliştiriciyseniz veya optimizasyona önem vermiyorsanız:**
208
+ En az manuel yönetim istiyorsanız, derleyici tabanlı yaklaşım muhtemelen en iyisidir. Anahtarları veya çeviri dosyalarını kendiniz yönetmenize gerek kalmaz—sadece metni yazarsınız ve derleyici geri kalanını otomatikleştirir. Bu, kurulum çabasını ve manuel adımlara bağlı yaygın i18n hatalarını azaltır.
209
+
210
+ **Eğer zaten binlerce bileşeni yeniden düzenlemeyi gerektiren mevcut bir projeyi uluslararasılaştırıyorsanız:**
211
+ Derleyici tabanlı bir yaklaşım burada pragmatik bir seçim olabilir. İlk çıkarım aşaması haftalar veya aylar süren manuel çalışmayı kurtarabilir. Ancak, Intlayer'ın `transform` komutu gibi bir aracı kullanmayı düşünün; bu araç dizeleri çıkarabilir ve bunları açık beyan edici içerik deklarasyonlarına dönüştürebilir. Bu, otomasyon hızını sağlarken, beyan edici yaklaşımın güvenliği ve taşınabilirliğini korur. İki dünyanın en iyisini elde edersiniz: uzun vadeli mimari borç olmadan hızlı ilk geçiş.
129
212
 
130
- **Eğer Profesyonel, Kurumsal Düzeyde Bir Uygulama Geliştiriyorsanız:**
131
- Sihir genellikle kötü bir fikirdir. Kontrole ihtiyacınız vardır.
213
+ **Profesyonel, Kurumsal Düzeyde Bir Uygulama Geliştiriyorsanız:**
214
+ Sihir genellikle kötü bir fikirdir. Kontrole ihtiyacınız var.
132
215
 
133
- - Backendlerden dinamik verileri yönetmeniz gerekir.
134
- - Düşük donanımlı cihazlarda performansı garanti etmeniz gerekir (hook patlamalarını önleyerek).
135
- - Belirli bir derleme aracına sonsuza kadar bağımlı kalmadığınızdan emin olmanız gerekir.
216
+ - Backend'lerden gelen dinamik verileri yönetmeniz gerekir.
217
+ - Düşük donanımlı cihazlarda performansı sağlamanız gerekir (hook patlamalarını önleyerek).
218
+ - Belirli bir build aracına sonsuza dek bağlı kalmadığınızdan emin olmanız gerekir.
136
219
 
137
- Profesyonel uygulamalar için, **Deklaratif İçerik Yönetimi** (Intlayer veya yerleşik kütüphaneler gibi) altın standart olmaya devam eder. Bu, endişelerinizi ayırır, mimarinizi temiz tutar ve uygulamanızın birden fazla dili konuşma yeteneğinin, niyetlerinizi tahmin eden "kara kutu" bir derleyiciye bağlı olmamasını sağlar.
220
+ Profesyonel uygulamalar için, **Deklaratif İçerik Yönetimi** (Intlayer veya yerleşik kütüphaneler gibi) altın standart olmaya devam eder. Bu, endişelerinizi ayırır, mimarinizi temiz tutar ve uygulamanızın çoklu dil desteğinin, niyetlerinizi tahmin eden "kara kutu" bir derleyiciye bağlı olmamasını sağlar.