@intl-party/react 1.1.3 → 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 +2 -2
- package/README.md +329 -198
- package/dist/index.js +19 -0
- package/dist/index.mjs +19 -0
- package/package.json +11 -4
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c)
|
|
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
CHANGED
|
@@ -1,31 +1,29 @@
|
|
|
1
1
|
# @intl-party/react
|
|
2
2
|
|
|
3
|
-
React integration for IntlParty
|
|
3
|
+
**React integration for IntlParty with perfect TypeScript support and developer experience.**
|
|
4
4
|
|
|
5
|
-
## Features
|
|
5
|
+
## ✨ Features
|
|
6
6
|
|
|
7
|
-
-
|
|
8
|
-
-
|
|
9
|
-
-
|
|
10
|
-
-
|
|
11
|
-
-
|
|
12
|
-
-
|
|
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
13
|
|
|
14
|
-
##
|
|
14
|
+
## 🚀 Quick Start
|
|
15
|
+
|
|
16
|
+
### Installation
|
|
15
17
|
|
|
16
18
|
```bash
|
|
17
19
|
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
20
|
```
|
|
23
21
|
|
|
24
|
-
|
|
22
|
+
### Basic Usage
|
|
25
23
|
|
|
26
24
|
```tsx
|
|
27
25
|
import React from "react";
|
|
28
|
-
import { I18nProvider, useTranslations
|
|
26
|
+
import { I18nProvider, useTranslations } from "@intl-party/react";
|
|
29
27
|
import { createI18n } from "@intl-party/core";
|
|
30
28
|
|
|
31
29
|
// Create i18n instance
|
|
@@ -35,308 +33,441 @@ const i18n = createI18n({
|
|
|
35
33
|
namespaces: ["common"],
|
|
36
34
|
});
|
|
37
35
|
|
|
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
36
|
function App() {
|
|
50
37
|
return (
|
|
51
38
|
<I18nProvider i18n={i18n}>
|
|
52
|
-
<
|
|
39
|
+
<Welcome />
|
|
53
40
|
</I18nProvider>
|
|
54
41
|
);
|
|
55
42
|
}
|
|
56
43
|
|
|
57
|
-
function
|
|
44
|
+
function Welcome() {
|
|
58
45
|
const t = useTranslations("common");
|
|
59
|
-
const { locale, setLocale } = useLocale();
|
|
60
46
|
|
|
61
47
|
return (
|
|
62
48
|
<div>
|
|
63
49
|
<h1>{t("welcome")}</h1>
|
|
64
|
-
<p>{t("greeting", { interpolation: { name: "
|
|
65
|
-
|
|
66
|
-
<button onClick={() => setLocale("es")}>Español</button>
|
|
67
|
-
<button onClick={() => setLocale("en")}>English</button>
|
|
68
|
-
|
|
69
|
-
<p>Current locale: {locale}</p>
|
|
50
|
+
<p>{t("greeting", { interpolation: { name: "World" } })}</p>
|
|
70
51
|
</div>
|
|
71
52
|
);
|
|
72
53
|
}
|
|
73
54
|
```
|
|
74
55
|
|
|
75
|
-
##
|
|
56
|
+
## 🎯 API Reference
|
|
76
57
|
|
|
77
|
-
###
|
|
58
|
+
### `I18nProvider`
|
|
78
59
|
|
|
79
|
-
|
|
60
|
+
Provides i18n context to the React component tree.
|
|
80
61
|
|
|
81
62
|
```tsx
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
interpolation: { name: "User" },
|
|
93
|
-
count: 5,
|
|
94
|
-
})}
|
|
95
|
-
</p>
|
|
96
|
-
</div>
|
|
97
|
-
);
|
|
98
|
-
}
|
|
63
|
+
<I18nProvider
|
|
64
|
+
i18n={i18nInstance}
|
|
65
|
+
initialLocale="en"
|
|
66
|
+
initialNamespace="common"
|
|
67
|
+
loadingComponent={<Loading />}
|
|
68
|
+
fallbackComponent={<Error />}
|
|
69
|
+
>
|
|
70
|
+
{children}
|
|
71
|
+
</I18nProvider>
|
|
72
|
+
```
|
|
99
73
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
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;
|
|
104
88
|
}
|
|
105
89
|
```
|
|
106
90
|
|
|
107
|
-
###
|
|
91
|
+
### Hooks
|
|
92
|
+
|
|
93
|
+
#### `useTranslations(namespace?)`
|
|
108
94
|
|
|
109
|
-
|
|
95
|
+
Main hook for using translations.
|
|
110
96
|
|
|
111
97
|
```tsx
|
|
112
|
-
|
|
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()`
|
|
113
111
|
|
|
114
|
-
|
|
115
|
-
|
|
112
|
+
Get and set the current locale.
|
|
113
|
+
|
|
114
|
+
```tsx
|
|
115
|
+
function LocaleComponent() {
|
|
116
|
+
const [locale, setLocale] = useLocale();
|
|
116
117
|
|
|
117
118
|
return (
|
|
118
|
-
<
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
))}
|
|
124
|
-
</select>
|
|
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>
|
|
125
124
|
);
|
|
126
125
|
}
|
|
127
126
|
```
|
|
128
127
|
|
|
129
|
-
|
|
128
|
+
#### `useNamespace()`
|
|
130
129
|
|
|
131
|
-
|
|
130
|
+
Get and set the current namespace.
|
|
132
131
|
|
|
133
132
|
```tsx
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
function NamespaceSwitcher() {
|
|
137
|
-
const { namespace, setNamespace, availableNamespaces } = useNamespace();
|
|
133
|
+
function NamespaceComponent() {
|
|
134
|
+
const [namespace, setNamespace] = useNamespace();
|
|
138
135
|
|
|
139
136
|
return (
|
|
140
137
|
<div>
|
|
141
138
|
<p>Current namespace: {namespace}</p>
|
|
142
|
-
{
|
|
143
|
-
|
|
144
|
-
{ns}
|
|
145
|
-
</button>
|
|
146
|
-
))}
|
|
139
|
+
<button onClick={() => setNamespace("navigation")}>Navigation</button>
|
|
140
|
+
<button onClick={() => setNamespace("auth")}>Auth</button>
|
|
147
141
|
</div>
|
|
148
142
|
);
|
|
149
143
|
}
|
|
150
144
|
```
|
|
151
145
|
|
|
152
|
-
|
|
146
|
+
#### `useI18nContext()`
|
|
153
147
|
|
|
154
|
-
Access the full i18n context
|
|
148
|
+
Access the full i18n context.
|
|
155
149
|
|
|
156
150
|
```tsx
|
|
157
|
-
import { useI18nContext } from "@intl-party/react";
|
|
158
|
-
|
|
159
151
|
function AdvancedComponent() {
|
|
160
|
-
const { i18n, locale, namespace } =
|
|
152
|
+
const { i18n, locale, namespace, t, setLocale, setNamespace } =
|
|
153
|
+
useI18nContext();
|
|
161
154
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
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
166
|
}
|
|
167
167
|
```
|
|
168
168
|
|
|
169
|
-
## Components
|
|
169
|
+
## 🧩 Components
|
|
170
170
|
|
|
171
|
-
### Trans
|
|
171
|
+
### `Trans`
|
|
172
172
|
|
|
173
|
-
|
|
173
|
+
Component for translations with rich text and interpolation.
|
|
174
174
|
|
|
175
175
|
```tsx
|
|
176
176
|
import { Trans } from "@intl-party/react";
|
|
177
177
|
|
|
178
|
-
function
|
|
178
|
+
function RichText() {
|
|
179
179
|
return (
|
|
180
180
|
<Trans
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
values={{ name: "John", count: 5 }}
|
|
181
|
+
i18nKey="rich.greeting"
|
|
182
|
+
interpolation={{ name: "John" }}
|
|
184
183
|
components={{
|
|
185
184
|
bold: <strong />,
|
|
186
|
-
link: <a href="/
|
|
185
|
+
link: <a href="/about" />,
|
|
187
186
|
}}
|
|
188
|
-
|
|
187
|
+
>
|
|
188
|
+
Hello <bold>{{ name }}</bold>! Learn more <link>about</link>.
|
|
189
|
+
</Trans>
|
|
189
190
|
);
|
|
190
191
|
}
|
|
191
192
|
```
|
|
192
193
|
|
|
193
|
-
|
|
194
|
+
### `LocaleSelector`
|
|
195
|
+
|
|
196
|
+
Pre-built locale selector component.
|
|
194
197
|
|
|
195
|
-
```
|
|
196
|
-
{
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
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
|
+
);
|
|
200
212
|
}
|
|
201
213
|
```
|
|
202
214
|
|
|
203
|
-
|
|
215
|
+
## 🎨 Advanced Usage
|
|
216
|
+
|
|
217
|
+
### Typed Translations
|
|
204
218
|
|
|
205
|
-
|
|
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
|
|
206
256
|
|
|
207
257
|
```tsx
|
|
208
|
-
|
|
258
|
+
function MultiNamespaceComponent() {
|
|
259
|
+
const commonT = useTranslations("common");
|
|
260
|
+
const authT = useTranslations("auth");
|
|
209
261
|
|
|
210
|
-
function Header() {
|
|
211
262
|
return (
|
|
212
|
-
<
|
|
213
|
-
<h1>
|
|
214
|
-
<
|
|
215
|
-
|
|
216
|
-
showFlags={true}
|
|
217
|
-
onChange={(locale) => console.log("Locale changed to:", locale)}
|
|
218
|
-
/>
|
|
219
|
-
</header>
|
|
263
|
+
<div>
|
|
264
|
+
<h1>{commonT("welcome")}</h1>
|
|
265
|
+
<button>{authT("login")}</button>
|
|
266
|
+
</div>
|
|
220
267
|
);
|
|
221
268
|
}
|
|
222
269
|
```
|
|
223
270
|
|
|
224
|
-
|
|
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
|
+
```
|
|
225
285
|
|
|
226
|
-
###
|
|
286
|
+
### Dynamic Namespace Loading
|
|
227
287
|
|
|
228
288
|
```tsx
|
|
229
|
-
|
|
289
|
+
function DynamicComponent({ namespace }: { namespace: string }) {
|
|
290
|
+
const t = useTranslations(namespace);
|
|
230
291
|
|
|
231
|
-
function App() {
|
|
232
292
|
return (
|
|
233
|
-
<
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
>
|
|
237
|
-
<YourApp />
|
|
238
|
-
</I18nProvider>
|
|
293
|
+
<div>
|
|
294
|
+
<h2>Namespace: {namespace}</h2>
|
|
295
|
+
<p>{t("title")}</p>
|
|
296
|
+
</div>
|
|
239
297
|
);
|
|
240
298
|
}
|
|
241
299
|
```
|
|
242
300
|
|
|
243
|
-
|
|
301
|
+
## 🔧 Utilities
|
|
302
|
+
|
|
303
|
+
### `createNamespaceHOC(namespace)`
|
|
244
304
|
|
|
245
|
-
|
|
305
|
+
Higher-order component for automatic namespacing.
|
|
246
306
|
|
|
247
307
|
```tsx
|
|
248
|
-
|
|
249
|
-
import { createI18n } from "@intl-party/core";
|
|
308
|
+
import { createNamespaceHOC } from "@intl-party/react";
|
|
250
309
|
|
|
251
|
-
|
|
252
|
-
const i18n = createI18n({
|
|
253
|
-
locales: ["en", "es", "fr"],
|
|
254
|
-
defaultLocale: "en",
|
|
255
|
-
namespaces: ["common"],
|
|
256
|
-
});
|
|
310
|
+
const withNavigation = createNamespaceHOC("navigation");
|
|
257
311
|
|
|
258
|
-
|
|
259
|
-
return
|
|
312
|
+
function NavigationComponent({ t }) {
|
|
313
|
+
return (
|
|
314
|
+
<nav>
|
|
315
|
+
<a href="/">{t("home")}</a>
|
|
316
|
+
<a href="/about">{t("about")}</a>
|
|
317
|
+
</nav>
|
|
318
|
+
);
|
|
260
319
|
}
|
|
261
320
|
|
|
262
|
-
|
|
263
|
-
const i18n = createServerI18n(detectedLocale);
|
|
321
|
+
export default withNavigation(NavigationComponent);
|
|
264
322
|
```
|
|
265
323
|
|
|
266
|
-
|
|
324
|
+
### `useMultipleTranslations(namespaces)`
|
|
267
325
|
|
|
268
|
-
|
|
326
|
+
Use multiple namespaces at once.
|
|
269
327
|
|
|
270
328
|
```tsx
|
|
271
|
-
|
|
272
|
-
common
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
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;
|
|
329
|
+
function MultiNamespaceComponent() {
|
|
330
|
+
const { common, auth, navigation } = useMultipleTranslations([
|
|
331
|
+
"common",
|
|
332
|
+
"auth",
|
|
333
|
+
"navigation",
|
|
334
|
+
]);
|
|
291
335
|
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
336
|
+
return (
|
|
337
|
+
<div>
|
|
338
|
+
<h1>{common("welcome")}</h1>
|
|
339
|
+
<button>{auth("login")}</button>
|
|
340
|
+
<nav>{navigation("home")}</nav>
|
|
341
|
+
</div>
|
|
342
|
+
);
|
|
296
343
|
}
|
|
297
344
|
```
|
|
298
345
|
|
|
299
|
-
##
|
|
346
|
+
## 🎨 Styling
|
|
300
347
|
|
|
301
|
-
###
|
|
348
|
+
### Theme Support
|
|
302
349
|
|
|
303
350
|
```tsx
|
|
304
|
-
import {
|
|
305
|
-
|
|
306
|
-
function
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
},
|
|
316
|
-
);
|
|
317
|
-
}, [i18n.locale]);
|
|
318
|
-
|
|
319
|
-
return <div>{t("content")}</div>;
|
|
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
|
+
);
|
|
320
362
|
}
|
|
321
363
|
```
|
|
322
364
|
|
|
323
|
-
### Custom
|
|
365
|
+
### Custom Components
|
|
324
366
|
|
|
325
367
|
```tsx
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
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>
|
|
331
376
|
);
|
|
332
377
|
}
|
|
378
|
+
```
|
|
333
379
|
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
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();
|
|
338
392
|
```
|
|
339
393
|
|
|
340
|
-
|
|
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
|
|
341
472
|
|
|
342
|
-
MIT
|
|
473
|
+
MIT
|
package/dist/index.js
CHANGED
|
@@ -852,6 +852,25 @@ function LocaleSelector({
|
|
|
852
852
|
locale
|
|
853
853
|
)) });
|
|
854
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
|
+
}
|
|
855
874
|
return null;
|
|
856
875
|
}
|
|
857
876
|
function FlagLocaleSelector({
|
package/dist/index.mjs
CHANGED
|
@@ -786,6 +786,25 @@ function LocaleSelector({
|
|
|
786
786
|
locale
|
|
787
787
|
)) });
|
|
788
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
|
+
}
|
|
789
808
|
return null;
|
|
790
809
|
}
|
|
791
810
|
function FlagLocaleSelector({
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intl-party/react",
|
|
3
|
-
"version": "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",
|
|
@@ -24,10 +24,14 @@
|
|
|
24
24
|
"hooks",
|
|
25
25
|
"context"
|
|
26
26
|
],
|
|
27
|
-
"author": "
|
|
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
|
|
34
|
+
"@intl-party/core": "1.2.0"
|
|
31
35
|
},
|
|
32
36
|
"devDependencies": {
|
|
33
37
|
"@testing-library/jest-dom": "^6.1.4",
|
|
@@ -49,9 +53,12 @@
|
|
|
49
53
|
},
|
|
50
54
|
"repository": {
|
|
51
55
|
"type": "git",
|
|
52
|
-
"url": "https://github.com/
|
|
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
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",
|