@simplix-react/i18n 0.0.1 → 0.0.3

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.
package/README.md ADDED
@@ -0,0 +1,206 @@
1
+ # @simplix-react/i18n
2
+
3
+ Internationalization framework with an adapter pattern and built-in i18next integration.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ pnpm add @simplix-react/i18n
9
+ ```
10
+
11
+ ### Peer Dependencies
12
+
13
+ | Package | Version | Required |
14
+ | --- | --- | --- |
15
+ | `i18next` | >= 25.0.0 | Optional |
16
+ | `react` | >= 18.0.0 | Optional |
17
+ | `react-i18next` | >= 16.0.0 | Optional |
18
+
19
+ Install the peers you need based on your usage:
20
+
21
+ ```bash
22
+ # Core only (i18next adapter)
23
+ pnpm add i18next
24
+
25
+ # With React bindings
26
+ pnpm add i18next react react-i18next
27
+ ```
28
+
29
+ ## Quick Example
30
+
31
+ ```ts
32
+ import { createI18nConfig } from "@simplix-react/i18n";
33
+
34
+ const appTranslations = import.meta.glob("./locales/**/*.json", { eager: true });
35
+
36
+ const { adapter, i18nReady } = createI18nConfig({
37
+ defaultLocale: "ko",
38
+ appTranslations,
39
+ });
40
+
41
+ await i18nReady;
42
+
43
+ adapter.t("common:greeting"); // "안녕하세요"
44
+ adapter.formatCurrency(10000); // "₩10,000"
45
+ adapter.formatDate(new Date()); // "2025. 1. 15."
46
+ ```
47
+
48
+ ## API Overview
49
+
50
+ ### Core (`@simplix-react/i18n`)
51
+
52
+ | Export | Kind | Description |
53
+ | --- | --- | --- |
54
+ | `II18nAdapter` | Interface | Adapter contract for i18n backends |
55
+ | `I18nextAdapter` | Class | i18next-based adapter implementation |
56
+ | `createI18nConfig` | Function | Factory that creates and initializes an adapter |
57
+ | `buildModuleTranslations` | Function | Builds lazy-loadable module translation descriptors |
58
+ | `DEFAULT_LOCALES` | Constant | Built-in locale configs (ko, en, ja) |
59
+ | `SUPPORTED_LOCALES` | Constant | Locale codes from `DEFAULT_LOCALES` |
60
+ | `DATE_TIME_STYLES` | Constant | Date/time formatting style values |
61
+ | `NUMBER_FORMAT_STYLES` | Constant | Number formatting style values |
62
+ | `TEXT_DIRECTIONS` | Constant | Text direction values (ltr, rtl) |
63
+ | `TRANSLATION_LOAD_STATES` | Constant | Translation loading state values |
64
+
65
+ ### React Bindings (`@simplix-react/i18n/react`)
66
+
67
+ | Export | Kind | Description |
68
+ | --- | --- | --- |
69
+ | `I18nProvider` | Component | Provides the adapter via React context |
70
+ | `useTranslation` | Hook | Namespace-scoped translation with auto re-render |
71
+ | `useLocale` | Hook | Returns the active locale with auto re-render |
72
+ | `useI18n` | Hook | Returns the raw adapter from context |
73
+ | `useI18nAdapter` | Hook | Returns the adapter or `null` from context |
74
+
75
+ ## Key Concepts
76
+
77
+ ### Adapter Pattern
78
+
79
+ The `II18nAdapter` interface decouples your application from any specific i18n library. The built-in `I18nextAdapter` implements this interface using i18next, but you can create a custom adapter for any backend.
80
+
81
+ ```ts
82
+ import { I18nextAdapter } from "@simplix-react/i18n";
83
+
84
+ const adapter = new I18nextAdapter({
85
+ defaultLocale: "en",
86
+ fallbackLocale: "en",
87
+ resources: {
88
+ en: { common: { greeting: "Hello, {{name}}!" } },
89
+ ko: { common: { greeting: "안녕하세요, {{name}}!" } },
90
+ },
91
+ });
92
+
93
+ await adapter.initialize();
94
+
95
+ adapter.t("common:greeting"); // uses default namespace
96
+ adapter.tn("common", "greeting", { name: "A" }); // namespaced lookup
97
+ adapter.tp("items", 3); // plural form
98
+ ```
99
+
100
+ ### Module Translations
101
+
102
+ Use `buildModuleTranslations` to define lazy-loaded, per-component translations. This enables code splitting -- translations are only loaded when their module is used.
103
+
104
+ ```ts
105
+ import { buildModuleTranslations } from "@simplix-react/i18n";
106
+
107
+ const dashboardTranslations = buildModuleTranslations({
108
+ namespace: "dashboard",
109
+ locales: ["en", "ko"],
110
+ components: {
111
+ header: {
112
+ en: () => import("./header/locales/en.json"),
113
+ ko: () => import("./header/locales/ko.json"),
114
+ },
115
+ sidebar: {
116
+ en: () => import("./sidebar/locales/en.json"),
117
+ ko: () => import("./sidebar/locales/ko.json"),
118
+ },
119
+ },
120
+ });
121
+ ```
122
+
123
+ Pass these to `createI18nConfig` for automatic loading:
124
+
125
+ ```ts
126
+ const { adapter, i18nReady } = createI18nConfig({
127
+ defaultLocale: "ko",
128
+ moduleTranslations: [dashboardTranslations],
129
+ });
130
+ ```
131
+
132
+ ### Locale Configuration
133
+
134
+ The package includes built-in locale configs for Korean, English, and Japanese via `DEFAULT_LOCALES`. Provide custom configs to support additional locales:
135
+
136
+ ```ts
137
+ import type { LocaleConfig } from "@simplix-react/i18n";
138
+
139
+ const customLocales: LocaleConfig[] = [
140
+ { code: "en", name: "English", englishName: "English", currency: "USD" },
141
+ { code: "ko", name: "한국어", englishName: "Korean", currency: "KRW" },
142
+ { code: "zh", name: "中文", englishName: "Chinese", currency: "CNY" },
143
+ ];
144
+
145
+ const { adapter, i18nReady } = createI18nConfig({
146
+ defaultLocale: "en",
147
+ supportedLocales: customLocales,
148
+ });
149
+ ```
150
+
151
+ ### Formatting
152
+
153
+ The adapter provides locale-aware formatting powered by the `Intl` API:
154
+
155
+ ```ts
156
+ // Date / Time
157
+ adapter.formatDate(new Date(), { dateStyle: "long" });
158
+ adapter.formatTime(new Date(), { timeStyle: "short", hour12: true });
159
+ adapter.formatDateTime(new Date());
160
+ adapter.formatRelativeTime(pastDate); // "3 hours ago"
161
+
162
+ // Numbers
163
+ adapter.formatNumber(1234567.89); // "1,234,567.89"
164
+ adapter.formatNumber(0.42, { style: "percent" }); // "42%"
165
+ adapter.formatCurrency(9900, "KRW"); // "₩9,900"
166
+ ```
167
+
168
+ ## React Integration
169
+
170
+ Wrap your app with `I18nProvider` and use the hooks:
171
+
172
+ ```tsx
173
+ import { I18nProvider, useTranslation, useLocale } from "@simplix-react/i18n/react";
174
+ import { createI18nConfig } from "@simplix-react/i18n";
175
+
176
+ // Setup
177
+ const { adapter, i18nReady } = createI18nConfig({ defaultLocale: "ko" });
178
+ await i18nReady;
179
+
180
+ // Provider
181
+ function App() {
182
+ return (
183
+ <I18nProvider adapter={adapter}>
184
+ <Dashboard />
185
+ </I18nProvider>
186
+ );
187
+ }
188
+
189
+ // Consumer
190
+ function Dashboard() {
191
+ const { t, locale } = useTranslation("dashboard");
192
+ return <h1>{t("title")} ({locale})</h1>;
193
+ }
194
+
195
+ // Locale-only
196
+ function LocaleBadge() {
197
+ const locale = useLocale();
198
+ return <span>{locale}</span>;
199
+ }
200
+ ```
201
+
202
+ ## Related Packages
203
+
204
+ - `@simplix-react/contract` -- Type-safe API contract definitions
205
+ - `@simplix-react/react` -- React Query hooks derived from contracts
206
+ - `@simplix-react/mock` -- MSW handlers and PGlite repositories
package/dist/index.d.ts CHANGED
@@ -1,26 +1,75 @@
1
1
  import { i18n } from 'i18next';
2
2
 
3
+ /**
4
+ * Represents a BCP 47 locale code string (e.g., `"en"`, `"ko"`, `"ja"`).
5
+ */
3
6
  type LocaleCode = string;
7
+ /**
8
+ * Represents key-value pairs for translation string interpolation.
9
+ *
10
+ * @example
11
+ * ```ts
12
+ * const values: TranslationValues = { name: "Alice", count: 3, active: true };
13
+ * adapter.t("greeting", values); // "Hello, Alice!"
14
+ * ```
15
+ */
4
16
  type TranslationValues = Record<string, string | number | boolean>;
17
+ /**
18
+ * Provides constant values for date/time formatting styles compatible with the `Intl.DateTimeFormat` API.
19
+ *
20
+ * @example
21
+ * ```ts
22
+ * import { DATE_TIME_STYLES } from "@simplix-react/i18n";
23
+ *
24
+ * adapter.formatDate(new Date(), { dateStyle: DATE_TIME_STYLES.LONG });
25
+ * ```
26
+ */
5
27
  declare const DATE_TIME_STYLES: {
6
28
  readonly FULL: "full";
7
29
  readonly LONG: "long";
8
30
  readonly MEDIUM: "medium";
9
31
  readonly SHORT: "short";
10
32
  };
33
+ /**
34
+ * Represents a date/time formatting style derived from {@link DATE_TIME_STYLES}.
35
+ */
11
36
  type DateTimeStyle = (typeof DATE_TIME_STYLES)[keyof typeof DATE_TIME_STYLES];
37
+ /**
38
+ * Provides constant values for number formatting styles compatible with the `Intl.NumberFormat` API.
39
+ *
40
+ * @example
41
+ * ```ts
42
+ * import { NUMBER_FORMAT_STYLES } from "@simplix-react/i18n";
43
+ *
44
+ * adapter.formatNumber(1234.5, { style: NUMBER_FORMAT_STYLES.CURRENCY, currency: "USD" });
45
+ * ```
46
+ */
12
47
  declare const NUMBER_FORMAT_STYLES: {
13
48
  readonly DECIMAL: "decimal";
14
49
  readonly CURRENCY: "currency";
15
50
  readonly PERCENT: "percent";
16
51
  readonly UNIT: "unit";
17
52
  };
53
+ /**
54
+ * Represents a number formatting style derived from {@link NUMBER_FORMAT_STYLES}.
55
+ */
18
56
  type NumberFormatStyle = (typeof NUMBER_FORMAT_STYLES)[keyof typeof NUMBER_FORMAT_STYLES];
57
+ /**
58
+ * Provides constant values for text direction (`"ltr"` or `"rtl"`).
59
+ */
19
60
  declare const TEXT_DIRECTIONS: {
20
61
  readonly LTR: "ltr";
21
62
  readonly RTL: "rtl";
22
63
  };
64
+ /**
65
+ * Represents a text direction value derived from {@link TEXT_DIRECTIONS}.
66
+ */
23
67
  type TextDirection = (typeof TEXT_DIRECTIONS)[keyof typeof TEXT_DIRECTIONS];
68
+ /**
69
+ * Defines plural form strings following the CLDR plural rules.
70
+ *
71
+ * @see {@link https://cldr.unicode.org/index/cldr-spec/plural-rules | CLDR Plural Rules}
72
+ */
24
73
  interface PluralForms {
25
74
  zero?: string;
26
75
  one: string;
@@ -29,79 +78,281 @@ interface PluralForms {
29
78
  many?: string;
30
79
  other: string;
31
80
  }
81
+ /**
82
+ * Configures date/time formatting options passed to `Intl.DateTimeFormat`.
83
+ */
32
84
  interface DateTimeFormatOptions {
85
+ /** The date formatting style. */
33
86
  dateStyle?: DateTimeStyle;
87
+ /** The time formatting style. */
34
88
  timeStyle?: DateTimeStyle;
89
+ /** Whether to use 12-hour time format. */
35
90
  hour12?: boolean;
36
91
  }
92
+ /**
93
+ * Configures number formatting options passed to `Intl.NumberFormat`.
94
+ */
37
95
  interface NumberFormatOptions {
96
+ /** The number formatting style. */
38
97
  style?: NumberFormatStyle;
98
+ /** ISO 4217 currency code (required when `style` is `"currency"`). */
39
99
  currency?: string;
100
+ /** Unit identifier (required when `style` is `"unit"`). */
40
101
  unit?: string;
102
+ /** Minimum number of fraction digits to display. */
41
103
  minimumFractionDigits?: number;
104
+ /** Maximum number of fraction digits to display. */
42
105
  maximumFractionDigits?: number;
43
106
  }
107
+ /**
108
+ * Describes metadata for a single locale including display names, text direction, and default formats.
109
+ */
44
110
  interface LocaleInfo {
111
+ /** BCP 47 locale code. */
45
112
  code: LocaleCode;
113
+ /** Native name of the locale (e.g., "한국어"). */
46
114
  name: string;
115
+ /** English name of the locale (e.g., "Korean"). */
47
116
  englishName: string;
117
+ /** Text direction for the locale. */
48
118
  direction: TextDirection;
119
+ /** Default date format pattern. */
49
120
  dateFormat: string;
121
+ /** Default time format pattern. */
50
122
  timeFormat: string;
123
+ /** Default ISO 4217 currency code. */
51
124
  currency: string;
52
125
  }
126
+ /**
127
+ * Represents a translation namespace identifier used to scope translation keys.
128
+ */
53
129
  type TranslationNamespace = string;
130
+ /**
131
+ * Provides constant values representing translation resource loading states.
132
+ */
54
133
  declare const TRANSLATION_LOAD_STATES: {
55
134
  readonly IDLE: "idle";
56
135
  readonly LOADING: "loading";
57
136
  readonly LOADED: "loaded";
58
137
  readonly ERROR: "error";
59
138
  };
139
+ /**
140
+ * Represents a translation loading state derived from {@link TRANSLATION_LOAD_STATES}.
141
+ */
60
142
  type TranslationLoadState = (typeof TRANSLATION_LOAD_STATES)[keyof typeof TRANSLATION_LOAD_STATES];
61
143
 
144
+ /**
145
+ * Defines the contract for an internationalization adapter.
146
+ *
147
+ * Provides translation lookup, locale management, and formatting capabilities.
148
+ * Implement this interface to integrate a custom i18n backend.
149
+ *
150
+ * @see {@link I18nextAdapter} for the built-in i18next implementation.
151
+ *
152
+ * @example
153
+ * ```ts
154
+ * import type { II18nAdapter } from "@simplix-react/i18n";
155
+ *
156
+ * class CustomAdapter implements II18nAdapter {
157
+ * // ... implement all required members
158
+ * }
159
+ * ```
160
+ */
62
161
  interface II18nAdapter {
162
+ /** Unique identifier for this adapter implementation. */
63
163
  readonly id: string;
164
+ /** Human-readable name for this adapter. */
64
165
  readonly name: string;
166
+ /** Currently active locale code. */
65
167
  readonly locale: LocaleCode;
168
+ /** Locale code used when a translation key is missing in the active locale. */
66
169
  readonly fallbackLocale: LocaleCode;
170
+ /** List of all locale codes supported by this adapter. */
67
171
  readonly availableLocales: LocaleCode[];
172
+ /**
173
+ * Initializes the adapter with an optional default locale.
174
+ * @param defaultLocale - The locale to activate on initialization.
175
+ */
68
176
  initialize(defaultLocale?: LocaleCode): Promise<void>;
177
+ /** Disposes of the adapter and releases all resources. */
69
178
  dispose(): Promise<void>;
179
+ /**
180
+ * Changes the active locale.
181
+ * @param locale - The target locale code.
182
+ */
70
183
  setLocale(locale: LocaleCode): Promise<void>;
184
+ /**
185
+ * Returns metadata for the given locale, or `null` if unsupported.
186
+ * @param locale - The locale code to look up.
187
+ */
71
188
  getLocaleInfo(locale: LocaleCode): LocaleInfo | null;
189
+ /**
190
+ * Translates a key with optional interpolation values.
191
+ * @param key - The translation key.
192
+ * @param values - Interpolation values.
193
+ */
72
194
  t(key: string, values?: TranslationValues): string;
195
+ /**
196
+ * Translates a namespaced key with optional interpolation values.
197
+ * @param namespace - The translation namespace.
198
+ * @param key - The translation key within the namespace.
199
+ * @param values - Interpolation values.
200
+ */
73
201
  tn(namespace: TranslationNamespace, key: string, values?: TranslationValues): string;
202
+ /**
203
+ * Translates a key with plural form selection based on count.
204
+ * @param key - The translation key.
205
+ * @param count - The count for plural selection.
206
+ * @param values - Additional interpolation values.
207
+ */
74
208
  tp(key: string, count: number, values?: TranslationValues): string;
209
+ /**
210
+ * Checks whether a translation key exists.
211
+ * @param key - The translation key to check.
212
+ * @param namespace - Optional namespace to scope the lookup.
213
+ */
75
214
  exists(key: string, namespace?: TranslationNamespace): boolean;
215
+ /**
216
+ * Formats a date according to the active locale.
217
+ * @param date - The date to format.
218
+ * @param options - Formatting options.
219
+ */
76
220
  formatDate(date: Date, options?: DateTimeFormatOptions): string;
221
+ /**
222
+ * Formats a time according to the active locale.
223
+ * @param date - The date/time to format.
224
+ * @param options - Formatting options.
225
+ */
77
226
  formatTime(date: Date, options?: DateTimeFormatOptions): string;
227
+ /**
228
+ * Formats a date and time together according to the active locale.
229
+ * @param date - The date/time to format.
230
+ * @param options - Formatting options.
231
+ */
78
232
  formatDateTime(date: Date, options?: DateTimeFormatOptions): string;
233
+ /**
234
+ * Formats a date as a human-readable relative time string (e.g., "3 hours ago").
235
+ * @param date - The date to compare against the current time.
236
+ */
79
237
  formatRelativeTime(date: Date): string;
238
+ /**
239
+ * Formats a number according to the active locale.
240
+ * @param value - The number to format.
241
+ * @param options - Formatting options.
242
+ */
80
243
  formatNumber(value: number, options?: NumberFormatOptions): string;
244
+ /**
245
+ * Formats a number as a currency string according to the active locale.
246
+ * @param value - The monetary value to format.
247
+ * @param currency - ISO 4217 currency code override (defaults to the locale's currency).
248
+ */
81
249
  formatCurrency(value: number, currency?: string): string;
250
+ /**
251
+ * Loads translation resources for a given locale and namespace.
252
+ * @param locale - The target locale code.
253
+ * @param namespace - The translation namespace.
254
+ * @param translations - The translation key-value pairs to load.
255
+ */
82
256
  loadTranslations(locale: LocaleCode, namespace: TranslationNamespace, translations: Record<string, string | PluralForms>): void;
257
+ /**
258
+ * Returns the loading state of translation resources.
259
+ * @param locale - The locale to check.
260
+ * @param namespace - Optional namespace to check (defaults to `"translation"`).
261
+ */
83
262
  getLoadState(locale: LocaleCode, namespace?: TranslationNamespace): TranslationLoadState;
263
+ /**
264
+ * Registers a callback invoked whenever the active locale changes.
265
+ * @param handler - The callback receiving the new locale code.
266
+ * @returns A function that unregisters the handler when called.
267
+ */
84
268
  onLocaleChange(handler: (locale: LocaleCode) => void): () => void;
85
269
  }
86
270
 
271
+ /**
272
+ * Describes the configuration for a single supported locale.
273
+ *
274
+ * @example
275
+ * ```ts
276
+ * import type { LocaleConfig } from "@simplix-react/i18n";
277
+ *
278
+ * const korean: LocaleConfig = {
279
+ * code: "ko",
280
+ * name: "한국어",
281
+ * englishName: "Korean",
282
+ * direction: "ltr",
283
+ * currency: "KRW",
284
+ * };
285
+ * ```
286
+ */
87
287
  interface LocaleConfig {
288
+ /** BCP 47 locale code. */
88
289
  code: LocaleCode;
290
+ /** Native display name. */
89
291
  name: string;
292
+ /** English display name. */
90
293
  englishName: string;
294
+ /** Text direction (defaults to `"ltr"`). */
91
295
  direction?: "ltr" | "rtl";
296
+ /** Default date format pattern. */
92
297
  dateFormat?: string;
298
+ /** Default time format pattern. */
93
299
  timeFormat?: string;
300
+ /** Default ISO 4217 currency code. */
94
301
  currency?: string;
95
302
  }
303
+ /**
304
+ * Represents a nested structure of translation resources keyed by locale, then namespace.
305
+ *
306
+ * @example
307
+ * ```ts
308
+ * import type { TranslationResources } from "@simplix-react/i18n";
309
+ *
310
+ * const resources: TranslationResources = {
311
+ * en: { common: { greeting: "Hello" } },
312
+ * ko: { common: { greeting: "안녕하세요" } },
313
+ * };
314
+ * ```
315
+ */
96
316
  type TranslationResources = Record<LocaleCode, Record<TranslationNamespace, Record<string, unknown>>>;
317
+ /**
318
+ * Configures the {@link I18nextAdapter} constructor.
319
+ */
97
320
  interface I18nextAdapterOptions {
321
+ /** Initial locale to use (defaults to `"en"`). */
98
322
  defaultLocale?: LocaleCode;
323
+ /** Fallback locale when a key is missing (defaults to `"en"`). */
99
324
  fallbackLocale?: LocaleCode;
325
+ /** Supported locale configurations. */
100
326
  locales?: LocaleConfig[];
327
+ /** Pre-loaded translation resources. */
101
328
  resources?: TranslationResources;
329
+ /** An existing i18next instance to reuse instead of creating a new one. */
102
330
  i18nextInstance?: i18n;
331
+ /** Enables i18next debug logging. */
103
332
  debug?: boolean;
104
333
  }
334
+ /**
335
+ * Implements {@link II18nAdapter} using i18next as the underlying translation engine.
336
+ *
337
+ * Provides locale-aware translation, date/time/number formatting via the `Intl` API,
338
+ * and reactive locale change notifications.
339
+ *
340
+ * @example
341
+ * ```ts
342
+ * import { I18nextAdapter } from "@simplix-react/i18n";
343
+ *
344
+ * const adapter = new I18nextAdapter({
345
+ * defaultLocale: "ko",
346
+ * resources: {
347
+ * ko: { common: { greeting: "안녕하세요, {{name}}!" } },
348
+ * en: { common: { greeting: "Hello, {{name}}!" } },
349
+ * },
350
+ * });
351
+ *
352
+ * await adapter.initialize();
353
+ * adapter.tn("common", "greeting", { name: "Alice" }); // "안녕하세요, Alice!"
354
+ * ```
355
+ */
105
356
  declare class I18nextAdapter implements II18nAdapter {
106
357
  readonly id = "i18next";
107
358
  readonly name = "i18next Adapter";
@@ -134,46 +385,159 @@ declare class I18nextAdapter implements II18nAdapter {
134
385
  loadTranslations(locale: LocaleCode, namespace: TranslationNamespace, translations: Record<string, string | PluralForms>): void;
135
386
  getLoadState(locale: LocaleCode, namespace?: TranslationNamespace): TranslationLoadState;
136
387
  onLocaleChange(handler: (locale: LocaleCode) => void): () => void;
388
+ /**
389
+ * Adds translation resources to the underlying i18next instance, merging with any existing resources.
390
+ * @param locale - The target locale code.
391
+ * @param namespace - The translation namespace.
392
+ * @param resources - The translation key-value pairs to add.
393
+ */
137
394
  addResources(locale: LocaleCode, namespace: TranslationNamespace, resources: Record<string, unknown>): void;
395
+ /**
396
+ * Returns the underlying i18next instance for advanced usage or direct integration with `react-i18next`.
397
+ */
138
398
  getI18nextInstance(): i18n;
139
399
  private notifyLocaleChange;
140
400
  }
141
401
 
402
+ /**
403
+ * Maps locale codes to lazy-loading functions that return translation modules.
404
+ *
405
+ * Designed to work with Vite's `import.meta.glob` for code-split translation files.
406
+ *
407
+ * @example
408
+ * ```ts
409
+ * import type { ComponentTranslations } from "@simplix-react/i18n";
410
+ *
411
+ * const translations: ComponentTranslations = {
412
+ * en: () => import("./locales/en.json"),
413
+ * ko: () => import("./locales/ko.json"),
414
+ * };
415
+ * ```
416
+ */
142
417
  interface ComponentTranslations {
143
418
  [locale: string]: () => Promise<{
144
419
  default: Record<string, unknown>;
145
420
  }>;
146
421
  }
422
+ /**
423
+ * Configures the {@link buildModuleTranslations} function.
424
+ */
147
425
  interface BuildModuleTranslationsOptions {
426
+ /** Namespace prefix for all component translations in this module. */
148
427
  namespace: string;
428
+ /** List of supported locale codes. */
149
429
  locales: string[];
430
+ /** Map of component paths to their locale-specific translation loaders. */
150
431
  components: Record<string, ComponentTranslations>;
151
432
  }
433
+ /**
434
+ * Represents the output of {@link buildModuleTranslations}, providing a lazy-loadable
435
+ * collection of namespaced translations for a module.
436
+ */
152
437
  interface ModuleTranslations {
438
+ /** The module's translation namespace. */
153
439
  namespace: string;
440
+ /** Supported locale codes. */
154
441
  locales: string[];
442
+ /** Loads all component translations for the given locale. */
155
443
  load: (locale: string) => Promise<Record<string, Record<string, unknown>>>;
156
444
  }
445
+ /**
446
+ * Builds a lazy-loadable module translation descriptor from per-component translation loaders.
447
+ *
448
+ * Aggregates component-level translations under a shared namespace so they can be
449
+ * loaded on demand by {@link createI18nConfig}.
450
+ *
451
+ * @param options - The module translation configuration.
452
+ * @returns A {@link ModuleTranslations} descriptor.
453
+ *
454
+ * @example
455
+ * ```ts
456
+ * import { buildModuleTranslations } from "@simplix-react/i18n";
457
+ *
458
+ * const moduleTranslations = buildModuleTranslations({
459
+ * namespace: "dashboard",
460
+ * locales: ["en", "ko"],
461
+ * components: {
462
+ * header: {
463
+ * en: () => import("./header/locales/en.json"),
464
+ * ko: () => import("./header/locales/ko.json"),
465
+ * },
466
+ * },
467
+ * });
468
+ * ```
469
+ */
157
470
  declare function buildModuleTranslations(options: BuildModuleTranslationsOptions): ModuleTranslations;
158
471
 
472
+ /**
473
+ * Configures the {@link createI18nConfig} factory function.
474
+ */
159
475
  interface CreateI18nConfigOptions {
476
+ /** Initial locale to activate (defaults to `"en"`). */
160
477
  defaultLocale?: LocaleCode;
478
+ /** Fallback locale for missing translations (defaults to `"en"`). */
161
479
  fallbackLocale?: LocaleCode;
480
+ /** Supported locale configurations (defaults to {@link DEFAULT_LOCALES}). */
162
481
  supportedLocales?: LocaleConfig[];
482
+ /** Language detection configuration. */
163
483
  detection?: {
164
484
  order: string[];
165
485
  };
486
+ /**
487
+ * Eagerly imported application translations, typically from `import.meta.glob`.
488
+ *
489
+ * Keys should follow the pattern `/locales/{namespace}/{locale}.json`.
490
+ */
166
491
  appTranslations?: Record<string, unknown>;
492
+ /** Lazy-loadable module translation descriptors built via {@link buildModuleTranslations}. */
167
493
  moduleTranslations?: ModuleTranslations[];
494
+ /** Enables i18next debug logging. */
168
495
  debug?: boolean;
169
496
  }
497
+ /**
498
+ * Represents the result of {@link createI18nConfig}.
499
+ */
170
500
  interface I18nConfigResult {
501
+ /** The configured i18next adapter instance. */
171
502
  adapter: I18nextAdapter;
503
+ /** A promise that resolves when all translations (including module translations) are loaded. */
172
504
  i18nReady: Promise<void>;
173
505
  }
506
+ /**
507
+ * Creates and initializes an i18n configuration with an {@link I18nextAdapter}.
508
+ *
509
+ * Handles eager loading of app-level translations and lazy loading of module translations.
510
+ * Returns both the adapter instance and a promise that resolves when initialization is complete.
511
+ *
512
+ * @param options - The i18n configuration options.
513
+ * @returns An {@link I18nConfigResult} containing the adapter and a readiness promise.
514
+ *
515
+ * @example
516
+ * ```ts
517
+ * import { createI18nConfig } from "@simplix-react/i18n";
518
+ *
519
+ * const appTranslations = import.meta.glob("./locales/**\/*.json", { eager: true });
520
+ *
521
+ * const { adapter, i18nReady } = createI18nConfig({
522
+ * defaultLocale: "ko",
523
+ * appTranslations,
524
+ * });
525
+ *
526
+ * await i18nReady;
527
+ * adapter.t("common:greeting"); // "안녕하세요"
528
+ * ```
529
+ */
174
530
  declare function createI18nConfig(options: CreateI18nConfigOptions): I18nConfigResult;
175
531
 
532
+ /**
533
+ * Provides built-in locale configurations for Korean, English, and Japanese.
534
+ *
535
+ * Used as the default value for `supportedLocales` in {@link createI18nConfig}.
536
+ */
176
537
  declare const DEFAULT_LOCALES: LocaleConfig[];
538
+ /**
539
+ * Lists the locale codes from {@link DEFAULT_LOCALES} (`["ko", "en", "ja"]`).
540
+ */
177
541
  declare const SUPPORTED_LOCALES: string[];
178
542
 
179
543
  export { type BuildModuleTranslationsOptions, type ComponentTranslations, type CreateI18nConfigOptions, DATE_TIME_STYLES, DEFAULT_LOCALES, type DateTimeFormatOptions, type DateTimeStyle, type I18nConfigResult, I18nextAdapter, type I18nextAdapterOptions, type II18nAdapter, type LocaleCode, type LocaleConfig, type LocaleInfo, type ModuleTranslations, NUMBER_FORMAT_STYLES, type NumberFormatOptions, type NumberFormatStyle, type PluralForms, SUPPORTED_LOCALES, TEXT_DIRECTIONS, TRANSLATION_LOAD_STATES, type TextDirection, type TranslationLoadState, type TranslationNamespace, type TranslationResources, type TranslationValues, buildModuleTranslations, createI18nConfig };
package/dist/index.js CHANGED
@@ -249,9 +249,18 @@ var I18nextAdapter = class {
249
249
  this.localeChangeHandlers.delete(handler);
250
250
  };
251
251
  }
252
+ /**
253
+ * Adds translation resources to the underlying i18next instance, merging with any existing resources.
254
+ * @param locale - The target locale code.
255
+ * @param namespace - The translation namespace.
256
+ * @param resources - The translation key-value pairs to add.
257
+ */
252
258
  addResources(locale, namespace, resources) {
253
259
  this.i18n.addResourceBundle(locale, namespace, resources, true, true);
254
260
  }
261
+ /**
262
+ * Returns the underlying i18next instance for advanced usage or direct integration with `react-i18next`.
263
+ */
255
264
  getI18nextInstance() {
256
265
  return this.i18n;
257
266
  }
package/dist/react.d.ts CHANGED
@@ -1,27 +1,76 @@
1
1
  import * as react_jsx_runtime from 'react/jsx-runtime';
2
2
  import { ReactNode } from 'react';
3
3
 
4
+ /**
5
+ * Represents a BCP 47 locale code string (e.g., `"en"`, `"ko"`, `"ja"`).
6
+ */
4
7
  type LocaleCode = string;
8
+ /**
9
+ * Represents key-value pairs for translation string interpolation.
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * const values: TranslationValues = { name: "Alice", count: 3, active: true };
14
+ * adapter.t("greeting", values); // "Hello, Alice!"
15
+ * ```
16
+ */
5
17
  type TranslationValues = Record<string, string | number | boolean>;
