@intl-party/react 1.1.1 → 1.1.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.
package/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2024 IntlParty Team
3
+ Copyright (c) 2025-2026 IntlParty Team
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
18
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
19
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
20
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,473 @@
1
+ # @intl-party/react
2
+
3
+ **React integration for IntlParty with perfect TypeScript support and developer experience.**
4
+
5
+ ## ✨ Features
6
+
7
+ - **⚛️ React Hooks**: `useTranslations`, `useLocale`, `useNamespace`
8
+ - **🎯 Context Provider**: `I18nProvider` for app-wide i18n state
9
+ - **🧩 Components**: `Trans`, `LocaleSelector` for declarative translations
10
+ - **🔄 Real-time Updates**: Automatic re-renders when locale changes
11
+ - **🔒 Type-Safe**: Full TypeScript support with auto-completion
12
+ - **⚡ Performance Optimized**: Minimal re-renders and efficient caching
13
+
14
+ ## 🚀 Quick Start
15
+
16
+ ### Installation
17
+
18
+ ```bash
19
+ npm install @intl-party/react @intl-party/core
20
+ ```
21
+
22
+ ### Basic Usage
23
+
24
+ ```tsx
25
+ import React from "react";
26
+ import { I18nProvider, useTranslations } from "@intl-party/react";
27
+ import { createI18n } from "@intl-party/core";
28
+
29
+ // Create i18n instance
30
+ const i18n = createI18n({
31
+ locales: ["en", "es", "fr"],
32
+ defaultLocale: "en",
33
+ namespaces: ["common"],
34
+ });
35
+
36
+ function App() {
37
+ return (
38
+ <I18nProvider i18n={i18n}>
39
+ <Welcome />
40
+ </I18nProvider>
41
+ );
42
+ }
43
+
44
+ function Welcome() {
45
+ const t = useTranslations("common");
46
+
47
+ return (
48
+ <div>
49
+ <h1>{t("welcome")}</h1>
50
+ <p>{t("greeting", { interpolation: { name: "World" } })}</p>
51
+ </div>
52
+ );
53
+ }
54
+ ```
55
+
56
+ ## 🎯 API Reference
57
+
58
+ ### `I18nProvider`
59
+
60
+ Provides i18n context to the React component tree.
61
+
62
+ ```tsx
63
+ <I18nProvider
64
+ i18n={i18nInstance}
65
+ initialLocale="en"
66
+ initialNamespace="common"
67
+ loadingComponent={<Loading />}
68
+ fallbackComponent={<Error />}
69
+ >
70
+ {children}
71
+ </I18nProvider>
72
+ ```
73
+
74
+ #### Props
75
+
76
+ ```typescript
77
+ interface I18nProviderProps {
78
+ children: ReactNode;
79
+ i18n?: I18nInstance; // I18n instance
80
+ config?: I18nConfig; // Config (creates instance if not provided)
81
+ initialLocale?: Locale; // Initial locale
82
+ initialNamespace?: Namespace; // Initial namespace
83
+ loadingComponent?: ReactNode; // Loading component
84
+ fallbackComponent?: ReactNode; // Error fallback component
85
+ onLocaleChange?: (locale: Locale) => void;
86
+ onNamespaceChange?: (namespace: Namespace) => void;
87
+ onError?: (error: Error) => void;
88
+ }
89
+ ```
90
+
91
+ ### Hooks
92
+
93
+ #### `useTranslations(namespace?)`
94
+
95
+ Main hook for using translations.
96
+
97
+ ```tsx
98
+ // Without namespace (uses default)
99
+ const t = useTranslations();
100
+
101
+ // With namespace
102
+ const t = useTranslations("common");
103
+
104
+ // Usage
105
+ t("welcome"); // "Welcome!"
106
+ t("greeting", { interpolation: { name: "John" } }); // "Hello John!"
107
+ t("navigation.home"); // "Home"
108
+ ```
109
+
110
+ #### `useLocale()`
111
+
112
+ Get and set the current locale.
113
+
114
+ ```tsx
115
+ function LocaleComponent() {
116
+ const [locale, setLocale] = useLocale();
117
+
118
+ return (
119
+ <div>
120
+ <p>Current locale: {locale}</p>
121
+ <button onClick={() => setLocale("es")}>Español</button>
122
+ <button onClick={() => setLocale("fr")}>Français</button>
123
+ </div>
124
+ );
125
+ }
126
+ ```
127
+
128
+ #### `useNamespace()`
129
+
130
+ Get and set the current namespace.
131
+
132
+ ```tsx
133
+ function NamespaceComponent() {
134
+ const [namespace, setNamespace] = useNamespace();
135
+
136
+ return (
137
+ <div>
138
+ <p>Current namespace: {namespace}</p>
139
+ <button onClick={() => setNamespace("navigation")}>Navigation</button>
140
+ <button onClick={() => setNamespace("auth")}>Auth</button>
141
+ </div>
142
+ );
143
+ }
144
+ ```
145
+
146
+ #### `useI18nContext()`
147
+
148
+ Access the full i18n context.
149
+
150
+ ```tsx
151
+ function AdvancedComponent() {
152
+ const { i18n, locale, namespace, t, setLocale, setNamespace } =
153
+ useI18nContext();
154
+
155
+ return (
156
+ <div>
157
+ <p>Locale: {locale}</p>
158
+ <p>Namespace: {namespace}</p>
159
+ <button
160
+ onClick={() => i18n.addTranslations("en", "common", { new: "Key" })}
161
+ >
162
+ Add Translation
163
+ </button>
164
+ </div>
165
+ );
166
+ }
167
+ ```
168
+
169
+ ## 🧩 Components
170
+
171
+ ### `Trans`
172
+
173
+ Component for translations with rich text and interpolation.
174
+
175
+ ```tsx
176
+ import { Trans } from "@intl-party/react";
177
+
178
+ function RichText() {
179
+ return (
180
+ <Trans
181
+ i18nKey="rich.greeting"
182
+ interpolation={{ name: "John" }}
183
+ components={{
184
+ bold: <strong />,
185
+ link: <a href="/about" />,
186
+ }}
187
+ >
188
+ Hello <bold>{{ name }}</bold>! Learn more <link>about</link>.
189
+ </Trans>
190
+ );
191
+ }
192
+ ```
193
+
194
+ ### `LocaleSelector`
195
+
196
+ Pre-built locale selector component.
197
+
198
+ ```tsx
199
+ import { LocaleSelector } from "@intl-party/react";
200
+
201
+ function Header() {
202
+ return (
203
+ <LocaleSelector
204
+ locales={[
205
+ { code: "en", name: "English", flag: "🇺🇸" },
206
+ { code: "es", name: "Español", flag: "🇪🇸" },
207
+ { code: "fr", name: "Français", flag: "🇫🇷" },
208
+ ]}
209
+ variant="flags" // or "dropdown" or "compact"
210
+ />
211
+ );
212
+ }
213
+ ```
214
+
215
+ ## 🎨 Advanced Usage
216
+
217
+ ### Typed Translations
218
+
219
+ ```typescript
220
+ interface AppTranslations {
221
+ common: {
222
+ welcome: string;
223
+ navigation: {
224
+ home: string;
225
+ about: string;
226
+ };
227
+ };
228
+ auth: {
229
+ login: string;
230
+ register: string;
231
+ };
232
+ }
233
+
234
+ // Create typed i18n instance
235
+ const i18n = createI18n<AppTranslations>({
236
+ locales: ["en", "es", "fr"],
237
+ defaultLocale: "en",
238
+ namespaces: ["common", "auth"],
239
+ });
240
+
241
+ // Use with full type safety
242
+ function TypedComponent() {
243
+ const t = useTranslations<AppTranslations["common"]>("common");
244
+
245
+ return (
246
+ <div>
247
+ {t("welcome")} {/* ✅ Type-safe */}
248
+ {t("navigation.home")} {/* ✅ Type-safe */}
249
+ {t("invalid.key")} {/* ❌ TypeScript error */}
250
+ </div>
251
+ );
252
+ }
253
+ ```
254
+
255
+ ### Multiple Namespaces
256
+
257
+ ```tsx
258
+ function MultiNamespaceComponent() {
259
+ const commonT = useTranslations("common");
260
+ const authT = useTranslations("auth");
261
+
262
+ return (
263
+ <div>
264
+ <h1>{commonT("welcome")}</h1>
265
+ <button>{authT("login")}</button>
266
+ </div>
267
+ );
268
+ }
269
+ ```
270
+
271
+ ### Server-Side Rendering
272
+
273
+ ```tsx
274
+ // Server component (Next.js App Router)
275
+ async function ServerPage() {
276
+ const t = await getServerTranslations("common");
277
+
278
+ return (
279
+ <div>
280
+ <h1>{t("welcome")}</h1>
281
+ </div>
282
+ );
283
+ }
284
+ ```
285
+
286
+ ### Dynamic Namespace Loading
287
+
288
+ ```tsx
289
+ function DynamicComponent({ namespace }: { namespace: string }) {
290
+ const t = useTranslations(namespace);
291
+
292
+ return (
293
+ <div>
294
+ <h2>Namespace: {namespace}</h2>
295
+ <p>{t("title")}</p>
296
+ </div>
297
+ );
298
+ }
299
+ ```
300
+
301
+ ## 🔧 Utilities
302
+
303
+ ### `createNamespaceHOC(namespace)`
304
+
305
+ Higher-order component for automatic namespacing.
306
+
307
+ ```tsx
308
+ import { createNamespaceHOC } from "@intl-party/react";
309
+
310
+ const withNavigation = createNamespaceHOC("navigation");
311
+
312
+ function NavigationComponent({ t }) {
313
+ return (
314
+ <nav>
315
+ <a href="/">{t("home")}</a>
316
+ <a href="/about">{t("about")}</a>
317
+ </nav>
318
+ );
319
+ }
320
+
321
+ export default withNavigation(NavigationComponent);
322
+ ```
323
+
324
+ ### `useMultipleTranslations(namespaces)`
325
+
326
+ Use multiple namespaces at once.
327
+
328
+ ```tsx
329
+ function MultiNamespaceComponent() {
330
+ const { common, auth, navigation } = useMultipleTranslations([
331
+ "common",
332
+ "auth",
333
+ "navigation",
334
+ ]);
335
+
336
+ return (
337
+ <div>
338
+ <h1>{common("welcome")}</h1>
339
+ <button>{auth("login")}</button>
340
+ <nav>{navigation("home")}</nav>
341
+ </div>
342
+ );
343
+ }
344
+ ```
345
+
346
+ ## 🎨 Styling
347
+
348
+ ### Theme Support
349
+
350
+ ```tsx
351
+ import { I18nProvider } from "@intl-party/react";
352
+
353
+ function ThemedApp() {
354
+ return (
355
+ <I18nProvider
356
+ i18n={i18n}
357
+ theme="dark" // or "light", "auto"
358
+ >
359
+ <App />
360
+ </I18nProvider>
361
+ );
362
+ }
363
+ ```
364
+
365
+ ### Custom Components
366
+
367
+ ```tsx
368
+ // Custom translation component
369
+ function CustomTrans({ i18nKey, interpolation, components }) {
370
+ const t = useTranslations();
371
+
372
+ return (
373
+ <span className="translation">
374
+ {t(i18nKey, { interpolation, components })}
375
+ </span>
376
+ );
377
+ }
378
+ ```
379
+
380
+ ## 🔄 Migration from react-i18next
381
+
382
+ ### Simple Migration
383
+
384
+ ```tsx
385
+ // react-i18next
386
+ import { useTranslation } from "react-i18next";
387
+ const { t } = useTranslation();
388
+
389
+ // intl-party/react
390
+ import { useTranslations } from "@intl-party/react";
391
+ const t = useTranslations();
392
+ ```
393
+
394
+ ### Benefits of switching:
395
+
396
+ - ✅ **Better TypeScript**: No more `t('key' as any)`
397
+ - ✅ **Simpler API**: Less boilerplate code
398
+ - ✅ **Performance**: Optimized re-rendering
399
+ - ✅ **Modern**: Built for React 18+ and concurrent features
400
+
401
+ ## 📦 Exports
402
+
403
+ ```typescript
404
+ // Provider and context
405
+ export {
406
+ I18nProvider,
407
+ TypedI18nProvider,
408
+ ScopedI18nProvider,
409
+ useI18nContext,
410
+ useTypedI18nContext,
411
+ withI18n,
412
+ type I18nProviderProps,
413
+ type TypedI18nProviderProps,
414
+ type ScopedI18nProviderProps,
415
+ type I18nContextValue,
416
+ type TypedI18nContextValue,
417
+ };
418
+
419
+ // Hooks
420
+ export {
421
+ useTranslations,
422
+ useTypedTranslations,
423
+ useT,
424
+ useTypedT,
425
+ useScopedTranslations,
426
+ useMultipleTranslations,
427
+ useOptionalTranslation,
428
+ useTranslationWithFallback,
429
+ useHasTranslation,
430
+ useTranslationValue,
431
+ useInterpolatedTranslation,
432
+ usePluralization,
433
+ };
434
+
435
+ // Locale and namespace hooks
436
+ export {
437
+ useLocale,
438
+ useLocaleInfo,
439
+ useLocaleSwitch,
440
+ useBrowserLocale,
441
+ useLocalePreference,
442
+ useDirection,
443
+ useFormatting,
444
+ useNamespace,
445
+ useNamespaceInfo,
446
+ useNamespaceSwitch,
447
+ useMultipleNamespaces,
448
+ useNamespacePreloading,
449
+ };
450
+
451
+ // Components
452
+ export {
453
+ Trans,
454
+ ConditionalTrans,
455
+ PluralTrans,
456
+ RichTrans,
457
+ LocaleSelector,
458
+ FlagLocaleSelector,
459
+ CompactLocaleSelector,
460
+ AccessibleLocaleSelector,
461
+ };
462
+
463
+ // Utilities
464
+ export { createI18nHook, createNamespaceHOC, I18nErrorBoundary };
465
+ ```
466
+
467
+ ## 🤝 Contributing
468
+
469
+ See the [main README](../../README.md) for contribution guidelines.
470
+
471
+ ## 📄 License
472
+
473
+ MIT
@@ -0,0 +1,196 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as _intl_party_core from '@intl-party/core';
3
+ import { I18nConfig, I18nInstance, Locale, Namespace, TranslationFunction, TypedTranslationFunction, TranslationKey, TranslationOptions } from '@intl-party/core';
4
+ export { DeepKeyOf, I18nConfig, I18nInstance, Locale, Namespace, TranslationFunction, TranslationKey, TranslationOptions, TranslationValue, Translations, TypedI18nInstance, TypedTranslationFunction } from '@intl-party/core';
5
+ import React, { ReactNode } from 'react';
6
+
7
+ interface I18nContextValue {
8
+ i18n: I18nInstance;
9
+ locale: Locale;
10
+ namespace: Namespace;
11
+ t: TranslationFunction;
12
+ setLocale: (locale: Locale) => void;
13
+ setNamespace: (namespace: Namespace) => void;
14
+ isLoading: boolean;
15
+ }
16
+ interface TypedI18nContextValue<T extends Record<string, any> = Record<string, any>> extends Omit<I18nContextValue, "t"> {
17
+ t: TypedTranslationFunction<T>;
18
+ }
19
+ interface I18nProviderProps {
20
+ children: ReactNode;
21
+ config?: I18nConfig;
22
+ i18n?: I18nInstance;
23
+ initialLocale?: Locale;
24
+ initialNamespace?: Namespace;
25
+ loadingComponent?: ReactNode;
26
+ fallbackComponent?: ReactNode;
27
+ onLocaleChange?: (locale: Locale) => void;
28
+ onNamespaceChange?: (namespace: Namespace) => void;
29
+ onError?: (error: Error) => void;
30
+ }
31
+ declare function I18nProvider({ children, config, i18n: externalI18n, initialLocale, initialNamespace, loadingComponent, fallbackComponent, onLocaleChange, onNamespaceChange, onError, }: I18nProviderProps): react_jsx_runtime.JSX.Element;
32
+ declare function useI18nContext(): I18nContextValue;
33
+ interface TypedI18nProviderProps<T extends Record<string, any>> extends Omit<I18nProviderProps, "i18n"> {
34
+ i18n?: I18nInstance;
35
+ }
36
+ declare function TypedI18nProvider<T extends Record<string, any>>({ children, ...props }: TypedI18nProviderProps<T>): react_jsx_runtime.JSX.Element;
37
+ declare function useTypedI18nContext<T extends Record<string, any>>(): TypedI18nContextValue<T>;
38
+ interface WithI18nProps {
39
+ i18n: I18nContextValue;
40
+ }
41
+ declare function withI18n<P extends object>(Component: React.ComponentType<P & WithI18nProps>): React.ComponentType<P>;
42
+ interface ScopedI18nProviderProps {
43
+ children: ReactNode;
44
+ namespace: Namespace;
45
+ locale?: Locale;
46
+ }
47
+ declare function ScopedI18nProvider({ children, namespace, locale, }: ScopedI18nProviderProps): react_jsx_runtime.JSX.Element;
48
+
49
+ declare function useTranslations(namespace?: Namespace): TranslationFunction;
50
+ declare function useTypedTranslations<T extends Record<string, any>>(namespace?: Namespace): TypedTranslationFunction<T>;
51
+ declare const useT: typeof useTranslations;
52
+ declare const useTypedT: typeof useTypedTranslations;
53
+ declare function useScopedTranslations(namespace: Namespace): TranslationFunction;
54
+ declare function useMultipleTranslations(namespaces: Namespace[]): Record<Namespace, TranslationFunction>;
55
+ declare function useOptionalTranslation(key: TranslationKey, namespace?: Namespace, options?: TranslationOptions): string | undefined;
56
+ declare function useTranslationWithFallback(key: TranslationKey, fallback: string, namespace?: Namespace, options?: TranslationOptions): string;
57
+ declare function useHasTranslation(): (key: TranslationKey, namespace?: Namespace) => boolean;
58
+ declare function useTranslationValue(): (key: TranslationKey, namespace?: Namespace) => any;
59
+ declare function useInterpolatedTranslation(key: TranslationKey, variables: Record<string, any>, namespace?: Namespace): string;
60
+ declare function usePluralization(key: TranslationKey, count: number, namespace?: Namespace, additionalOptions?: Omit<TranslationOptions, "count">): string;
61
+
62
+ declare function useLocale(): [Locale, (locale: Locale) => void];
63
+ declare function useLocaleInfo(): {
64
+ current: string;
65
+ available: string[];
66
+ fallbackChain: string[];
67
+ isRTL: boolean;
68
+ direction: string;
69
+ };
70
+ declare function useLocaleSwitch(): {
71
+ switchLocale: (locale: Locale) => void;
72
+ isLocaleAvailable: (locale: Locale) => boolean;
73
+ availableLocales: string[];
74
+ };
75
+ declare function useBrowserLocale(): {
76
+ detected: string;
77
+ browser: string;
78
+ supported: boolean;
79
+ } | null;
80
+ declare function useLocalePreference(): {
81
+ current: string;
82
+ save: (newLocale: Locale) => void;
83
+ load: () => string | null;
84
+ clear: () => void;
85
+ };
86
+ declare function useDirection(): "ltr" | "rtl";
87
+ declare function useFormatting(): {
88
+ formatDate: (date: Date, options?: Intl.DateTimeFormatOptions) => string;
89
+ formatNumber: (number: number, options?: Intl.NumberFormatOptions) => string;
90
+ formatCurrency: (amount: number, currency: string, options?: Intl.NumberFormatOptions) => string;
91
+ formatRelativeTime: (value: number, unit: Intl.RelativeTimeFormatUnit, options?: Intl.RelativeTimeFormatOptions) => string;
92
+ };
93
+
94
+ declare function useNamespace(): [Namespace, (namespace: Namespace) => void];
95
+ declare function useNamespaceInfo(): {
96
+ current: string;
97
+ available: string[];
98
+ isAvailable: boolean;
99
+ };
100
+ declare function useNamespaceSwitch(): {
101
+ switchNamespace: (namespace: Namespace) => void;
102
+ isNamespaceAvailable: (namespace: Namespace) => boolean;
103
+ availableNamespaces: string[];
104
+ };
105
+ declare function useMultipleNamespaces(namespaces: Namespace[]): {
106
+ translators: Record<string, _intl_party_core.TranslationFunction>;
107
+ isAllAvailable: boolean;
108
+ getMissingNamespaces: () => string[];
109
+ };
110
+ declare function useNamespacePreloading(): {
111
+ preloadNamespace: (namespace: Namespace) => Promise<void>;
112
+ preloadNamespaces: (namespaces: Namespace[]) => Promise<void>;
113
+ };
114
+
115
+ interface TransProps {
116
+ i18nKey: TranslationKey;
117
+ namespace?: Namespace;
118
+ values?: Record<string, any>;
119
+ components?: Record<string, ReactNode>;
120
+ count?: number;
121
+ fallback?: string;
122
+ children?: ReactNode;
123
+ }
124
+ declare function Trans({ i18nKey, namespace, values, components, count, fallback, children, }: TransProps): react_jsx_runtime.JSX.Element;
125
+ interface ConditionalTransProps extends TransProps {
126
+ when?: boolean;
127
+ fallbackComponent?: ReactNode;
128
+ }
129
+ declare function ConditionalTrans({ when, fallbackComponent, ...transProps }: ConditionalTransProps): react_jsx_runtime.JSX.Element;
130
+ interface PluralTransProps extends Omit<TransProps, "count"> {
131
+ count: number;
132
+ zero?: TranslationKey;
133
+ one?: TranslationKey;
134
+ other?: TranslationKey;
135
+ }
136
+ declare function PluralTrans({ count, zero, one, other, i18nKey, ...props }: PluralTransProps): react_jsx_runtime.JSX.Element;
137
+ interface RichTransProps extends TransProps {
138
+ allowedTags?: string[];
139
+ sanitize?: boolean;
140
+ }
141
+ declare function RichTrans({ allowedTags, sanitize, ...transProps }: RichTransProps): react_jsx_runtime.JSX.Element;
142
+
143
+ interface LocaleSelectorProps {
144
+ className?: string;
145
+ style?: React.CSSProperties;
146
+ placeholder?: string;
147
+ disabled?: boolean;
148
+ showNativeNames?: boolean;
149
+ filterLocales?: (locale: Locale) => boolean;
150
+ formatLocale?: (locale: Locale) => string;
151
+ onLocaleChange?: (locale: Locale) => void;
152
+ variant?: "select" | "buttons" | "dropdown";
153
+ }
154
+ declare function LocaleSelector({ className, style, placeholder, disabled, showNativeNames, filterLocales, formatLocale, onLocaleChange, variant, }: LocaleSelectorProps): react_jsx_runtime.JSX.Element | null;
155
+ interface FlagLocaleSelectorProps extends Omit<LocaleSelectorProps, "showNativeNames"> {
156
+ flagMap?: Record<Locale, string>;
157
+ showFlags?: boolean;
158
+ showLabels?: boolean;
159
+ }
160
+ declare function FlagLocaleSelector({ flagMap, showFlags, showLabels, variant, ...props }: FlagLocaleSelectorProps): react_jsx_runtime.JSX.Element;
161
+ interface CompactLocaleSelectorProps extends LocaleSelectorProps {
162
+ maxVisibleLocales?: number;
163
+ }
164
+ declare function CompactLocaleSelector({ maxVisibleLocales, ...props }: CompactLocaleSelectorProps): react_jsx_runtime.JSX.Element;
165
+ interface AccessibleLocaleSelectorProps extends LocaleSelectorProps {
166
+ ariaLabel?: string;
167
+ ariaDescribedBy?: string;
168
+ }
169
+ declare function AccessibleLocaleSelector({ ariaLabel, ariaDescribedBy, ...props }: AccessibleLocaleSelectorProps): react_jsx_runtime.JSX.Element;
170
+
171
+ declare const VERSION = "0.1.0";
172
+ declare function createI18nHook<T extends Record<string, any>>(): {
173
+ useTranslations: (namespace?: _intl_party_core.Namespace) => _intl_party_core.TypedTranslationFunction<T>;
174
+ useT: (namespace?: _intl_party_core.Namespace) => _intl_party_core.TypedTranslationFunction<T>;
175
+ };
176
+ declare function createNamespaceHOC(namespace: string): <P extends object>(Component: React.ComponentType<P>) => React.ComponentType<P>;
177
+ declare class I18nErrorBoundary extends React.Component<{
178
+ children: React.ReactNode;
179
+ fallback?: React.ComponentType<{
180
+ error: Error;
181
+ }>;
182
+ onError?: (error: Error, errorInfo: React.ErrorInfo) => void;
183
+ }, {
184
+ hasError: boolean;
185
+ error?: Error;
186
+ }> {
187
+ constructor(props: any);
188
+ static getDerivedStateFromError(error: Error): {
189
+ hasError: boolean;
190
+ error: Error;
191
+ };
192
+ componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void;
193
+ render(): string | number | boolean | Iterable<React.ReactNode> | react_jsx_runtime.JSX.Element | null | undefined;
194
+ }
195
+
196
+ export { AccessibleLocaleSelector, type AccessibleLocaleSelectorProps, CompactLocaleSelector, type CompactLocaleSelectorProps, ConditionalTrans, type ConditionalTransProps, FlagLocaleSelector, type FlagLocaleSelectorProps, type I18nContextValue, I18nErrorBoundary, I18nProvider, type I18nProviderProps, LocaleSelector, type LocaleSelectorProps, PluralTrans, type PluralTransProps, RichTrans, type RichTransProps, ScopedI18nProvider, type ScopedI18nProviderProps, Trans, type TransProps, type TypedI18nContextValue, TypedI18nProvider, type TypedI18nProviderProps, VERSION, type WithI18nProps, createI18nHook, createNamespaceHOC, useBrowserLocale, useDirection, useFormatting, useHasTranslation, useI18nContext, useInterpolatedTranslation, useLocale, useLocaleInfo, useLocalePreference, useLocaleSwitch, useMultipleNamespaces, useMultipleTranslations, useNamespace, useNamespaceInfo, useNamespacePreloading, useNamespaceSwitch, useOptionalTranslation, usePluralization, useScopedTranslations, useT, useTranslationValue, useTranslationWithFallback, useTranslations, useTypedI18nContext, useTypedT, useTypedTranslations, withI18n };
@@ -0,0 +1,196 @@
1
+ import * as react_jsx_runtime from 'react/jsx-runtime';
2
+ import * as _intl_party_core from '@intl-party/core';
3
+ import { I18nConfig, I18nInstance, Locale, Namespace, TranslationFunction, TypedTranslationFunction, TranslationKey, TranslationOptions } from '@intl-party/core';
4
+ export { DeepKeyOf, I18nConfig, I18nInstance, Locale, Namespace, TranslationFunction, TranslationKey, TranslationOptions, TranslationValue, Translations, TypedI18nInstance, TypedTranslationFunction } from '@intl-party/core';
5
+ import React, { ReactNode } from 'react';
6
+
7
+ interface I18nContextValue {
8
+ i18n: I18nInstance;
9
+ locale: Locale;
10
+ namespace: Namespace;
11
+ t: TranslationFunction;
12
+ setLocale: (locale: Locale) => void;
13
+ setNamespace: (namespace: Namespace) => void;
14
+ isLoading: boolean;
15
+ }
16
+ interface TypedI18nContextValue<T extends Record<string, any> = Record<string, any>> extends Omit<I18nContextValue, "t"> {
17
+ t: TypedTranslationFunction<T>;
18
+ }
19
+ interface I18nProviderProps {
20
+ children: ReactNode;
21
+ config?: I18nConfig;
22
+ i18n?: I18nInstance;
23
+ initialLocale?: Locale;
24
+ initialNamespace?: Namespace;
25
+ loadingComponent?: ReactNode;
26
+ fallbackComponent?: ReactNode;
27
+ onLocaleChange?: (locale: Locale) => void;
28
+ onNamespaceChange?: (namespace: Namespace) => void;
29
+ onError?: (error: Error) => void;
30
+ }
31
+ declare function I18nProvider({ children, config, i18n: externalI18n, initialLocale, initialNamespace, loadingComponent, fallbackComponent, onLocaleChange, onNamespaceChange, onError, }: I18nProviderProps): react_jsx_runtime.JSX.Element;
32
+ declare function useI18nContext(): I18nContextValue;
33
+ interface TypedI18nProviderProps<T extends Record<string, any>> extends Omit<I18nProviderProps, "i18n"> {
34
+ i18n?: I18nInstance;
35
+ }
36
+ declare function TypedI18nProvider<T extends Record<string, any>>({ children, ...props }: TypedI18nProviderProps<T>): react_jsx_runtime.JSX.Element;
37
+ declare function useTypedI18nContext<T extends Record<string, any>>(): TypedI18nContextValue<T>;
38
+ interface WithI18nProps {
39
+ i18n: I18nContextValue;
40
+ }
41
+ declare function withI18n<P extends object>(Component: React.ComponentType<P & WithI18nProps>): React.ComponentType<P>;
42
+ interface ScopedI18nProviderProps {
43
+ children: ReactNode;
44
+ namespace: Namespace;
45
+ locale?: Locale;
46
+ }
47
+ declare function ScopedI18nProvider({ children, namespace, locale, }: ScopedI18nProviderProps): react_jsx_runtime.JSX.Element;
48
+
49
+ declare function useTranslations(namespace?: Namespace): TranslationFunction;
50
+ declare function useTypedTranslations<T extends Record<string, any>>(namespace?: Namespace): TypedTranslationFunction<T>;
51
+ declare const useT: typeof useTranslations;
52
+ declare const useTypedT: typeof useTypedTranslations;
53
+ declare function useScopedTranslations(namespace: Namespace): TranslationFunction;
54
+ declare function useMultipleTranslations(namespaces: Namespace[]): Record<Namespace, TranslationFunction>;
55
+ declare function useOptionalTranslation(key: TranslationKey, namespace?: Namespace, options?: TranslationOptions): string | undefined;
56
+ declare function useTranslationWithFallback(key: TranslationKey, fallback: string, namespace?: Namespace, options?: TranslationOptions): string;
57
+ declare function useHasTranslation(): (key: TranslationKey, namespace?: Namespace) => boolean;
58
+ declare function useTranslationValue(): (key: TranslationKey, namespace?: Namespace) => any;
59
+ declare function useInterpolatedTranslation(key: TranslationKey, variables: Record<string, any>, namespace?: Namespace): string;
60
+ declare function usePluralization(key: TranslationKey, count: number, namespace?: Namespace, additionalOptions?: Omit<TranslationOptions, "count">): string;
61
+
62
+ declare function useLocale(): [Locale, (locale: Locale) => void];
63
+ declare function useLocaleInfo(): {
64
+ current: string;
65
+ available: string[];
66
+ fallbackChain: string[];
67
+ isRTL: boolean;
68
+ direction: string;
69
+ };
70
+ declare function useLocaleSwitch(): {
71
+ switchLocale: (locale: Locale) => void;
72
+ isLocaleAvailable: (locale: Locale) => boolean;
73
+ availableLocales: string[];
74
+ };
75
+ declare function useBrowserLocale(): {
76
+ detected: string;
77
+ browser: string;
78
+ supported: boolean;
79
+ } | null;
80
+ declare function useLocalePreference(): {
81
+ current: string;
82
+ save: (newLocale: Locale) => void;
83
+ load: () => string | null;
84
+ clear: () => void;
85
+ };
86
+ declare function useDirection(): "ltr" | "rtl";
87
+ declare function useFormatting(): {
88
+ formatDate: (date: Date, options?: Intl.DateTimeFormatOptions) => string;
89
+ formatNumber: (number: number, options?: Intl.NumberFormatOptions) => string;
90
+ formatCurrency: (amount: number, currency: string, options?: Intl.NumberFormatOptions) => string;
91
+ formatRelativeTime: (value: number, unit: Intl.RelativeTimeFormatUnit, options?: Intl.RelativeTimeFormatOptions) => string;
92
+ };
93
+
94
+ declare function useNamespace(): [Namespace, (namespace: Namespace) => void];
95
+ declare function useNamespaceInfo(): {
96
+ current: string;
97
+ available: string[];
98
+ isAvailable: boolean;
99
+ };
100
+ declare function useNamespaceSwitch(): {
101
+ switchNamespace: (namespace: Namespace) => void;
102
+ isNamespaceAvailable: (namespace: Namespace) => boolean;
103
+ availableNamespaces: string[];
104
+ };
105
+ declare function useMultipleNamespaces(namespaces: Namespace[]): {
106
+ translators: Record<string, _intl_party_core.TranslationFunction>;
107
+ isAllAvailable: boolean;
108
+ getMissingNamespaces: () => string[];
109
+ };
110
+ declare function useNamespacePreloading(): {
111
+ preloadNamespace: (namespace: Namespace) => Promise<void>;
112
+ preloadNamespaces: (namespaces: Namespace[]) => Promise<void>;
113
+ };
114
+
115
+ interface TransProps {
116
+ i18nKey: TranslationKey;
117
+ namespace?: Namespace;
118
+ values?: Record<string, any>;
119
+ components?: Record<string, ReactNode>;
120
+ count?: number;
121
+ fallback?: string;
122
+ children?: ReactNode;
123
+ }
124
+ declare function Trans({ i18nKey, namespace, values, components, count, fallback, children, }: TransProps): react_jsx_runtime.JSX.Element;
125
+ interface ConditionalTransProps extends TransProps {
126
+ when?: boolean;
127
+ fallbackComponent?: ReactNode;
128
+ }
129
+ declare function ConditionalTrans({ when, fallbackComponent, ...transProps }: ConditionalTransProps): react_jsx_runtime.JSX.Element;
130
+ interface PluralTransProps extends Omit<TransProps, "count"> {
131
+ count: number;
132
+ zero?: TranslationKey;
133
+ one?: TranslationKey;
134
+ other?: TranslationKey;
135
+ }
136
+ declare function PluralTrans({ count, zero, one, other, i18nKey, ...props }: PluralTransProps): react_jsx_runtime.JSX.Element;
137
+ interface RichTransProps extends TransProps {
138
+ allowedTags?: string[];
139
+ sanitize?: boolean;
140
+ }
141
+ declare function RichTrans({ allowedTags, sanitize, ...transProps }: RichTransProps): react_jsx_runtime.JSX.Element;
142
+
143
+ interface LocaleSelectorProps {
144
+ className?: string;
145
+ style?: React.CSSProperties;
146
+ placeholder?: string;
147
+ disabled?: boolean;
148
+ showNativeNames?: boolean;
149
+ filterLocales?: (locale: Locale) => boolean;
150
+ formatLocale?: (locale: Locale) => string;
151
+ onLocaleChange?: (locale: Locale) => void;
152
+ variant?: "select" | "buttons" | "dropdown";
153
+ }
154
+ declare function LocaleSelector({ className, style, placeholder, disabled, showNativeNames, filterLocales, formatLocale, onLocaleChange, variant, }: LocaleSelectorProps): react_jsx_runtime.JSX.Element | null;
155
+ interface FlagLocaleSelectorProps extends Omit<LocaleSelectorProps, "showNativeNames"> {
156
+ flagMap?: Record<Locale, string>;
157
+ showFlags?: boolean;
158
+ showLabels?: boolean;
159
+ }
160
+ declare function FlagLocaleSelector({ flagMap, showFlags, showLabels, variant, ...props }: FlagLocaleSelectorProps): react_jsx_runtime.JSX.Element;
161
+ interface CompactLocaleSelectorProps extends LocaleSelectorProps {
162
+ maxVisibleLocales?: number;
163
+ }
164
+ declare function CompactLocaleSelector({ maxVisibleLocales, ...props }: CompactLocaleSelectorProps): react_jsx_runtime.JSX.Element;
165
+ interface AccessibleLocaleSelectorProps extends LocaleSelectorProps {
166
+ ariaLabel?: string;
167
+ ariaDescribedBy?: string;
168
+ }
169
+ declare function AccessibleLocaleSelector({ ariaLabel, ariaDescribedBy, ...props }: AccessibleLocaleSelectorProps): react_jsx_runtime.JSX.Element;
170
+
171
+ declare const VERSION = "0.1.0";
172
+ declare function createI18nHook<T extends Record<string, any>>(): {
173
+ useTranslations: (namespace?: _intl_party_core.Namespace) => _intl_party_core.TypedTranslationFunction<T>;
174
+ useT: (namespace?: _intl_party_core.Namespace) => _intl_party_core.TypedTranslationFunction<T>;
175
+ };
176
+ declare function createNamespaceHOC(namespace: string): <P extends object>(Component: React.ComponentType<P>) => React.ComponentType<P>;
177
+ declare class I18nErrorBoundary extends React.Component<{
178
+ children: React.ReactNode;
179
+ fallback?: React.ComponentType<{
180
+ error: Error;
181
+ }>;
182
+ onError?: (error: Error, errorInfo: React.ErrorInfo) => void;
183
+ }, {
184
+ hasError: boolean;
185
+ error?: Error;
186
+ }> {
187
+ constructor(props: any);
188
+ static getDerivedStateFromError(error: Error): {
189
+ hasError: boolean;
190
+ error: Error;
191
+ };
192
+ componentDidCatch(error: Error, errorInfo: React.ErrorInfo): void;
193
+ render(): string | number | boolean | Iterable<React.ReactNode> | react_jsx_runtime.JSX.Element | null | undefined;
194
+ }
195
+
196
+ export { AccessibleLocaleSelector, type AccessibleLocaleSelectorProps, CompactLocaleSelector, type CompactLocaleSelectorProps, ConditionalTrans, type ConditionalTransProps, FlagLocaleSelector, type FlagLocaleSelectorProps, type I18nContextValue, I18nErrorBoundary, I18nProvider, type I18nProviderProps, LocaleSelector, type LocaleSelectorProps, PluralTrans, type PluralTransProps, RichTrans, type RichTransProps, ScopedI18nProvider, type ScopedI18nProviderProps, Trans, type TransProps, type TypedI18nContextValue, TypedI18nProvider, type TypedI18nProviderProps, VERSION, type WithI18nProps, createI18nHook, createNamespaceHOC, useBrowserLocale, useDirection, useFormatting, useHasTranslation, useI18nContext, useInterpolatedTranslation, useLocale, useLocaleInfo, useLocalePreference, useLocaleSwitch, useMultipleNamespaces, useMultipleTranslations, useNamespace, useNamespaceInfo, useNamespacePreloading, useNamespaceSwitch, useOptionalTranslation, usePluralization, useScopedTranslations, useT, useTranslationValue, useTranslationWithFallback, useTranslations, useTypedI18nContext, useTypedT, useTypedTranslations, withI18n };
package/dist/index.js CHANGED
@@ -195,6 +195,24 @@ function I18nProvider({
195
195
  function useI18nContext() {
196
196
  const context = (0, import_react.useContext)(I18nContext);
197
197
  if (!context) {
198
+ if (typeof window === "undefined") {
199
+ const fallbackI18n = (0, import_core.createI18n)({
200
+ locales: ["en"],
201
+ defaultLocale: "en",
202
+ namespaces: ["common"]
203
+ });
204
+ return {
205
+ i18n: fallbackI18n,
206
+ locale: "en",
207
+ namespace: "common",
208
+ t: fallbackI18n.t,
209
+ setLocale: () => {
210
+ },
211
+ setNamespace: () => {
212
+ },
213
+ isLoading: false
214
+ };
215
+ }
198
216
  throw new Error("useI18nContext must be used within an I18nProvider");
199
217
  }
200
218
  return context;
@@ -229,6 +247,24 @@ function useTypedI18nContext() {
229
247
  TypedI18nContext
230
248
  );
231
249
  if (!context) {
250
+ if (typeof window === "undefined") {
251
+ const fallbackI18n = (0, import_core.createI18n)({
252
+ locales: ["en"],
253
+ defaultLocale: "en",
254
+ namespaces: ["common"]
255
+ });
256
+ return {
257
+ i18n: fallbackI18n,
258
+ locale: "en",
259
+ namespace: "common",
260
+ t: fallbackI18n.t,
261
+ setLocale: () => {
262
+ },
263
+ setNamespace: () => {
264
+ },
265
+ isLoading: false
266
+ };
267
+ }
232
268
  throw new Error(
233
269
  "useTypedI18nContext must be used within a TypedI18nProvider"
234
270
  );
@@ -816,6 +852,25 @@ function LocaleSelector({
816
852
  locale
817
853
  )) });
818
854
  }
855
+ if (variant === "dropdown") {
856
+ return /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("div", { className, style, children: /* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
857
+ "select",
858
+ {
859
+ value: currentLocale,
860
+ onChange: (e) => handleLocaleChange(e.target.value),
861
+ disabled,
862
+ style: {
863
+ padding: "8px 12px",
864
+ borderRadius: "4px",
865
+ border: "1px solid #ccc",
866
+ backgroundColor: "white",
867
+ fontSize: "14px",
868
+ minWidth: "120px"
869
+ },
870
+ children: filteredLocales.map((locale) => /* @__PURE__ */ (0, import_jsx_runtime3.jsx)("option", { value: locale, children: formatLocaleDisplay(locale) }, locale))
871
+ }
872
+ ) });
873
+ }
819
874
  return null;
