@dxtmisha/wiki 0.24.0 → 0.24.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.
@@ -0,0 +1,312 @@
1
+ import {Meta} from '@storybook/addon-docs/blocks'
2
+
3
+ <Meta title='@dxtmisha/functional/ru/Composables/useTranslateRef'/>
4
+
5
+ # Композабл useTranslateRef
6
+
7
+ Композабл для получения переведённых текстов по массиву ключей или строке с ключом. Предоставляет реактивную переменную, которая автоматически обновляется при изменении языка приложения. Поддерживает динамическую подгрузку переводов с сервера и шаблонизацию текстов с подстановкой значений.
8
+
9
+ ## Основные возможности
10
+
11
+ - **Реактивные переводы** — автоматическое обновление при смене языка
12
+ - **Массовая загрузка** — получение нескольких переводов за один раз
13
+ - **Динамическая подгрузка** — автоматическая загрузка отсутствующих переводов с сервера
14
+ - **Шаблонизация** — подстановка значений в текст перевода
15
+ - **Синхронный fallback** — мгновенный возврат ключа до загрузки перевода
16
+ - **Типобезопасность** — полная поддержка TypeScript с автоматическим выводом типов
17
+ - **Оптимизация запросов** — батчинг запросов к серверу (160ms таймаут)
18
+ - **Интеграция с Geo** — автоматическое определение языка из геолокации
19
+
20
+ ## Функция
21
+
22
+ ### `useTranslateRef`
23
+
24
+ Создаёт реактивную переменную с переводами по массиву ключей.
25
+
26
+ **Параметры:**
27
+ - `names: (string | string[])[]` — массив ключей переводов или массивов с ключом и параметрами для шаблона
28
+
29
+ **Возвращает:** `ShallowRef<TranslateList<T>>` — реактивный объект с переводами
30
+
31
+ ```javascript
32
+ import { useTranslateRef } from '@dxtmisha/functional'
33
+
34
+ // Простой перевод
35
+ const texts = useTranslateRef(['hello', 'goodbye', 'welcome'])
36
+ console.log(texts.value.hello) // 'Привет'
37
+ console.log(texts.value.goodbye) // 'До свидания'
38
+
39
+ // С шаблонизацией
40
+ const messages = useTranslateRef([
41
+ ['greeting', 'Иван'],
42
+ ['count', '5']
43
+ ])
44
+ console.log(messages.value.greeting) // 'Привет, Иван!'
45
+ console.log(messages.value.count) // 'Найдено: 5 элементов'
46
+ ```
47
+
48
+ ### `t` (алиас)
49
+
50
+ Короткий алиас для `useTranslateRef`.
51
+
52
+ **Параметры:**
53
+ - `names: string[]` — массив ключей переводов
54
+
55
+ **Возвращает:** `ShallowRef<TranslateList<T>>` — реактивный объект с переводами
56
+
57
+ ```javascript
58
+ import { t } from '@dxtmisha/functional'
59
+
60
+ // Короткая запись
61
+ const texts = t(['save', 'cancel', 'delete'])
62
+ console.log(texts.value.save) // 'Сохранить'
63
+ ```
64
+
65
+ ## Основное использование
66
+
67
+ ### Базовый перевод
68
+
69
+ ```javascript
70
+ import { useTranslateRef } from '@dxtmisha/functional'
71
+
72
+ // Получение нескольких переводов
73
+ const translations = useTranslateRef([
74
+ 'button.save',
75
+ 'button.cancel',
76
+ 'message.success'
77
+ ])
78
+
79
+ // Доступ к переводам
80
+ console.log(translations.value['button.save']) // 'Сохранить'
81
+ console.log(translations.value['button.cancel']) // 'Отмена'
82
+ console.log(translations.value['message.success']) // 'Успешно!'
83
+
84
+ // Автоматическое обновление при смене языка
85
+ // Geo.setLocation('en-US')
86
+ // translations.value['button.save'] === 'Save'
87
+ ```
88
+
89
+ ### Использование алиаса `t`
90
+
91
+ ```javascript
92
+ import { t } from '@dxtmisha/functional'
93
+
94
+ // Короткая запись для переводов
95
+ const texts = t(['home', 'about', 'contact'])
96
+
97
+ console.log(texts.value.home) // 'Главная'
98
+ console.log(texts.value.about) // 'О нас'
99
+ console.log(texts.value.contact) // 'Контакты'
100
+ ```
101
+
102
+ ## Использование в компонентах
103
+
104
+ ### Базовая форма
105
+
106
+ ```javascript
107
+ import { useTranslateRef } from '@dxtmisha/functional'
108
+
109
+ export default {
110
+ setup() {
111
+ const t = useTranslateRef([
112
+ 'form.name',
113
+ 'form.email',
114
+ 'form.submit',
115
+ 'form.reset'
116
+ ])
117
+
118
+ return { t }
119
+ }
120
+ }
121
+
122
+ // Template:
123
+ // <form>
124
+ // <input :placeholder="t['form.name']" />
125
+ // <input :placeholder="t['form.email']" />
126
+ // <button>{{ t['form.submit'] }}</button>
127
+ // <button type="reset">{{ t['form.reset'] }}</button>
128
+ // </form>
129
+ ```
130
+
131
+ ### Навигационное меню
132
+
133
+ ```javascript
134
+ import { t } from '@dxtmisha/functional'
135
+
136
+ export default {
137
+ setup() {
138
+ const menu = t([
139
+ 'menu.home',
140
+ 'menu.products',
141
+ 'menu.services',
142
+ 'menu.contact'
143
+ ])
144
+
145
+ return { menu }
146
+ }
147
+ }
148
+
149
+ // Template:
150
+ // <nav>
151
+ // <a href="/">{{ menu['menu.home'] }}</a>
152
+ // <a href="/products">{{ menu['menu.products'] }}</a>
153
+ // <a href="/services">{{ menu['menu.services'] }}</a>
154
+ // <a href="/contact">{{ menu['menu.contact'] }}</a>
155
+ // </nav>
156
+ ```
157
+
158
+ ## Шаблонизация текстов
159
+
160
+ ### Подстановка значений
161
+
162
+ ```javascript
163
+ import { useTranslateRef } from '@dxtmisha/functional'
164
+
165
+ // Переводы с параметрами
166
+ // Файл переводов: { "greeting": "Привет, {0}!", "items": "Найдено {0} из {1}" }
167
+ const messages = useTranslateRef([
168
+ ['greeting', 'Иван'],
169
+ ['items', '5', '10']
170
+ ])
171
+
172
+ console.log(messages.value.greeting) // 'Привет, Иван!'
173
+ console.log(messages.value.items) // 'Найдено 5 из 10'
174
+ ```
175
+
176
+ ### Динамические параметры
177
+
178
+ ```javascript
179
+ import { ref, computed } from 'vue'
180
+ import { useTranslateRef } from '@dxtmisha/functional'
181
+
182
+ export default {
183
+ setup() {
184
+ const userName = ref('Иван')
185
+ const count = ref(5)
186
+
187
+ // Базовые переводы
188
+ const t = useTranslateRef(['welcome', 'total'])
189
+
190
+ // Динамическая подстановка в шаблоне
191
+ const welcomeMessage = computed(() =>
192
+ t.value.welcome.replace('{0}', userName.value)
193
+ )
194
+
195
+ const totalMessage = computed(() =>
196
+ t.value.total.replace('{0}', count.value)
197
+ )
198
+
199
+ return { welcomeMessage, totalMessage }
200
+ }
201
+ }
202
+ ```
203
+
204
+ ## Автоматическое обновление при смене языка
205
+
206
+ ```javascript
207
+ import { watch } from 'vue'
208
+ import { useTranslateRef } from '@dxtmisha/functional'
209
+ import { Geo } from '@dxtmisha/functional'
210
+
211
+ // Переводы автоматически обновляются при смене языка
212
+ const texts = useTranslateRef(['title', 'description'])
213
+
214
+ console.log(texts.value.title) // 'Заголовок' (ru-RU)
215
+
216
+ // Смена языка
217
+ Geo.setLocation('en-US')
218
+
219
+ // texts.value автоматически обновится
220
+ // texts.value.title === 'Title'
221
+
222
+ // Можно отслеживать изменения
223
+ watch(() => texts.value, (newTranslations) => {
224
+ console.log('Переводы обновлены:', newTranslations)
225
+ })
226
+ ```
227
+
228
+ ## Интеграция с классом Translate
229
+
230
+ Композабл использует класс `Translate` для управления переводами:
231
+
232
+ ```javascript
233
+ import { Translate } from '@dxtmisha/functional'
234
+
235
+ // Установка URL для загрузки переводов
236
+ Translate.setUrl('/api/translations')
237
+
238
+ // Установка имени параметра запроса
239
+ Translate.setPropsName('keys')
240
+
241
+ // Добавление переводов вручную (для SSR или тестов)
242
+ Translate.addSync({
243
+ 'button.save': 'Сохранить',
244
+ 'button.cancel': 'Отмена'
245
+ })
246
+
247
+ // Получение одного перевода
248
+ const text = await Translate.get('button.save')
249
+ console.log(text) // 'Сохранить'
250
+
251
+ // Синхронное получение
252
+ const syncText = Translate.getSync('button.save')
253
+ console.log(syncText) // 'Сохранить'
254
+ ```
255
+
256
+ ## Примеры использования
257
+
258
+ ### Таблица данных
259
+
260
+ ```javascript
261
+ const table = useTranslateRef([
262
+ 'table.name',
263
+ 'table.email',
264
+ 'table.status',
265
+ 'table.actions'
266
+ ])
267
+
268
+ // В шаблоне:
269
+ // <thead>
270
+ // <th>{{ table['table.name'] }}</th>
271
+ // <th>{{ table['table.email'] }}</th>
272
+ // <th>{{ table['table.status'] }}</th>
273
+ // <th>{{ table['table.actions'] }}</th>
274
+ // </thead>
275
+ ```
276
+
277
+ ### Сообщения валидации
278
+
279
+ ```javascript
280
+ const validation = useTranslateRef([
281
+ 'validation.required',
282
+ 'validation.email',
283
+ 'validation.minLength',
284
+ 'validation.maxLength'
285
+ ])
286
+
287
+ const validateField = (value) => {
288
+ if (!value) return validation.value['validation.required']
289
+ if (value.length < 3) return validation.value['validation.minLength']
290
+ return null
291
+ }
292
+ ```
293
+
294
+ ### Динамический контент
295
+
296
+ ```javascript
297
+ import { computed } from 'vue'
298
+
299
+ const status = ref('pending')
300
+ const messages = useTranslateRef([
301
+ 'status.pending',
302
+ 'status.approved',
303
+ 'status.rejected'
304
+ ])
305
+
306
+ const statusText = computed(() =>
307
+ messages.value[`status.${status.value}`]
308
+ )
309
+
310
+ console.log(statusText.value) // 'Ожидает' (когда status = 'pending')
311
+ ```
312
+