18
+ /**
19
+ * Provides constant values for date/time formatting styles compatible with the `Intl.DateTimeFormat` API.
20
+ *
21
+ * @example
22
+ * ```ts
23
+ * import { DATE_TIME_STYLES } from "@simplix-react/i18n";
24
+ *
25
+ * adapter.formatDate(new Date(), { dateStyle: DATE_TIME_STYLES.LONG });
26
+ * ```
27
+ */
6
28
  declare const DATE_TIME_STYLES: {
7
29
  readonly FULL: "full";
8
30
  readonly LONG: "long";
9
31
  readonly MEDIUM: "medium";
10
32
  readonly SHORT: "short";
11
33
  };
34
+ /**
35
+ * Represents a date/time formatting style derived from {@link DATE_TIME_STYLES}.
36
+ */
12
37
  type DateTimeStyle = (typeof DATE_TIME_STYLES)[keyof typeof DATE_TIME_STYLES];
38
+ /**
39
+ * Provides constant values for number formatting styles compatible with the `Intl.NumberFormat` API.
40
+ *
41
+ * @example
42
+ * ```ts
43
+ * import { NUMBER_FORMAT_STYLES } from "@simplix-react/i18n";
44
+ *
45
+ * adapter.formatNumber(1234.5, { style: NUMBER_FORMAT_STYLES.CURRENCY, currency: "USD" });
46
+ * ```
47
+ */
13
48
  declare const NUMBER_FORMAT_STYLES: {
14
49
  readonly DECIMAL: "decimal";
15
50
  readonly CURRENCY: "currency";
16
51
  readonly PERCENT: "percent";
17
52
  readonly UNIT: "unit";
18
53
  };