820
875
  }
821
876
  function FlagLocaleSelector({
package/dist/index.mjs CHANGED
@@ -129,6 +129,24 @@ function I18nProvider({
129
129
  function useI18nContext() {
130
130
  const context = useContext(I18nContext);
131
131
  if (!context) {
132
+ if (typeof window === "undefined") {
133
+ const fallbackI18n = createI18n({
134
+ locales: ["en"],
135
+ defaultLocale: "en",
136
+ namespaces: ["common"]
137
+ });
138
+ return {
139
+ i18n: fallbackI18n,
140
+ locale: "en",
141
+ namespace: "common",
142
+ t: fallbackI18n.t,
143
+ setLocale: () => {
144
+ },
145
+ setNamespace: () => {
146
+ },
147
+ isLoading: false
148
+ };
149
+ }
132
150
  throw new Error("useI18nContext must be used within an I18nProvider");
133
151
  }
134
152
  return context;
@@ -163,6 +181,24 @@ function useTypedI18nContext() {
163
181
  TypedI18nContext
164
182
  );
165
183
  if (!context) {
184
+ if (typeof window === "undefined") {
185
+ const fallbackI18n = createI18n({
186
+ locales: ["en"],
187
+ defaultLocale: "en",
188
+ namespaces: ["common"]
189
+ });
190
+ return {
191
+ i18n: fallbackI18n,
192
+ locale: "en",
193
+ namespace: "common",
194
+ t: fallbackI18n.t,
195
+ setLocale: () => {
196
+ },
197
+ setNamespace: () => {
198
+ },
199
+ isLoading: false
200
+ };
201
+ }
166
202
  throw new Error(
167
203
  "useTypedI18nContext must be used within a TypedI18nProvider"
168
204
  );
@@ -750,6 +786,25 @@ function LocaleSelector({
750
786
  locale
751
787
  )) });
752
788
  }
789
+ if (variant === "dropdown") {
790
+ return /* @__PURE__ */ jsx3("div", { className, style, children: /* @__PURE__ */ jsx3(
791
+ "select",
792
+ {
793
+ value: currentLocale,
794
+ onChange: (e) => handleLocaleChange(e.target.value),
795
+ disabled,
796
+ style: {
797
+ padding: "8px 12px",
798
+ borderRadius: "4px",
799
+ border: "1px solid #ccc",
800
+ backgroundColor: "white",
801
+ fontSize: "14px",
802
+ minWidth: "120px"
803
+ },
804
+ children: filteredLocales.map((locale) => /* @__PURE__ */ jsx3("option", { value: locale, children: formatLocaleDisplay(locale) }, locale))
805
+ }
806
+ ) });
807
+ }
753
808
  return null;
754
809
  }
755
810
  function FlagLocaleSelector({
@@ -0,0 +1,7 @@
1
+ export { I18nConfig, I18nInstance, Locale, Namespace, TranslationFunction, TranslationKey, TranslationOptions, TranslationValue } from '@intl-party/core';
2
+
3
+ declare function useTranslations(): never;
4
+ declare function useLocale(): never;
5
+ declare function I18nProvider(): never;
6
+
7
+ export { I18nProvider, useLocale, useTranslations };
@@ -0,0 +1,7 @@
1
+ export { I18nConfig, I18nInstance, Locale, Namespace, TranslationFunction, TranslationKey, TranslationOptions, TranslationValue } from '@intl-party/core';
2
+
3
+ declare function useTranslations(): never;
4
+ declare function useLocale(): never;
5
+ declare function I18nProvider(): never;
6
+
7
+ export { I18nProvider, useLocale, useTranslations };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intl-party/react",
3
- "version": "1.1.1",
3
+ "version": "1.1.4",
4
4
  "description": "React integration for IntlParty - hooks, context, and components for type-safe i18n",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",
@@ -8,9 +8,9 @@
8
8
  "exports": {
9
9
  ".": {
10
10
  "react-server": "./dist/server.js",
11
+ "types": "./dist/index.d.ts",
11
12
  "import": "./dist/index.mjs",
12
- "require": "./dist/index.js",
13
- "types": "./dist/index.d.ts"
13
+ "require": "./dist/index.js"
14
14
  }
15
15
  },
16
16
  "files": [
@@ -24,10 +24,14 @@
24
24
  "hooks",
25
25
  "context"
26
26
  ],
27
- "author": "IntlParty Team",
27
+ "author": "RodrigoEspinosa",
28
28
  "license": "MIT",
29
+ "homepage": "https://github.com/RodrigoEspinosa/intl-party#readme",
30
+ "bugs": {
31
+ "url": "https://github.com/RodrigoEspinosa/intl-party/issues"
32
+ },
29
33
  "dependencies": {
30
- "@intl-party/core": "1.0.0"
34
+ "@intl-party/core": "1.2.0"
31
35
  },
32
36
  "devDependencies": {
33
37
  "@testing-library/jest-dom": "^6.1.4",
@@ -49,14 +53,17 @@
49
53
  },
50
54
  "repository": {
51
55
  "type": "git",
52
- "url": "https://github.com/intl-party/intl-party.git",
56
+ "url": "https://github.com/RodrigoEspinosa/intl-party.git",
53
57
  "directory": "packages/react"
54
58
  },
59
+ "engines": {
60
+ "node": ">=18.0.0"
61
+ },
55
62
  "scripts": {
56
- "build": "tsup src/index.tsx src/server.ts --format cjs,esm --external react,react-dom",
63
+ "build": "tsup src/index.tsx src/server.ts --format cjs,esm --dts --external react,react-dom",
57
64
  "dev": "tsup src/index.tsx --format cjs,esm --external react,react-dom --watch",
58
- "test": "vitest",
59
- "test:watch": "vitest --watch",
65
+ "test": "vitest --run",
66
+ "test:watch": "vitest",
60
67
  "lint": "eslint src --ext .ts,.tsx",
61
68
  "typecheck": "tsc --noEmit",
62
69
  "clean": "rm -rf dist"