@ttoss/react-i18n 2.0.13 → 2.0.15

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.
Files changed (3) hide show
  1. package/README.md +621 -51
  2. package/dist/esm/index.js +20 -20
  3. package/package.json +4 -4
package/README.md CHANGED
@@ -1,108 +1,678 @@
1
1
  # @ttoss/react-i18n
2
2
 
3
- **@ttoss/react-i18n** is a library that provides a way to internationalize your React application using ttoss ecosystem.
3
+ **@ttoss/react-i18n** is a React internationalization library built on [FormatJS](https://formatjs.io/) that seamlessly integrates with the ttoss ecosystem. It provides component-level i18n capabilities for translating text elements like buttons, labels, and headings, making your React applications accessible to global audiences.
4
+
5
+ ## Key Features
6
+
7
+ - **FormatJS Integration**: Built on industry-standard FormatJS with full ICU message format support
8
+ - **Dynamic Locale Loading**: Async loading of translation files with automatic caching
9
+ - **TypeScript Support**: Full TypeScript definitions for type-safe internationalization
10
+ - **Developer Experience**: Simple hooks and components for easy integration
11
+ - **ttoss Ecosystem**: Works seamlessly with other ttoss packages and tooling
12
+ - **Performance Optimized**: Efficient message loading and rendering with minimal overhead
13
+
14
+ ## When to Use
15
+
16
+ Choose `@ttoss/react-i18n` for **component-level internationalization** when you need to:
17
+
18
+ - Translate UI text elements (buttons, labels, form fields, notifications)
19
+ - Support multiple languages within React components
20
+ - Implement user language switching functionality
21
+ - Handle pluralization, number formatting, and date localization
22
+
23
+ For **routing-level internationalization** (SEO, CMS content, URL localization), consider Next.js built-in i18n features alongside this library.
4
24
 
5
25
  :::note
6
- You should declare your messages as describe in the [FormatJS](https://formatjs.io/docs/getting-started/message-declaration) documentation.
26
+ Declare your messages following [FormatJS message declaration guidelines](https://formatjs.io/docs/getting-started/message-declaration) for optimal extraction and compilation.
7
27
  :::
8
28
 
9
- ## Get Started
10
-
11
- ### Install @ttoss/react-i18n
29
+ ## Installation
12
30
 
13
31
  ```shell
14
32
  pnpm add @ttoss/react-i18n
15
33
  pnpm add -D @ttoss/i18n-cli
16
34
  ```
17
35
 
18
- To extract and compile your translations, check the [ttoss/i18n-cli](/docs/modules/packages/i18n-cli/) documentation.
36
+ The `@ttoss/i18n-cli` package handles message extraction and compilation. See the [i18n-cli documentation](https://ttoss.dev/docs/modules/packages/i18n-cli/) for complete workflow setup.
19
37
 
20
- ## Examples of use
38
+ ## Quick Start
21
39
 
22
- ### index.tsx
40
+ ### 1. Provider Setup
23
41
 
24
- Import the `I18nProvider` and wrap your application with it. Add to it a function called `loadLocaleData` to load all the translation data.
42
+ Wrap your application with `I18nProvider` and configure locale data loading:
25
43
 
26
- ```tsx title="src/index.tsx"
44
+ ```tsx title="src/main.tsx"
45
+ import React from 'react';
46
+ import ReactDOM from 'react-dom/client';
27
47
  import { I18nProvider, LoadLocaleData } from '@ttoss/react-i18n';
48
+ import App from './App';
28
49
 
29
50
  const loadLocaleData: LoadLocaleData = async (locale) => {
30
51
  switch (locale) {
31
52
  case 'pt-BR':
32
53
  return import('../i18n/compiled/pt-BR.json');
54
+ case 'es':
55
+ return import('../i18n/compiled/es.json');
33
56
  default:
34
57
  return import('../i18n/compiled/en.json');
35
58
  }
36
59
  };
37
60
 
38
- ReactDOM.render(
39
- <I18nProvider
40
- locale={window.navigator.language}
41
- loadLocaleData={loadLocaleData}
42
- >
61
+ ReactDOM.createRoot(document.getElementById('root')!).render(
62
+ <I18nProvider locale={navigator.language} loadLocaleData={loadLocaleData}>
43
63
  <App />
44
- </I18nProvider>,
45
- document.getElementById('root')
64
+ </I18nProvider>
46
65
  );
47
66
  ```
48
67
 
49
- ### App.tsx
68
+ ### 2. Component Usage
50
69
 
51
- Then import the useI18n hook and extract the intl, to get access to the `formatMessage` function and many others (using `defineMessages` is optional).
70
+ Use the `useI18n` hook to access internationalization features:
52
71
 
53
72
  ```tsx title="src/App.tsx"
54
- import { useI18n, defineMessages } from '@ttoss/react-i18n';
73
+ import React, { useState } from 'react';
74
+ import { useI18n } from '@ttoss/react-i18n';
55
75
 
56
- const messages = defineMessages({
57
- myNameIs: {
58
- description: 'My name is',
59
- defaultValue: 'My name is {name}',
60
- },
76
+ export default function App() {
77
+ const { intl, setLocale, locale } = useI18n();
78
+ const [name, setName] = useState('User');
79
+
80
+ const toggleLanguage = () => {
81
+ setLocale(locale === 'en' ? 'pt-BR' : 'en');
82
+ };
83
+
84
+ return (
85
+ <div>
86
+ <h1>
87
+ {intl.formatMessage(
88
+ {
89
+ description: 'Welcome message',
90
+ defaultMessage: 'Welcome, {name}!',
91
+ },
92
+ { name }
93
+ )}
94
+ </h1>
95
+ <input
96
+ value={name}
97
+ onChange={(e) => setName(e.target.value)}
98
+ placeholder="Enter your name"
99
+ />
100
+ <button onClick={toggleLanguage}>
101
+ {intl.formatMessage({
102
+ description: 'Change language button',
103
+ defaultMessage: 'Change Language',
104
+ })}
105
+ </button>
106
+ <p>Current locale: {locale}</p>
107
+ </div>
108
+ );
109
+ }
110
+ ```
111
+
112
+ ## Framework Integration
113
+
114
+ ### Vite Configuration
115
+
116
+ Configure Vite to properly handle message extraction. Choose between Babel or SWC based on your setup:
117
+
118
+ #### Option 1: Using Babel (with @ttoss/config)
119
+
120
+ ```ts title="vite.config.ts"
121
+ import { defineConfig } from 'vite';
122
+ import react from '@vitejs/plugin-react';
123
+ import { babelConfig } from '@ttoss/config';
124
+
125
+ export default defineConfig({
126
+ plugins: [
127
+ react({
128
+ babel: {
129
+ plugins: babelConfig().plugins,
130
+ },
131
+ }),
132
+ ],
133
+ });
134
+ ```
135
+
136
+ #### Option 2: Using Babel (manual configuration)
137
+
138
+ First, install the Babel plugin:
139
+
140
+ ```shell
141
+ pnpm add -D babel-plugin-formatjs
142
+ ```
143
+
144
+ Then configure Vite:
145
+
146
+ ```ts title="vite.config.ts"
147
+ import { defineConfig } from 'vite';
148
+ import react from '@vitejs/plugin-react';
149
+
150
+ export default defineConfig({
151
+ plugins: [
152
+ react({
153
+ babel: {
154
+ plugins: [
155
+ [
156
+ 'formatjs',
157
+ {
158
+ idInterpolationPattern: '[sha512:contenthash:base64:6]',
159
+ ast: true,
160
+ },
161
+ ],
162
+ ],
163
+ },
164
+ }),
165
+ ],
166
+ });
167
+ ```
168
+
169
+ #### Option 3: Using SWC
170
+
171
+ First, install the SWC plugin:
172
+
173
+ ```shell
174
+ pnpm add -D @swc/plugin-formatjs
175
+ ```
176
+
177
+ Then configure Vite with SWC:
178
+
179
+ ```ts title="vite.config.ts"
180
+ import react from '@vitejs/plugin-react-swc';
181
+ import { defineConfig } from 'vite';
182
+
183
+ export default defineConfig({
184
+ plugins: [
185
+ react({
186
+ plugins: [
187
+ [
188
+ '@swc/plugin-formatjs',
189
+ {
190
+ idInterpolationPattern: '[sha512:contenthash:base64:6]',
191
+ ast: true,
192
+ },
193
+ ],
194
+ ],
195
+ }),
196
+ ],
61
197
  });
198
+ ```
199
+
200
+ #### Configuration Options
201
+
202
+ - **`idInterpolationPattern`**: Generates unique, deterministic IDs for messages using content hash
203
+ - **`ast`**: Enables AST-based extraction for better performance and accuracy
204
+
205
+ For more configuration options, see:
206
+
207
+ - [Babel plugin documentation](https://formatjs.github.io/docs/tooling/babel-plugin/)
208
+ - [SWC plugin documentation](https://www.npmjs.com/package/@swc/plugin-formatjs)
209
+
210
+ ### Next.js Setup
211
+
212
+ For Next.js applications, configure the provider in `_app.tsx`:
213
+
214
+ ```tsx title="pages/_app.tsx"
215
+ import { I18nProvider, LoadLocaleData } from '@ttoss/react-i18n';
216
+ import { useRouter } from 'next/router';
217
+ import type { AppProps } from 'next/app';
62
218
 
63
- const App = () => {
64
- const { intl, setLocale } = useI18n();
219
+ const loadLocaleData: LoadLocaleData = async (locale) => {
220
+ switch (locale) {
221
+ case 'pt-BR':
222
+ return import('../../i18n/compiled/pt-BR.json');
223
+ default:
224
+ return import('../../i18n/compiled/en.json');
225
+ }
226
+ };
65
227
 
66
- const [name, setName] = React.useState('Rayza');
228
+ export default function MyApp({ Component, pageProps }: AppProps) {
229
+ const { locale } = useRouter();
67
230
 
68
231
  return (
69
- <div>
70
- <div>
71
- <button onClick={() => setLocale('en-US')}>en-US</button>
232
+ <I18nProvider locale={locale} loadLocaleData={loadLocaleData}>
233
+ <Component {...pageProps} />
234
+ </I18nProvider>
235
+ );
236
+ }
237
+ ```
238
+
239
+ ## Advanced Usage
240
+
241
+ ### FormattedMessage Component
242
+
243
+ Use `FormattedMessage` for declarative message rendering:
72
244
 
73
- <button onClick={() => setLocale('pt-BR')}>pt-BR</button>
74
- </div>
245
+ ```tsx
246
+ import { FormattedMessage } from '@ttoss/react-i18n';
75
247
 
76
- <input value={name} onChange={(e) => setName(e.target.value)} />
248
+ function UserStats({ userCount, lastSeen }) {
249
+ return (
250
+ <div>
251
+ <FormattedMessage
252
+ description="Number of users"
253
+ defaultMessage="{count, plural, =0 {No users} =1 {One user} other {# users}}"
254
+ values={{ count: userCount }}
255
+ />
256
+ <FormattedMessage
257
+ description="Last seen timestamp"
258
+ defaultMessage="Last seen: {timestamp, date, short}"
259
+ values={{ timestamp: lastSeen }}
260
+ />
261
+ </div>
262
+ );
263
+ }
264
+ ```
265
+
266
+ :::warning Library Development
267
+ When creating **reusable libraries** that use this package, prefer `intl.formatMessage` over `FormattedMessage` component. During the build process, `FormattedMessage` gets transformed into JSX syntax like `return /* @__PURE__ */jsx(FormattedMessage, { defaultMessage: "..." })`, which prevents the message extraction tool from properly detecting and generating IDs for the messages.
77
268
 
78
- <h3>{intl.formatMessage(messages.myNameIs, { name })}</h3>
269
+ ```tsx
270
+ // ✅ Good for libraries - extracts correctly
271
+ function MyLibraryComponent() {
272
+ const { intl } = useI18n();
273
+ return (
274
+ <div>
275
+ {intl.formatMessage({
276
+ description: 'Library message',
277
+ defaultMessage: 'This message will be extracted correctly',
278
+ })}
79
279
  </div>
80
280
  );
81
- };
281
+ }
82
282
 
83
- export default App;
283
+ // Avoid in libraries - extraction may fail
284
+ function MyLibraryComponent() {
285
+ return (
286
+ <FormattedMessage
287
+ description="Library message"
288
+ defaultMessage="This may not extract properly in built libraries"
289
+ />
290
+ );
291
+ }
84
292
  ```
85
293
 
86
- ### Configuring Vite
294
+ :::
87
295
 
88
- In order to inject the i18n id's properly on the code, configure the `plugins` section of `vite.config.ts` according to this:
296
+ ### Error Handling
89
297
 
90
- ```ts
91
- import { babelConfig } from '@ttoss/config';
298
+ Handle translation errors gracefully:
92
299
 
93
- export default defineConfig(async () => {
94
- return {
95
- // ...
300
+ ```tsx
301
+ import { I18nProvider } from '@ttoss/react-i18n';
96
302
 
97
- plugins: [
98
- react({
99
- babel: {
100
- plugins: babelConfig().plugins,
303
+ function App() {
304
+ const handleTranslationError = (error: Error) => {
305
+ console.warn('Translation error:', error.message);
306
+ // Log to error tracking service
307
+ };
308
+
309
+ return (
310
+ <I18nProvider
311
+ locale="en"
312
+ loadLocaleData={loadLocaleData}
313
+ onError={handleTranslationError}
314
+ >
315
+ <MyApp />
316
+ </I18nProvider>
317
+ );
318
+ }
319
+ ```
320
+
321
+ ### Rich Text Formatting
322
+
323
+ Format messages with embedded components:
324
+
325
+ ```tsx
326
+ import { useI18n } from '@ttoss/react-i18n';
327
+
328
+ function SignupForm() {
329
+ const { intl } = useI18n();
330
+
331
+ return (
332
+ <p>
333
+ {intl.formatMessage(
334
+ {
335
+ description: 'Terms and conditions',
336
+ defaultMessage:
337
+ 'By signing up, you agree to our {termsLink} and {privacyLink}.',
101
338
  },
102
- }),
103
- ],
339
+ {
340
+ termsLink: <a href="/terms">Terms of Service</a>,
341
+ privacyLink: <a href="/privacy">Privacy Policy</a>,
342
+ }
343
+ )}
344
+ </p>
345
+ );
346
+ }
347
+ ```
348
+
349
+ ### Dynamic Locale Loading
350
+
351
+ Load locales based on user preferences:
352
+
353
+ ```tsx
354
+ import { useI18n } from '@ttoss/react-i18n';
355
+
356
+ function LanguageSelector() {
357
+ const { setLocale, locale } = useI18n();
358
+
359
+ const languages = [
360
+ { code: 'en', name: 'English' },
361
+ { code: 'pt-BR', name: 'Português' },
362
+ { code: 'es', name: 'Español' },
363
+ ];
364
+
365
+ const handleLanguageChange = async (newLocale: string) => {
366
+ // Persist user choice
367
+ localStorage.setItem('preferredLocale', newLocale);
368
+ setLocale(newLocale);
104
369
  };
105
370
 
106
- // ...
371
+ return (
372
+ <select
373
+ value={locale}
374
+ onChange={(e) => handleLanguageChange(e.target.value)}
375
+ >
376
+ {languages.map((lang) => (
377
+ <option key={lang.code} value={lang.code}>
378
+ {lang.name}
379
+ </option>
380
+ ))}
381
+ </select>
382
+ );
383
+ }
384
+ ```
385
+
386
+ ## API Reference
387
+
388
+ ### I18nProvider
389
+
390
+ Main provider component that configures internationalization context.
391
+
392
+ **Props:**
393
+
394
+ - `locale?: string` - Initial locale (defaults to browser language)
395
+ - `loadLocaleData?: LoadLocaleData` - Function to load translation data
396
+ - `onError?: (error: Error) => void` - Error handler for translation issues
397
+ - `children: ReactNode` - Child components
398
+
399
+ ```tsx
400
+ type LoadLocaleData = (locale: string) => Promise<Messages> | Messages;
401
+ type Messages = Record<string, string> | Record<string, MessageFormatElement[]>;
402
+ ```
403
+
404
+ ### useI18n Hook
405
+
406
+ Returns internationalization utilities and state.
407
+
408
+ **Returns:**
409
+
410
+ ```tsx
411
+ {
412
+ intl: IntlShape; // FormatJS intl object
413
+ locale: string; // Current locale
414
+ defaultLocale: string; // Default locale ('en')
415
+ setLocale: (locale: string) => void; // Change locale function
416
+ messages?: Messages; // Current translation messages
417
+ }
418
+ ```
419
+
420
+ **Example:**
421
+
422
+ ```tsx
423
+ const { intl, locale, setLocale } = useI18n();
424
+
425
+ // Format messages
426
+ const greeting = intl.formatMessage({
427
+ description: 'Simple greeting',
428
+ defaultMessage: 'Hello!',
429
+ });
430
+
431
+ // Format with variables
432
+ const welcome = intl.formatMessage(
433
+ {
434
+ description: 'Welcome message with name',
435
+ defaultMessage: 'Welcome, {name}!',
436
+ },
437
+ { name: 'John' }
438
+ );
439
+
440
+ // Format numbers and dates
441
+ const price = intl.formatNumber(29.99, { style: 'currency', currency: 'USD' });
442
+ const date = intl.formatDate(new Date(), { dateStyle: 'medium' });
443
+ ```
444
+
445
+ ### defineMessages / defineMessage
446
+
447
+ Type-safe message definition utilities from FormatJS.
448
+
449
+ ```tsx
450
+ import { defineMessages, defineMessage } from '@ttoss/react-i18n';
451
+
452
+ // Single message (recommended pattern)
453
+ const errorMessage = defineMessage({
454
+ description: 'Generic error message',
455
+ defaultMessage: 'Something went wrong. Please try again.',
456
+ });
457
+
458
+ // Multiple messages (alternative approach)
459
+ const messages = defineMessages({
460
+ title: {
461
+ description: 'Page title',
462
+ defaultMessage: 'My Application',
463
+ },
464
+ subtitle: {
465
+ description: 'Page subtitle',
466
+ defaultMessage: 'Welcome to our platform',
467
+ },
107
468
  });
469
+
470
+ // Usage in component
471
+ function MyComponent() {
472
+ const { intl } = useI18n();
473
+ return <div>{intl.formatMessage(errorMessage)}</div>;
474
+ }
108
475
  ```
476
+
477
+ :::note
478
+ The current ttoss pattern is to define messages inline within components rather than using `defineMessages`. This approach provides better co-location and reduces the need for separate message definitions.
479
+ :::
480
+
481
+ ### FormattedMessage
482
+
483
+ Component for declarative message rendering.
484
+
485
+ **Props:**
486
+
487
+ - `id?: string` - Message ID (auto-generated if using defineMessage)
488
+ - `defaultMessage: string` - Default message text
489
+ - `description?: string` - Message description for translators
490
+ - `values?: Record<string, any>` - Interpolation values
491
+
492
+ ```tsx
493
+ <FormattedMessage
494
+ description="Item count message"
495
+ defaultMessage="You have {count, plural, =0 {no items} =1 {one item} other {# items}}"
496
+ values={{ count: itemCount }}
497
+ />
498
+ ```
499
+
500
+ ## Best Practices
501
+
502
+ ### Message Organization
503
+
504
+ Structure your messages for maintainability:
505
+
506
+ ```tsx
507
+ // Inline messages with components (recommended ttoss pattern)
508
+ function AuthComponent() {
509
+ const { intl } = useI18n();
510
+
511
+ return (
512
+ <div>
513
+ <h1>
514
+ {intl.formatMessage({
515
+ description: 'Login page title',
516
+ defaultMessage: 'Sign In',
517
+ })}
518
+ </h1>
519
+ <button>
520
+ {intl.formatMessage({
521
+ description: 'Login submit button',
522
+ defaultMessage: 'Log In',
523
+ })}
524
+ </button>
525
+ <a href="/forgot-password">
526
+ {intl.formatMessage({
527
+ description: 'Forgot password link',
528
+ defaultMessage: 'Forgot your password?',
529
+ })}
530
+ </a>
531
+ </div>
532
+ );
533
+ }
534
+
535
+ // For reusable messages across components, you can still use defineMessage
536
+ import { defineMessage } from '@ttoss/react-i18n';
537
+
538
+ const successMessage = defineMessage({
539
+ description: 'Success message when user profile is updated',
540
+ defaultMessage: 'Your profile has been successfully updated.',
541
+ });
542
+
543
+ function ProfileForm() {
544
+ const { intl } = useI18n();
545
+
546
+ const handleSuccess = () => {
547
+ toast.success(intl.formatMessage(successMessage));
548
+ };
549
+
550
+ // ... rest of component
551
+ }
552
+ ```
553
+
554
+ ### Performance Optimization
555
+
556
+ Optimize loading and rendering:
557
+
558
+ ```tsx
559
+ // Lazy load locale data to reduce initial bundle size
560
+ const loadLocaleData: LoadLocaleData = async (locale) => {
561
+ const localeModule = await import(`../i18n/compiled/${locale}.json`);
562
+ return localeModule.default;
563
+ };
564
+
565
+ // Use React.memo for components with many translated strings
566
+ const TranslatedComponent = React.memo(function TranslatedComponent({ data }) {
567
+ const { intl } = useI18n();
568
+
569
+ return (
570
+ <div>
571
+ {data.map((item) => (
572
+ <div key={item.id}>
573
+ {intl.formatMessage(
574
+ {
575
+ description: 'Item title in list',
576
+ defaultMessage: 'Title: {title}',
577
+ },
578
+ { title: item.title }
579
+ )}
580
+ </div>
581
+ ))}
582
+ </div>
583
+ );
584
+ });
585
+ ```
586
+
587
+ ### Locale Detection
588
+
589
+ Implement intelligent locale detection:
590
+
591
+ ```tsx
592
+ function getInitialLocale(): string {
593
+ // 1. Check user preference from localStorage
594
+ const saved = localStorage.getItem('preferredLocale');
595
+ if (saved) return saved;
596
+
597
+ // 2. Check URL parameters
598
+ const urlParams = new URLSearchParams(window.location.search);
599
+ const urlLocale = urlParams.get('locale');
600
+ if (urlLocale) return urlLocale;
601
+
602
+ // 3. Use browser language with fallback
603
+ const browserLocale = navigator.language;
604
+ const supportedLocales = ['en', 'pt-BR', 'es'];
605
+
606
+ return supportedLocales.includes(browserLocale) ? browserLocale : 'en';
607
+ }
608
+ ```
609
+
610
+ ## Troubleshooting
611
+
612
+ ### Common Issues
613
+
614
+ **Missing translation warnings:**
615
+
616
+ ```
617
+ MessageError: MISSING_TRANSLATION
618
+ ```
619
+
620
+ - Ensure all locales have corresponding translation files
621
+ - Check that message IDs match between code and translation files
622
+ - Use `onError` prop to handle gracefully
623
+
624
+ **Babel plugin not working:**
625
+
626
+ ```
627
+ Messages not being extracted during build
628
+ ```
629
+
630
+ - Verify `@ttoss/config` babel plugins are configured correctly
631
+ - Check that message definitions use inline `intl.formatMessage` calls
632
+ - Ensure babel configuration is applied to your build process
633
+
634
+ **Locale not switching:**
635
+
636
+ ```
637
+ setLocale called but UI doesn't update
638
+ ```
639
+
640
+ - Verify `loadLocaleData` function returns correct translation data
641
+ - Check browser console for loading errors
642
+ - Ensure `I18nProvider` is at the correct level in component tree
643
+
644
+ ### Development Tips
645
+
646
+ Enable verbose logging during development:
647
+
648
+ ```tsx
649
+ const loadLocaleData: LoadLocaleData = async (locale) => {
650
+ console.log(`Loading locale: ${locale}`);
651
+ try {
652
+ const data = await import(`../i18n/compiled/${locale}.json`);
653
+ console.log(
654
+ `Loaded ${Object.keys(data.default).length} messages for ${locale}`
655
+ );
656
+ return data.default;
657
+ } catch (error) {
658
+ console.error(`Failed to load locale ${locale}:`, error);
659
+ throw error;
660
+ }
661
+ };
662
+ ```
663
+
664
+ ## Related Resources
665
+
666
+ ### ttoss Ecosystem
667
+
668
+ - **[@ttoss/i18n-cli](https://ttoss.dev/docs/modules/packages/i18n-cli/)** - Extract and compile translations using FormatJS workflow
669
+ - **[@ttoss/forms](https://ttoss.dev/docs/modules/packages/forms/)** - Form components with built-in i18n support
670
+ - **[@ttoss/ui](https://ttoss.dev/docs/modules/packages/ui/)** - UI components that work seamlessly with react-i18n
671
+
672
+ ### External Resources
673
+
674
+ - **[FormatJS Documentation](https://formatjs.io/)** - Complete guide to ICU message format and FormatJS features
675
+ - **[ICU Message Format](https://unicode-org.github.io/icu/userguide/format_parse/messages/)** - Specification for message formatting
676
+ - **[Building a Multilingual Blog with Next.js and @ttoss/react-i18n](/blog/building-a-multilingual-blog-site-with-next.js-and-@ttoss-react-i18n)** - Comprehensive tutorial
677
+
678
+ This library enables efficient internationalization following FormatJS standards while integrating seamlessly with the ttoss development ecosystem. For complete workflow setup including message extraction and compilation, see the [@ttoss/i18n-cli documentation](https://ttoss.dev/docs/modules/packages/i18n-cli/).
package/dist/esm/index.js CHANGED
@@ -1,4 +1,9 @@
1
1
  /** Powered by @ttoss/config. https://ttoss.dev/docs/modules/packages/config/ */
2
+ var __defProp = Object.defineProperty;
3
+ var __name = (target, value) => __defProp(target, "name", {
4
+ value,
5
+ configurable: true
6
+ });
2
7
 
3
8
  // src/index.ts
4
9
  import { defineMessages, defineMessage, FormattedMessage } from "react-intl";
@@ -6,16 +11,15 @@ import { defineMessages, defineMessage, FormattedMessage } from "react-intl";
6
11
  // src/i18Provider.tsx
7
12
  import * as React from "react";
8
13
  import { IntlProvider } from "react-intl";
9
- import { Fragment, jsx } from "react/jsx-runtime";
10
14
  var DEFAULT_LOCALE = "en";
11
- var I18nConfigContext = React.createContext({
15
+ var I18nConfigContext = /* @__PURE__ */React.createContext({
12
16
  defaultLocale: DEFAULT_LOCALE,
13
17
  messages: {},
14
- setLocale: () => {
18
+ setLocale: /* @__PURE__ */__name(() => {
15
19
  return null;
16
- }
20
+ }, "setLocale")
17
21
  });
18
- var I18nProvider = ({
22
+ var I18nProvider = /* @__PURE__ */__name(({
19
23
  children,
20
24
  locale: initialLocale,
21
25
  loadLocaleData,
@@ -35,35 +39,31 @@ var I18nProvider = ({
35
39
  });
36
40
  }
37
41
  }, [loadLocaleData, locale]);
38
- return /* @__PURE__ */jsx(I18nConfigContext.Provider, {
42
+ return /* @__PURE__ */React.createElement(I18nConfigContext.Provider, {
39
43
  value: {
40
44
  locale,
41
45
  defaultLocale: DEFAULT_LOCALE,
42
46
  messages: messagesAndLocale.messages,
43
47
  setLocale,
44
48
  ...intlConfig
45
- },
46
- children: /* @__PURE__ */jsx(IntlProvider, {
47
- defaultLocale: DEFAULT_LOCALE,
48
- locale: messagesAndLocale.locale,
49
- messages: messagesAndLocale.messages,
50
- ...intlConfig,
51
- children: /* @__PURE__ */jsx(Fragment, {
52
- children
53
- })
54
- })
55
- });
56
- };
49
+ }
50
+ }, /* @__PURE__ */React.createElement(IntlProvider, {
51
+ defaultLocale: DEFAULT_LOCALE,
52
+ locale: messagesAndLocale.locale,
53
+ messages: messagesAndLocale.messages,
54
+ ...intlConfig
55
+ }, /* @__PURE__ */React.createElement(React.Fragment, null, children)));
56
+ }, "I18nProvider");
57
57
 
58
58
  // src/useI18n.ts
59
59
  import * as React2 from "react";
60
60
  import { useIntl } from "react-intl";
61
- var useI18n = () => {
61
+ var useI18n = /* @__PURE__ */__name(() => {
62
62
  const intl = useIntl();
63
63
  const config = React2.useContext(I18nConfigContext);
64
64
  return {
65
65
  ...config,
66
66
  intl
67
67
  };
68
- };
68
+ }, "useI18n");
69
69
  export { DEFAULT_LOCALE, FormattedMessage, I18nProvider, defineMessage, defineMessages, useI18n };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@ttoss/react-i18n",
3
- "version": "2.0.13",
3
+ "version": "2.0.15",
4
4
  "license": "MIT",
5
5
  "author": "ttoss",
6
6
  "contributors": [
@@ -35,9 +35,9 @@
35
35
  "jest": "^30.0.4",
36
36
  "react": "^19.1.0",
37
37
  "tsup": "^8.5.0",
38
- "@ttoss/config": "^1.35.5",
39
- "@ttoss/i18n-cli": "^0.7.30",
40
- "@ttoss/test-utils": "^2.1.25"
38
+ "@ttoss/i18n-cli": "^0.7.32",
39
+ "@ttoss/test-utils": "^2.1.26",
40
+ "@ttoss/config": "^1.35.6"
41
41
  },
42
42
  "keywords": [
43
43
  "React",