@mirta/i18n 0.0.1 → 0.4.0

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,353 @@
1
+ /**
2
+ * Тип для локали (например, 'en-US', 'ru-RU'), обеспечивающий типобезопасность.
3
+ * Использует branded type для предотвращения случайного смешивания строк.
4
+ *
5
+ * @since 0.4.0
6
+ *
7
+ **/
8
+ type Locale = Branded<string, 'Locale'>;
9
+ /**
10
+ * Тип для языкового кода (например, 'en', 'ru'), выделенного из локали.
11
+ * Обеспечивает типобезопасность через branded type.
12
+ *
13
+ * @since 0.4.0
14
+ *
15
+ **/
16
+ type Lang = Branded<string, 'Lang'>;
17
+ /**
18
+ * Допустимые типы значений переменных в сообщениях локализации.
19
+ *
20
+ * @since 0.4.0
21
+ *
22
+ * @private
23
+ *
24
+ **/
25
+ type MessageVariable = string | number | null | undefined;
26
+ /**
27
+ * Базовый интерфейс для описания структуры сообщений и переменных локали.
28
+ *
29
+ * @since 0.4.0
30
+ *
31
+ **/
32
+ interface GenericShape {
33
+ /**
34
+ * Словарь локализованных сообщений.
35
+ * Ключ — идентификатор сообщения, значение — строка с текстом или шаблоном.
36
+ *
37
+ **/
38
+ messages: Record<string, string | undefined>;
39
+ /**
40
+ * Опциональные типы переменных для каждого сообщения.
41
+ * Позволяет строго типизировать переменные при вызове `t(...)`.
42
+ *
43
+ **/
44
+ variables: Record<string, Record<string, MessageVariable>>;
45
+ }
46
+ /**
47
+ * Извлекает тип переменных для указанного ключа сообщения.
48
+ * Если переменные для ключа определены — возвращает соответствующий тип,
49
+ * иначе — `never`.
50
+ *
51
+ * @template TShape - Интерфейс локали, совместимый с `GenericShape`
52
+ * @template K - Ключ сообщения
53
+ *
54
+ * @since 0.4.0
55
+ *
56
+ * @private
57
+ *
58
+ **/
59
+ type VariablesOf<TShape extends GenericShape, K extends keyof TShape['messages']> = K extends keyof TShape['variables'] ? TShape['variables'][K] : never;
60
+ /**
61
+ * Переводчик сообщений для текущей локали.
62
+ *
63
+ * Поддерживает два режима работы:
64
+ * - `t('ключ', { переменные })` — интерполированная строка
65
+ * - `t.plain('ключ', 'резервный текст')` — прямой доступ к сообщению.
66
+ *
67
+ * @template TShape - Интерфейс локализации, совместимый с `GenericShape`
68
+ *
69
+ * @example
70
+ * ```ts
71
+ * t('greeting', { name: 'Анна' })
72
+ * // → "Привет, Анна!"
73
+ * ```
74
+ * @example
75
+ * ```ts
76
+ * t.plain('unknown.key', 'По умолчанию')
77
+ * // → "По умолчанию" (если ключ не найден)
78
+ * ```
79
+ * @since 0.4.0
80
+ *
81
+ **/
82
+ interface Translator<TShape extends GenericShape> {
83
+ /**
84
+ * Возвращает локализованное сообщение по ключу с подстановкой переменных.
85
+ * Ключ и структура переменных проверяются на этапе компиляции.
86
+ *
87
+ * @param key - Ключ сообщения
88
+ * @param variables - Данные для подстановки (если определены)
89
+ * @returns Локализованная строка с подставленными значениями
90
+ *
91
+ **/
92
+ <TMessageKey extends keyof TShape['messages']>(key: TMessageKey, variables?: VariablesOf<TShape, TMessageKey>): string;
93
+ /**
94
+ * Возвращает сообщение без интерполяции. Подходит для динамических ключей.
95
+ * Не требует строгой типизации переменных.
96
+ *
97
+ * @param key - Ключ сообщения
98
+ * @param fallbackValue - Текст, возвращаемый при отсутствии ключа
99
+ * @returns Значение сообщения или `fallbackValue`
100
+ *
101
+ **/
102
+ plain: (key: string, fallbackValue?: string) => string;
103
+ }
104
+ /**
105
+ * Интерфейс локализации, предоставляемый после инициализации.
106
+ *
107
+ * @since 0.4.0
108
+ *
109
+ **/
110
+ interface Localization<TShape extends GenericShape> {
111
+ /**
112
+ * Возвращает текущую активную локаль.
113
+ *
114
+ **/
115
+ getLocale: () => Locale;
116
+ /**
117
+ * Асинхронно устанавливает новую локаль.
118
+ * Если сообщения для указанной локали недоступны — используется fallback.
119
+ *
120
+ * @param locale - Локаль в виде строки (например, 'ru-RU')
121
+ *
122
+ **/
123
+ setLocaleAsync: (locale: string) => Promise<void>;
124
+ /**
125
+ * Переводчик сообщений для текущей локали.
126
+ *
127
+ **/
128
+ t: Translator<TShape>;
129
+ }
130
+
131
+ /**
132
+ * Опции для инициализации системы локализации.
133
+ *
134
+ * @since 0.4.0
135
+ *
136
+ **/
137
+ interface LocalizationOptions {
138
+ /**
139
+ * Рабочая директория, в которой ожидается папка `locales/`.
140
+ *
141
+ * По умолчанию `process.cwd()`
142
+ *
143
+ **/
144
+ cwd?: string;
145
+ /**
146
+ * Локаль по умолчанию, если системная недоступна или не поддерживается.
147
+ *
148
+ * По умолчанию `'en-US'`
149
+ *
150
+ **/
151
+ fallbackLocale?: string;
152
+ /**
153
+ * Определяет реакцию на ошибки при локализации.
154
+ *
155
+ * - `true` — выбрасывает ошибки,
156
+ * - `false` — использует fallback-поведение.
157
+ *
158
+ * По умолчанию `false`.
159
+ *
160
+ **/
161
+ strict?: boolean;
162
+ }
163
+ /**
164
+ * Инициализирует систему локализации, загружает сообщения для системной и fallback-локали.
165
+ *
166
+ * @template TShape - Интерфейс локали, описывающий структуру сообщений и переменных.
167
+ * Если не указан, применяется тип {@link GenericShape}, разрешающий использовать любые строки как ключи.
168
+ * Для включения строгой типизации передайте сгенерированный или явно определённый интерфейс `LocaleShape`.
169
+ *
170
+ * @param options - Опции инициализации локализации.
171
+ * @param options.cwd - Рабочая директория, откуда загружаются локали (по умолчанию: `process.cwd()`).
172
+ * @param options.fallbackLocale - Локаль по умолчанию, если другие не найдены (по умолчанию: `'en-US'`).
173
+ *
174
+ * @returns Промис, разрешающийся в объект `Localization<TShape>`, содержащий:
175
+ * - `getLocale()` — текущую локаль
176
+ * - `setLocaleAsync(locale)` — переключение локали
177
+ * - `t(key, vars)` — функция перевода
178
+ *
179
+ * @throws Ошибка, если не удалось загрузить fallback-локаль.
180
+ *
181
+ * @example
182
+ * ```ts
183
+ * // Без LocaleShape — нет строгой проверки ключей
184
+ * const { t } = await initLocalizationAsync()
185
+ * t('non.existing.key') // OK (нет ошибки на уровне типов)
186
+ * ```
187
+ *
188
+ * @example
189
+ * ```ts
190
+ * // С интерфейсом — полная типизация
191
+ * const { t } = await initLocalizationAsync<MyLocaleShape>()
192
+ * t('non.existing.key') // Ошибка компиляции
193
+ * ```
194
+ *
195
+ * @since 0.4.0
196
+ *
197
+ **/
198
+ declare function initLocalizationAsync<TShape extends GenericShape = GenericShape>(options?: LocalizationOptions): Promise<Localization<TShape>>;
199
+
200
+ /**
201
+ * Специализированный класс для обработки ошибок, связанных с работой локализации.
202
+ *
203
+ * Предоставляет структурированные и типизированные ошибки с использованием кодов, что упрощает
204
+ * программную обработку исключений в инструментах, работающих с пакетами.
205
+ *
206
+ * @example
207
+ * ```ts
208
+ * throw LocalizationError.get('fallback.LoadFailed', 'en-US')
209
+ * ```
210
+ * @since 0.4.0
211
+ *
212
+ **/
213
+ declare class LocalizationError extends Error {
214
+ /**
215
+ * Код ошибки для программной идентификации.
216
+ *
217
+ * Позволяет точно определить причину ошибки в обработчиках `try/catch`.
218
+ *
219
+ **/
220
+ readonly code: string;
221
+ /**
222
+ * Приватный конструктор, используемый только внутри
223
+ * класса для создания экземпляров ошибки.
224
+ *
225
+ * @param message - Полное сообщение об ошибке.
226
+ * @param code - Код ошибки для идентификации.
227
+ * @param scope - Пространство имён или модуль, в котором возникла ошибка.
228
+ * По умолчанию — {@link THIS_PACKAGE_NAME}.
229
+ *
230
+ **/
231
+ private constructor();
232
+ /** Карта кодов ошибок с соответствующими сообщениями. */
233
+ private static readonly codeMappings;
234
+ /**
235
+ * Фабричный метод для создания экземпляра ошибки по её коду.
236
+ *
237
+ * Автоматически подставляет сообщение из `codeMappings` и формирует ошибку с заданными параметрами.
238
+ *
239
+ * @template T - Ограниченный ключами `codeMappings` тип, гарантирующий корректность кода.
240
+ * @param code - Код ошибки (например, `'fallback.loadFailed'`).
241
+ * @param args - Аргументы, соответствующие параметрам функции сообщения из `codeMappings`.
242
+ * @returns Новый экземпляр {@link LocalizationError} с шаблонным сообщением.
243
+ *
244
+ * @example
245
+ * ```ts
246
+ * const error = LocalizationError.get('fallback.loadFailed', 'en-US')
247
+ * ```
248
+ */
249
+ static get<T extends keyof typeof LocalizationError['codeMappings']>(code: T, ...args: Parameters<typeof LocalizationError['codeMappings'][T]>): LocalizationError;
250
+ /**
251
+ * Фабричный метод, аналогичный `get`, но с возможностью указать
252
+ * пользовательское пространство имён (scope).
253
+ *
254
+ * Полезно при использовании в других модулях, где нужно указать
255
+ * иной контекст ошибки.
256
+ *
257
+ * @template TKey - Тип кода ошибки, аналогично `get`.
258
+ *
259
+ * @param scope - Пространство имён ошибки (например, `'@mirta/store'`).
260
+ * @param code - Код ошибки.
261
+ * @param args - Аргументы для формирования сообщения.
262
+ *
263
+ * @returns Новый экземпляр {@link LocalizationError} с пользовательским
264
+ * префиксом и шаблонным сообщением.
265
+ *
266
+ * @example
267
+ *
268
+ * ```ts
269
+ * const error = LocalizationError.getScoped('@mirta/cli', 'fallback.loadFailed', 'en-US')
270
+ * ```
271
+ **/
272
+ static getScoped<TKey extends keyof typeof LocalizationError['codeMappings']>(scope: string, code: TKey, ...args: Parameters<typeof LocalizationError['codeMappings'][TKey]>): LocalizationError;
273
+ }
274
+
275
+ /**
276
+ * Специализированный класс для обработки ошибок, связанных с работой локализации.
277
+ *
278
+ * Предоставляет структурированные и типизированные ошибки с использованием кодов, что упрощает
279
+ * программную обработку исключений в инструментах, работающих с пакетами.
280
+ *
281
+ * @example
282
+ * ```ts
283
+ * throw SourceError.get('file.accessDenied', '/path/to/file')
284
+ * ```
285
+ * @since 0.4.0
286
+ *
287
+ **/
288
+ declare class SourceError extends Error {
289
+ /**
290
+ * Код ошибки для программной идентификации.
291
+ *
292
+ * Позволяет точно определить причину ошибки в обработчиках `try/catch`.
293
+ *
294
+ **/
295
+ readonly code: string;
296
+ /**
297
+ * Приватный конструктор, используемый только внутри
298
+ * класса для создания экземпляров ошибки.
299
+ *
300
+ * @param message - Полное сообщение об ошибке.
301
+ * @param code - Код ошибки для идентификации.
302
+ * @param scope - Пространство имён или модуль, в котором возникла ошибка.
303
+ * По умолчанию — {@link THIS_PACKAGE_NAME}.
304
+ *
305
+ **/
306
+ private constructor();
307
+ /** Карта кодов ошибок с соответствующими сообщениями. */
308
+ private static readonly codeMappings;
309
+ static isFileError(error: unknown): error is SourceError;
310
+ static isParseError(error: unknown): error is SourceError;
311
+ /**
312
+ * Фабричный метод для создания экземпляра ошибки по её коду.
313
+ *
314
+ * Автоматически подставляет сообщение из `codeMappings` и формирует ошибку с заданными параметрами.
315
+ *
316
+ * @template T - Ограниченный ключами `codeMappings` тип, гарантирующий корректность кода.
317
+ * @param code - Код ошибки (например, `'alreadyDefined'`).
318
+ * @param args - Аргументы, соответствующие параметрам функции сообщения из `codeMappings`.
319
+ * @returns Новый экземпляр {@link SourceError} с шаблонным сообщением.
320
+ *
321
+ * @example
322
+ * ```ts
323
+ * const error = SourceError.get('file.notFound', '/path/to/locale.json')
324
+ * ```
325
+ */
326
+ static get<T extends keyof typeof SourceError['codeMappings']>(code: T, ...args: Parameters<typeof SourceError['codeMappings'][T]>): SourceError;
327
+ /**
328
+ * Фабричный метод, аналогичный `get`, но с возможностью указать
329
+ * пользовательское пространство имён (scope).
330
+ *
331
+ * Полезно при использовании в других модулях, где нужно указать
332
+ * иной контекст ошибки.
333
+ *
334
+ * @template TKey - Тип кода ошибки, аналогично `get`.
335
+ *
336
+ * @param scope - Пространство имён ошибки (например, `'@mirta/store'`).
337
+ * @param code - Код ошибки.
338
+ * @param args - Аргументы для формирования сообщения.
339
+ *
340
+ * @returns Новый экземпляр {@link SourceError} с пользовательским
341
+ * префиксом и шаблонным сообщением.
342
+ *
343
+ * @example
344
+ *
345
+ * ```ts
346
+ * const error = SourceError.getScoped('@mirta/bot-remote', 'file.accessDenied', '/path/to/file')
347
+ * ```
348
+ **/
349
+ static getScoped<TKey extends keyof typeof SourceError['codeMappings']>(scope: string, code: TKey, ...args: Parameters<typeof SourceError['codeMappings'][TKey]>): SourceError;
350
+ }
351
+
352
+ export { LocalizationError, SourceError, initLocalizationAsync };
353
+ export type { GenericShape, Lang, Locale, Localization, MessageVariable };