54
+ /**
55
+ * Represents a number formatting style derived from {@link NUMBER_FORMAT_STYLES}.
56
+ */
19
57
  type NumberFormatStyle = (typeof NUMBER_FORMAT_STYLES)[keyof typeof NUMBER_FORMAT_STYLES];
58
+ /**
59
+ * Provides constant values for text direction (`"ltr"` or `"rtl"`).
60
+ */
20
61
  declare const TEXT_DIRECTIONS: {
21
62
  readonly LTR: "ltr";
22
63
  readonly RTL: "rtl";
23
64
  };
65
+ /**
66
+ * Represents a text direction value derived from {@link TEXT_DIRECTIONS}.
67
+ */
24
68
  type TextDirection = (typeof TEXT_DIRECTIONS)[keyof typeof TEXT_DIRECTIONS];
69
+ /**
70
+ * Defines plural form strings following the CLDR plural rules.
71
+ *
72
+ * @see {@link https://cldr.unicode.org/index/cldr-spec/plural-rules | CLDR Plural Rules}
73
+ */
25
74
  interface PluralForms {
26
75
  zero?: string;
27
76
  one: string;
@@ -30,76 +79,302 @@ interface PluralForms {
30
79
  many?: string;
31
80
  other: string;
32
81
  }
82
+ /**
83
+ * Configures date/time formatting options passed to `Intl.DateTimeFormat`.
84
+ */
33
85
  interface DateTimeFormatOptions {
86
+ /** The date formatting style. */
34
87
  dateStyle?: DateTimeStyle;
88
+ /** The time formatting style. */
35
89
  timeStyle?: DateTimeStyle;
90
+ /** Whether to use 12-hour time format. */
36
91
  hour12?: boolean;
37
92
  }
93
+ /**
94
+ * Configures number formatting options passed to `Intl.NumberFormat`.
95
+ */
38
96
  interface NumberFormatOptions {
97
+ /** The number formatting style. */
39
98
  style?: NumberFormatStyle;
99
+ /** ISO 4217 currency code (required when `style` is `"currency"`). */
40
100
  currency?: string;
101
+ /** Unit identifier (required when `style` is `"unit"`). */
41
102
  unit?: string;
103
+ /** Minimum number of fraction digits to display. */
42
104
  minimumFractionDigits?: number;
105
+ /** Maximum number of fraction digits to display. */
43
106
  maximumFractionDigits?: number;
44
107
  }
108
+ /**
109
+ * Describes metadata for a single locale including display names, text direction, and default formats.
110
+ */
45
111
  interface LocaleInfo {
112
+ /** BCP 47 locale code. */
46
113
  code: LocaleCode;
114
+ /** Native name of the locale (e.g., "한국어"). */
47
115
  name: string;
116
+ /** English name of the locale (e.g., "Korean"). */
48
117
  englishName: string;
118
+ /** Text direction for the locale. */
49
119
  direction: TextDirection;
120
+ /** Default date format pattern. */
50
121
  dateFormat: string;
122
+ /** Default time format pattern. */
51
123
  timeFormat: string;
124
+ /** Default ISO 4217 currency code. */
52
125
  currency: string;
53
126
  }
127
+ /**
128
+ * Represents a translation namespace identifier used to scope translation keys.
129
+ */
54
130
  type TranslationNamespace = string;
131
+ /**
132
+ * Provides constant values representing translation resource loading states.
133
+ */
55
134
  declare const TRANSLATION_LOAD_STATES: {
56
135
  readonly IDLE: "idle";
57
136
  readonly LOADING: "loading";
58
137
  readonly LOADED: "loaded";
59
138
  readonly ERROR: "error";
60
139
  };
140
+ /**
141
+ * Represents a translation loading state derived from {@link TRANSLATION_LOAD_STATES}.
142
+ */
61
143
  type TranslationLoadState = (typeof TRANSLATION_LOAD_STATES)[keyof typeof TRANSLATION_LOAD_STATES];
62
144
 
145
+ /**
146
+ * Defines the contract for an internationalization adapter.
147
+ *
148
+ * Provides translation lookup, locale management, and formatting capabilities.
149
+ * Implement this interface to integrate a custom i18n backend.
150
+ *
151
+ * @see {@link I18nextAdapter} for the built-in i18next implementation.
152
+ *
153
+ * @example
154
+ * ```ts
155
+ * import type { II18nAdapter } from "@simplix-react/i18n";
156
+ *
157
+ * class CustomAdapter implements II18nAdapter {
158
+ * // ... implement all required members
159
+ * }
160
+ * ```
161
+ */
63
162
  interface II18nAdapter {
163
+ /** Unique identifier for this adapter implementation. */
64
164
  readonly id: string;
165
+ /** Human-readable name for this adapter. */
65
166
  readonly name: string;
167
+ /** Currently active locale code. */
66
168
  readonly locale: LocaleCode;
169
+ /** Locale code used when a translation key is missing in the active locale. */
67
170
  readonly fallbackLocale: LocaleCode;
171
+ /** List of all locale codes supported by this adapter. */
68
172
  readonly availableLocales: LocaleCode[];
173
+ /**
174
+ * Initializes the adapter with an optional default locale.
175
+ * @param defaultLocale - The locale to activate on initialization.
176
+ */
69
177
  initialize(defaultLocale?: LocaleCode): Promise<void>;
178
+ /** Disposes of the adapter and releases all resources. */
70
179
  dispose(): Promise<void>;
180
+ /**
181
+ * Changes the active locale.
182
+ * @param locale - The target locale code.
183
+ */
71
184
  setLocale(locale: LocaleCode): Promise<void>;
185
+ /**
186
+ * Returns metadata for the given locale, or `null` if unsupported.
187
+ * @param locale - The locale code to look up.
188
+ */
72
189
  getLocaleInfo(locale: LocaleCode): LocaleInfo | null;
190
+ /**
191
+ * Translates a key with optional interpolation values.
192
+ * @param key - The translation key.
193
+ * @param values - Interpolation values.
194
+ */
73
195
  t(key: string, values?: TranslationValues): string;
196
+ /**
197
+ * Translates a namespaced key with optional interpolation values.
198
+ * @param namespace - The translation namespace.
199
+ * @param key - The translation key within the namespace.
200
+ * @param values - Interpolation values.
201
+ */
74
202
  tn(namespace: TranslationNamespace, key: string, values?: TranslationValues): string;
203
+ /**
204
+ * Translates a key with plural form selection based on count.
205
+ * @param key - The translation key.
206
+ * @param count - The count for plural selection.
207
+ * @param values - Additional interpolation values.
208
+ */
75
209
  tp(key: string, count: number, values?: TranslationValues): string;
210
+ /**
211
+ * Checks whether a translation key exists.
212
+ * @param key - The translation key to check.
213
+ * @param namespace - Optional namespace to scope the lookup.
214
+ */
76
215
  exists(key: string, namespace?: TranslationNamespace): boolean;
216
+ /**
217
+ * Formats a date according to the active locale.
218
+ * @param date - The date to format.
219
+ * @param options - Formatting options.
220
+ */
77
221
  formatDate(date: Date, options?: DateTimeFormatOptions): string;
222
+ /**
223
+ * Formats a time according to the active locale.
224
+ * @param date - The date/time to format.
225
+ * @param options - Formatting options.
226
+ */
78
227
  formatTime(date: Date, options?: DateTimeFormatOptions): string;
228
+ /**
229
+ * Formats a date and time together according to the active locale.
230
+ * @param date - The date/time to format.
231
+ * @param options - Formatting options.
232
+ */
79
233
  formatDateTime(date: Date, options?: DateTimeFormatOptions): string;
234
+ /**
235
+ * Formats a date as a human-readable relative time string (e.g., "3 hours ago").
236
+ * @param date - The date to compare against the current time.
237
+ */
80
238
  formatRelativeTime(date: Date): string;
239
+ /**
240
+ * Formats a number according to the active locale.
241
+ * @param value - The number to format.
242
+ * @param options - Formatting options.
243
+ */
81
244
  formatNumber(value: number, options?: NumberFormatOptions): string;
245
+ /**
246
+ * Formats a number as a currency string according to the active locale.
247
+ * @param value - The monetary value to format.
248
+ * @param currency - ISO 4217 currency code override (defaults to the locale's currency).
249
+ */
82
250
  formatCurrency(value: number, currency?: string): string;
251
+ /**
252
+ * Loads translation resources for a given locale and namespace.
253
+ * @param locale - The target locale code.
254
+ * @param namespace - The translation namespace.
255
+ * @param translations - The translation key-value pairs to load.
256
+ */
83
257
  loadTranslations(locale: LocaleCode, namespace: TranslationNamespace, translations: Record<string, string | PluralForms>): void;
258
+ /**
259
+ * Returns the loading state of translation resources.
260
+ * @param locale - The locale to check.
261
+ * @param namespace - Optional namespace to check (defaults to `"translation"`).
262
+ */
84
263
  getLoadState(locale: LocaleCode, namespace?: TranslationNamespace): TranslationLoadState;
264
+ /**
265
+ * Registers a callback invoked whenever the active locale changes.
266
+ * @param handler - The callback receiving the new locale code.
267
+ * @returns A function that unregisters the handler when called.
268
+ */
85
269
  onLocaleChange(handler: (locale: LocaleCode) => void): () => void;
86
270
  }
87
271
 
272
+ /**
273
+ * Props for the {@link I18nProvider} component.
274
+ */
88
275
  interface I18nProviderProps {
276
+ /** Child components that will have access to the i18n adapter. */
89
277
  children: ReactNode;
278
+ /** The i18n adapter instance to provide via React context. */
90
279
  adapter: II18nAdapter;
91
280
  }
281
+ /**
282
+ * Provides an {@link II18nAdapter} instance to descendant components via React context.
283
+ *
284
+ * Wrap your application (or a subtree) with this provider to enable the
285
+ * {@link useTranslation}, {@link useLocale}, and {@link useI18n} hooks.
286
+ *
287
+ * @param props - The provider props.
288
+ *
289
+ * @example
290
+ * ```tsx
291
+ * import { I18nProvider } from "@simplix-react/i18n/react";
292
+ * import { createI18nConfig } from "@simplix-react/i18n";
293
+ *
294
+ * const { adapter, i18nReady } = createI18nConfig({ defaultLocale: "ko" });
295
+ * await i18nReady;
296
+ *
297
+ * function App() {
298
+ * return (
299
+ * <I18nProvider adapter={adapter}>
300
+ * <MyComponent />
301
+ * </I18nProvider>
302
+ * );
303
+ * }
304
+ * ```
305
+ */
92
306
  declare function I18nProvider({ children, adapter }: I18nProviderProps): react_jsx_runtime.JSX.Element;
307
+ /**
308
+ * Returns the {@link II18nAdapter} from the nearest {@link I18nProvider}, or `null` if none exists.
309
+ *
310
+ * Prefer {@link useTranslation} or {@link useLocale} for most use cases.
311
+ * Use this hook when you need direct access to the full adapter API.
312
+ */
93
313
  declare function useI18nAdapter(): II18nAdapter | null;
94
314
 
95
- type TranslateFunction = (key: string, values?: TranslationValues) => string;
96
- interface UseTranslationReturn {
97
- t: TranslateFunction;
315
+ /**
316
+ * A type-safe translation function that maps keys to translated strings.
317
+ *
318
+ * @typeParam TKeys - Union of allowed translation key strings.
319
+ */
320
+ type TranslateFunction<TKeys extends string = string> = (key: TKeys, values?: TranslationValues) => string;
321
+ /**
322
+ * Represents the return value of the {@link useTranslation} hook.
323
+ *
324
+ * @typeParam TKeys - Union of allowed translation key strings.
325
+ */
326
+ interface UseTranslationReturn<TKeys extends string = string> {
327
+ /** Translates a key within the hook's namespace. */
328
+ t: TranslateFunction<TKeys>;
329
+ /** The currently active locale code. */
98
330
  locale: LocaleCode;
331
+ /** Checks whether a translation key exists in the hook's namespace. */
99
332
  exists: (key: string) => boolean;
100
333
  }
101
- declare function useTranslation(namespace: string): UseTranslationReturn;
334
+ /**
335
+ * Provides namespace-scoped translation capabilities with automatic re-rendering on locale changes.
336
+ *
337
+ * Uses `useSyncExternalStore` to subscribe to locale changes from the adapter,
338
+ * ensuring consistent rendering during concurrent React features.
339
+ *
340
+ * @typeParam TKeys - Union of allowed translation key strings for type-safe lookups.
341
+ * @param namespace - The translation namespace to scope all lookups to.
342
+ * @returns A {@link UseTranslationReturn} object with `t`, `locale`, and `exists`.
343
+ *
344
+ * @example
345
+ * ```tsx
346
+ * import { useTranslation } from "@simplix-react/i18n/react";
347
+ *
348
+ * function Greeting() {
349
+ * const { t, locale } = useTranslation("common");
350
+ * return <p>{t("greeting")} (locale: {locale})</p>;
351
+ * }
352
+ * ```
353
+ */
354
+ declare function useTranslation<TKeys extends string = string>(namespace: string): UseTranslationReturn<TKeys>;
355
+ /**
356
+ * Returns the {@link II18nAdapter} from context for direct adapter access.
357
+ *
358
+ * Shorthand for {@link useI18nAdapter}. Use {@link useTranslation} for namespace-scoped translations.
359
+ */
102
360
  declare function useI18n(): II18nAdapter | null;
361
+ /**
362
+ * Returns the currently active locale code and re-renders on locale changes.
363
+ *
364
+ * Uses `useSyncExternalStore` to subscribe to locale changes from the adapter.
365
+ *
366
+ * @returns The active {@link LocaleCode}.
367
+ *
368
+ * @example
369
+ * ```tsx
370
+ * import { useLocale } from "@simplix-react/i18n/react";
371
+ *
372
+ * function LocaleDisplay() {
373
+ * const locale = useLocale();
374
+ * return <span>Current: {locale}</span>;
375
+ * }
376
+ * ```
377
+ */
103
378
  declare function useLocale(): LocaleCode;
104
379
 
105
380
  export { I18nProvider, type I18nProviderProps, type TranslateFunction, type UseTranslationReturn, useI18n, useI18nAdapter, useLocale, useTranslation };
package/package.json CHANGED
@@ -1,8 +1,9 @@
1
1
  {
2
2
  "name": "@simplix-react/i18n",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "Internationalization framework with i18next adapter",
5
5
  "type": "module",
6
+ "sideEffects": false,
6
7
  "exports": {
7
8
  ".": {
8
9
  "types": "./dist/index.d.ts",
@@ -13,14 +14,11 @@
13
14
  "import": "./dist/react.js"
14
15
  }
15
16
  },
16
- "files": ["dist"],
17
- "scripts": {
18
- "build": "tsup",
19
- "dev": "tsup --watch",
20
- "typecheck": "tsc --noEmit",
21
- "lint": "eslint src",
22
- "test": "vitest run --passWithNoTests",
23
- "clean": "rm -rf dist .turbo"
17
+ "files": [
18
+ "dist"
19
+ ],
20
+ "publishConfig": {
21
+ "access": "public"
24
22
  },
25
23
  "peerDependencies": {
26
24
  "i18next": ">=25.0.0",
@@ -28,12 +26,17 @@
28
26
  "react-i18next": ">=16.0.0"
29
27
  },
30
28
  "peerDependenciesMeta": {
31
- "i18next": { "optional": true },
32
- "react": { "optional": true },
33
- "react-i18next": { "optional": true }
29
+ "i18next": {
30
+ "optional": true
31
+ },
32
+ "react": {
33
+ "optional": true
34
+ },
35
+ "react-i18next": {
36
+ "optional": true
37
+ }
34
38
  },
35
39
  "devDependencies": {
36
- "@simplix-react/config-typescript": "workspace:*",
37
40
  "@types/react": "^19.0.0",
38
41
  "eslint": "^9.39.2",
39
42
  "i18next": "^25.8.0",
@@ -41,6 +44,16 @@
41
44
  "react-i18next": "^16.0.0",
42
45
  "tsup": "^8.5.1",
43
46
  "typescript": "^5.9.3",
44
- "vitest": "^3.0.0"
47
+ "vitest": "^3.0.0",
48
+ "@simplix-react/config-eslint": "0.0.1",
49
+ "@simplix-react/config-typescript": "0.0.1"
50
+ },
51
+ "scripts": {
52
+ "build": "tsup",
53
+ "dev": "tsup --watch",
54
+ "typecheck": "tsc --noEmit",
55
+ "lint": "eslint src",
56
+ "test": "vitest run --passWithNoTests",
57
+ "clean": "rm -rf dist .turbo"
45
58
  }
46
- }
59
+ }