@intl-party/react 1.1.1 → 1.1.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,342 @@
1
+ # @intl-party/react
2
+
3
+ React integration for IntlParty - hooks, context, and components for type-safe internationalization in React applications.
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
+ - 📱 **SSR support** - Server-side rendering compatible
12
+ - 🎨 **Type safety** - Full TypeScript support with typed hooks
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install @intl-party/react @intl-party/core
18
+ # or
19
+ pnpm add @intl-party/react @intl-party/core
20
+ # or
21
+ yarn add @intl-party/react @intl-party/core
22
+ ```
23
+
24
+ ## Quick Start
25
+
26
+ ```tsx
27
+ import React from "react";
28
+ import { I18nProvider, useTranslations, useLocale } from "@intl-party/react";
29
+ import { createI18n } from "@intl-party/core";
30
+
31
+ // Create i18n instance
32
+ const i18n = createI18n({
33
+ locales: ["en", "es", "fr"],
34
+ defaultLocale: "en",
35
+ namespaces: ["common"],
36
+ });
37
+
38
+ // Add translations
39
+ i18n.addTranslations("en", "common", {
40
+ welcome: "Welcome!",
41
+ greeting: "Hello, {{name}}!",
42
+ });
43
+
44
+ i18n.addTranslations("es", "common", {
45
+ welcome: "¡Bienvenido!",
46
+ greeting: "¡Hola, {{name}}!",
47
+ });
48
+
49
+ function App() {
50
+ return (
51
+ <I18nProvider i18n={i18n}>
52
+ <HomePage />
53
+ </I18nProvider>
54
+ );
55
+ }
56
+
57
+ function HomePage() {
58
+ const t = useTranslations("common");
59
+ const { locale, setLocale } = useLocale();
60
+
61
+ return (
62
+ <div>
63
+ <h1>{t("welcome")}</h1>
64
+ <p>{t("greeting", { interpolation: { name: "John" } })}</p>
65
+
66
+ <button onClick={() => setLocale("es")}>Español</button>
67
+ <button onClick={() => setLocale("en")}>English</button>
68
+
69
+ <p>Current locale: {locale}</p>
70
+ </div>
71
+ );
72
+ }
73
+ ```
74
+
75
+ ## Hooks
76
+
77
+ ### useTranslations
78
+
79
+ Get a translation function for a specific namespace:
80
+
81
+ ```tsx
82
+ import { useTranslations } from "@intl-party/react";
83
+
84
+ function MyComponent() {
85
+ const t = useTranslations("common");
86
+
87
+ return (
88
+ <div>
89
+ <h1>{t("title")}</h1>
90
+ <p>
91
+ {t("description", {
92
+ interpolation: { name: "User" },
93
+ count: 5,
94
+ })}
95
+ </p>
96
+ </div>
97
+ );
98
+ }
99
+
100
+ // With fallback namespace
101
+ function MyComponent() {
102
+ const t = useTranslations(["common", "fallback"]);
103
+ return <h1>{t("title")}</h1>;
104
+ }
105
+ ```
106
+
107
+ ### useLocale
108
+
109
+ Manage the current locale:
110
+
111
+ ```tsx
112
+ import { useLocale } from "@intl-party/react";
113
+
114
+ function LocaleSwitcher() {
115
+ const { locale, setLocale, availableLocales } = useLocale();
116
+
117
+ return (
118
+ <select value={locale} onChange={(e) => setLocale(e.target.value)}>
119
+ {availableLocales.map((loc) => (
120
+ <option key={loc} value={loc}>
121
+ {loc}
122
+ </option>
123
+ ))}
124
+ </select>
125
+ );
126
+ }
127
+ ```
128
+
129
+ ### useNamespace
130
+
131
+ Manage the current namespace:
132
+
133
+ ```tsx
134
+ import { useNamespace } from "@intl-party/react";
135
+
136
+ function NamespaceSwitcher() {
137
+ const { namespace, setNamespace, availableNamespaces } = useNamespace();
138
+
139
+ return (
140
+ <div>
141
+ <p>Current namespace: {namespace}</p>
142
+ {availableNamespaces.map((ns) => (
143
+ <button key={ns} onClick={() => setNamespace(ns)}>
144
+ {ns}
145
+ </button>
146
+ ))}
147
+ </div>
148
+ );
149
+ }
150
+ ```
151
+
152
+ ### useI18nContext
153
+
154
+ Access the full i18n context:
155
+
156
+ ```tsx
157
+ import { useI18nContext } from "@intl-party/react";
158
+
159
+ function AdvancedComponent() {
160
+ const { i18n, locale, namespace } = useI18nContext();
161
+
162
+ // Direct access to i18n instance
163
+ const hasTranslation = i18n.hasTranslation("some.key");
164
+
165
+ return <div>...</div>;
166
+ }
167
+ ```
168
+
169
+ ## Components
170
+
171
+ ### Trans Component
172
+
173
+ Declarative translation with JSX interpolation:
174
+
175
+ ```tsx
176
+ import { Trans } from "@intl-party/react";
177
+
178
+ function MyComponent() {
179
+ return (
180
+ <Trans
181
+ namespace="common"
182
+ i18nKey="welcome.message"
183
+ values={{ name: "John", count: 5 }}
184
+ components={{
185
+ bold: <strong />,
186
+ link: <a href="/profile" />,
187
+ }}
188
+ />
189
+ );
190
+ }
191
+ ```
192
+
193
+ Translation file:
194
+
195
+ ```json
196
+ {
197
+ "welcome": {
198
+ "message": "Hello <bold>{{name}}</bold>! You have <link>{{count}} messages</link>."
199
+ }
200
+ }
201
+ ```
202
+
203
+ ### LocaleSelector Component
204
+
205
+ Pre-built locale selector:
206
+
207
+ ```tsx
208
+ import { LocaleSelector } from "@intl-party/react";
209
+
210
+ function Header() {
211
+ return (
212
+ <header>
213
+ <h1>My App</h1>
214
+ <LocaleSelector
215
+ className="locale-selector"
216
+ showFlags={true}
217
+ onChange={(locale) => console.log("Locale changed to:", locale)}
218
+ />
219
+ </header>
220
+ );
221
+ }
222
+ ```
223
+
224
+ ## Provider Configuration
225
+
226
+ ### I18nProvider
227
+
228
+ ```tsx
229
+ import { I18nProvider } from "@intl-party/react";
230
+
231
+ function App() {
232
+ return (
233
+ <I18nProvider
234
+ i18n={i18nInstance}
235
+ fallback={<div>Loading translations...</div>}
236
+ >
237
+ <YourApp />
238
+ </I18nProvider>
239
+ );
240
+ }
241
+ ```
242
+
243
+ ### Server-Side Rendering
244
+
245
+ For SSR compatibility, initialize with server-detected locale:
246
+
247
+ ```tsx
248
+ // Server-side
249
+ import { createI18n } from "@intl-party/core";
250
+
251
+ function createServerI18n(locale: string) {
252
+ const i18n = createI18n({
253
+ locales: ["en", "es", "fr"],
254
+ defaultLocale: "en",
255
+ namespaces: ["common"],
256
+ });
257
+
258
+ i18n.setLocale(locale);
259
+ return i18n;
260
+ }
261
+
262
+ // In your SSR setup
263
+ const i18n = createServerI18n(detectedLocale);
264
+ ```
265
+
266
+ ## TypeScript Support
267
+
268
+ Create typed hooks for better developer experience:
269
+
270
+ ```tsx
271
+ interface MyTranslations {
272
+ common: {
273
+ welcome: string;
274
+ user: {
275
+ profile: string;
276
+ settings: string;
277
+ };
278
+ };
279
+ navigation: {
280
+ home: string;
281
+ about: string;
282
+ };
283
+ }
284
+
285
+ // Type the hooks
286
+ const useTypedTranslations = useTranslations as <
287
+ T extends keyof MyTranslations,
288
+ >(
289
+ namespace: T,
290
+ ) => (key: string) => string;
291
+
292
+ function TypedComponent() {
293
+ const t = useTypedTranslations("common");
294
+ // Now t() has autocomplete for keys in 'common' namespace
295
+ return <h1>{t("welcome")}</h1>;
296
+ }
297
+ ```
298
+
299
+ ## Advanced Usage
300
+
301
+ ### Dynamic namespace loading
302
+
303
+ ```tsx
304
+ import { useTranslations, useI18nContext } from "@intl-party/react";
305
+
306
+ function DynamicComponent() {
307
+ const { i18n } = useI18nContext();
308
+ const t = useTranslations("dynamic");
309
+
310
+ useEffect(() => {
311
+ // Load translations dynamically
312
+ import(`./translations/${i18n.locale}/dynamic.json`).then(
313
+ (translations) => {
314
+ i18n.addTranslations(i18n.locale, "dynamic", translations.default);
315
+ },
316
+ );
317
+ }, [i18n.locale]);
318
+
319
+ return <div>{t("content")}</div>;
320
+ }
321
+ ```
322
+
323
+ ### Custom hook for scoped translations
324
+
325
+ ```tsx
326
+ function usePageTranslations(page: string) {
327
+ const { i18n } = useI18nContext();
328
+ return useMemo(
329
+ () => i18n.createScopedTranslator(`pages.${page}`),
330
+ [i18n, page],
331
+ );
332
+ }
333
+
334
+ function ContactPage() {
335
+ const t = usePageTranslations("contact");
336
+ return <h1>{t("title")}</h1>; // translates 'pages.contact.title'
337
+ }
338
+ ```
339
+
340
+ ## License
341
+
342
+ MIT © IntlParty
@@ -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
  );
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
  );
@@ -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.3",
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": [
@@ -27,7 +27,7 @@
27
27
  "author": "IntlParty Team",
28
28
  "license": "MIT",
29
29
  "dependencies": {
30
- "@intl-party/core": "1.0.0"
30
+ "@intl-party/core": "1.0.2"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@testing-library/jest-dom": "^6.1.4",
@@ -53,10 +53,10 @@
53
53
  "directory": "packages/react"
54
54
  },
55
55
  "scripts": {
56
- "build": "tsup src/index.tsx src/server.ts --format cjs,esm --external react,react-dom",
56
+ "build": "tsup src/index.tsx src/server.ts --format cjs,esm --dts --external react,react-dom",
57
57
  "dev": "tsup src/index.tsx --format cjs,esm --external react,react-dom --watch",
58
- "test": "vitest",
59
- "test:watch": "vitest --watch",
58
+ "test": "vitest --run",
59
+ "test:watch": "vitest",
60
60
  "lint": "eslint src --ext .ts,.tsx",
61
61
  "typecheck": "tsc --noEmit",
62
62
  "clean": "rm -rf dist"